I was trying to print the contents of a trie in C. However I'm not very sucessful. And also let me say right in the beginning that this something we are doing in school right now, and this is one exercise.
This is how my trie looks like:
struct node{
char letter; //holds the letter associated with that node
int count; //its count
struct node* child[26]; //each node can have 26 children
};
struct trie{
struct node* root;
};
This print method has to traverse this trie and print the words in alphabetic order and the ones that have a count of 0 should not be printed.
I was thinking along recursion and this is what my code looks like:
void print(node* root) {
char buffer[15];//array to store the letters
if(root==NULL){ return;}//if the root is null return
int i;
int index=0; //index for the buffer
int hasAChild=hasChild(root);
if (hasAChild != 0) { //the root has children keep on going
for (i=0;i<27;i++) {
//go thru all the children and if they have children call print recursively
if (hasChild(root->child[i])) {
print(root->child[i]);
}
else {
// if they have no more children add the letter to the buffer
buffer[index++] = root->child[i]->letter;
}
// print the contents in the bufffer
printf("%s: %d",root->child[i]->count);
}
}
}
// function to determine if a node has children, if so it returns their number if not,returns 0
int hasChild(root) {
if(root==NULL){
return 0;
}
int i;
int count=0;
for(i=0;i<27;i++){
if(root->child[i]!=NULL){
count++;
}
}
return count;
}
This is what it would look like
Example of a trie:
Root
+--- a:2
| +--- t:4
|
+--- b:3
| +--- e:5
|
+--- c:0
we have 'a' 2 times, 'at' 4 times, 'b' 3 times and 'be' 5 times, only the words should be printed.
In this example I will have to print
at: 4
be: 5
but not c: 0 since its count is 0
So i'm only suppose to print the words that are formed, not the letters that do not form a word. Any help or guidance would be greatly appreciated. Thank you!
I see three issues here:
you append a letter to the current buffer only when the current node has no children. This means that you will only display the last letter of the words.
in addition, every time you enter the function, you start with an empty buffer.
your printf statement is missing a string argument.
You need to pass the length and the buffer, and make sure to null-terminate it correctly.
Related
I was trying to solve GeeksForGeeks problem Size of Binary Tree:
Given a binary tree of size N, you have to count number of nodes in it. For example, count of nodes in below tree is 4.
1
/ \
10 39
/
5
Unfortunately for the test case below I'm getting "incorrect answer" on my recursive code. Can someone tell me where I'm going wrong?
Input:
2 // Number of test cases
1 2 3 // Test Case #1
10 5 9 N 1 3 6 // Test Case #2
My Output:
3
9
Expected Output:
3
6
My Code:
/* Tree node structure used in the program
struct Node
{
int data;
Node* left;
Node* right;
}; */
/* Computes the number of nodes in a tree. */
int nodes=0;
void dfs(Node* node) {
if (node==NULL) return;
++nodes;
// cout << node->data << " ";
dfs(node->left);
dfs(node->right);
}
int getSize(Node* node)
{
// Your code here
dfs(node);
return nodes;
}
The mistake is that your code has a global int nodes that is only initialised once. When getSize is called multiple times, then only at the first call you can be sure it really is zero. All other calls will just keep incrementing that counter without it having been reset.
So either reset that counter just before the call to dfs is made, or -- better -- redesign your code so that you don't need a global counter at all, for example by having dfs return a counter. And if you do that, you can even make getSize recursive itself, without any need of a separate dfs function.
NB: don't use NULL in C++, but nullptr.
Here is a spoiler solution:
int getSize(Node* node) {
if (node==nullptr) return 0;
return 1 + getSize(node->left) + getSize(node->right);
}
i created char array
char Jan1[] = "1,2,3,4";
char Jan2[] = "5,7,3,4";
char Jan3[] = "10,9,3,4";`
the above char arrays i want to use it as shown below in for loop each time it will iterate and print, print is an example i am processing this string further in code, but it is giving error. if instead of yy i use Jan1 then it is printing properly. what is the other way i can use yy as to get print char array as string.
for(int i=1;i<=2;i++)
{
char yy[4];
sprintf(yy,"Jan%d",i);
String presentMonth = String(yy);
Serial.print(presntMonth);
}
So by the comments it seems that what you want is to print the contents of the JanX variable based on an index variable.
Missunderstanding
First of all you need to understand the difference between strings as datatypes and variable names. The former are ways to represent a sequence of characters (used mainly, but not only, to display output messages to any sort of output like a file, a console etc..). The latter are names that you use while coding and they can be whatever you want but they will never appear in the final program.
This for instance creates a String (datatype) named hello which contains the sequence of characters h e l l o.
String hello = "Hello";
Nothing prevents me to assign goodbye to it:
hello = "Goodbye"
Serial.print(hello); // This will print "Goodbye"
In general (apart from very hacky ways) you can't retrieve the name of the variable from your program and have them ready in your executable.
Issue
char Jan1[] = {'1','2','3'};
String yy = "Jan1"
Serial.print(yy); // This will print "Jan1"
To print the items in Jan1 you need to iterate through the values.
void printItems(char* s,int N){
for ( i = 0; i<N; i++ )
{ Serial.print(s[i]); }
}
Since Arduino provides the String class, however, it would be better to do this:
String Jan1 = "1,2,3,4";
Serial.print(Jan1); // This iterates under the hood, takes care of the length, and all the good stuff.
Solution
You want to do something a little more advanced, you want to point to a particular string based on a variable, then print the content of the retrieved string.
I can think of two ways for doing so: by using an list of strings or via a hashmap.
List of strings
String list[] = {"1,2,3,4" , "4,5,6,7", ... };
for(int i = 0; i < sizeof(list)/sizeof(String) ; i++ ){
Serial.print(list[i])
}
Hashmap
The reason I am thinking about this is because you want a string as the "index" that let's you lookup the string, so you can "search" by name. The easiest and quickest method I can think of is to declare an array of structs string_name;string_content and use strcmp to iterate through the array of structs until the needed one is found.
typedef struct{ String name; String content;} element_t;
element_t dict[] = { {"Jan1","1,2,3,4"} , {"Jan2","2,3,4,5"} ... }'
// Note this is not even close to perfect (for instance lacks check if key does not exists)
String lookup(element_t DICT, int DICT_SIZE, String key){
// Iterate through the elements, use strcmp to retrieve it
for(int i = 0; i < DICT_SIZE ; i++ ){
if(strcmp(DICT[i].name,key) {
return DICT[i].content;
}
}
}
// Now create the key, as in your code, and then lookup.
for(int i=1;i<=2;i++)
{
char yy[4];
sprintf(yy,"Jan%d",i);
String presentMonth = lookup(dict,dict_size,yy);
Serial.print(presntMonth);
}
How many different copies of the variable x are there? what are their values when their process finishes?
main (int argc, char ** argv){
int child = fork()
int x = 5;
if (child == 0) {
x += 5;
} else {
child = fork();
x += 10;
if(child) {
x += 5;
}
}
}
I know the answer but can someone help me guid through this?
The fork() function returns 2 times each time is called.
It creates two processes, returning 0 to the father and another value to the child process.
It means that both condititions will be executed.
I don't know if you have framed your question correctly i.e. copies of x (vs no. of address spaces) but here's how fork works:
every time you call this method, 2 address spaces are created for all
the statements below it.
in your case:
after "int child = fork()", 2 address spaces are created and after
"child = fork()", which will only get executed for parent, parent
would further break in 2 address spaces
so the answer is 3
Could someone explain the maxDepth() function, what value is being returned to ldepth and rdepth. How do the values increase for ldepth and rdepth with each recursion, I want to know which values are they storing. ldepth and rdepth were not even initialized with initial values. Do the values increment with every recursive process? I basically want to know the following two steps ldepth=maxDepth(node->left)); and rdepth=maxDepth(node->right));
#include<stdio.h>
#include<stdlib.h>
struct node
{
int data;
struct node *left;
struct node *right;
};
int maxDepth(struct node *node)
{
if(node==NULL)
return 0;
else
{
int ldepth;
int rdepth;
ldepth=maxDepth(node->left));
rdepth=maxDepth(node->right));
if(ldepth>rdepth)
return (ldepth+1);
else return (rdepth+1);
}
}
struct node* newNode(int data)
{
struct node* node=(struct node*)malloc(sizeof(struct node));
node->data=data;
node->left=NULL;
node->right=NULL;
return node;
}
int main()
{
struct node *root=newNode(1);
root->left=newNode(2);
root->right=newNode(3);
root->left->left=newNode(4);
root->left->right=newNode(5);
printf("Height of tree is %d",maxDepth(root));
getchar();
return 0;
}
Do the values increment with every recursive process?
Not exactly. The recursion goes deeper as long as there are child nodes. Once it satisfies 'if(node==NULL)', that is, there are no more leafs, it will return 0 to the calling node. Only then the value is incremented where it reaches 'return (ldepth+1);'
max depth takes root.
root is node, its value is 1.
As a node it has a left and a right node.
the left node of root has also a left and a right node.
so the tree looks like:
1 -> 2 -> 4
| | -> 5
|--> 3
maxDepth takes the element 1
it looks if the parameter is null, since 1 is not null it calls max depth for the left node 2 and the right node 3
lets focus on 2 now
2 is not null so it calls max depth for 4 and 5
lets focus on 4 now
4 is not null so it will call maxdepth for 4's left and right
4's left is NULL so it will return the value 0
now the function that calls the recursion continues (the maxDepth(4))
the value of ldepth is now 0
its increased by one and we fall back to the caller function maxDepth(2)
the depth is increased by 1
etc.
at the end we have the result.
For single linklist
1.1. This is what I saw from a tutorial, I only wrote the important part.
sortedInsert(Node **root, int key){};
int main(){
Node *root = &a;
sortedInsert(&root, 4);
}
1.2. However I just used pointer rather than double pointer, and everything works fine, I can insert the key successfully.
sortedInsert(Node *root, int key){};
int main(){
Node *root = &a;
sortedInsert(root, 4);
}
For binary Tree
2.1. From tutorial(double pointer)
void insert_Tree(Tree **root, int key){
}
int main(){
Tree *root = NULL;
insert_Tree(&root, 10);
}
2.2. what I did is below, and I failed to insert the key, when I checked the node after insertion, the node is still null.(single pointer)
void insert_Tree(Tree *root, int key){
if(root == NULL){
root = (Tree *)malloc(sizeof(Tree));
root->val = key;
root->left = NULL;
root->right = NULL;
cout<<"insert data "<<key<<endl;
}else if(key< root->val){
insert_Tree(root->left, key);
cout<<"go left"<<endl;
}else{
insert_Tree(root->right, key);
cout<<"go right"<<endl;
}
}
int main(){
Tree *root = NULL;
insert_Tree(root, 10);
}
I have a few questions
1). which is right, 1.1/2.1 double pointer or 1.2/2.2 single pointer? Please explain in detail, it could be better if you can show an example, I think both of them are right.
2). Why did I insert key successfully in the linkedlist with single pointer, however I failed in the tree insertion with single pointer?
Thanks very much, I appreciate everyone's help.
I suspect you were lucky with your linked list test. Try inserting something at the head of the list.
To expand on that...
main() has a pointer to the head of the list which it passes by value into your version of sortedInsert(). If sortedInsert() inserts into the middle or end of the list then no problem, the head is not changed and when it returns to main() the head is the same. However, if your version of sortedInsert() has to insert a new head, fine it can do that, but how does it return the information about the new head back to main()? It can't, when it returns to main() main will still be pointing at the old head.
Passing a pointer to main()'s copy of the head pointer allows sortedInsert() to change its value if it has to.
both your approaches are correct.But where you used a single pointer ,your head pointer isn't being updated.All you need to do is return the new head by writing 'return head;' at the end of your function,