I have built a BST that holds album names and years and It constructed according to years.But I want to enter album names and it should give a year.
So I built this code part :
int FindString(treeAlbum *node,char albumTitle[])
{
FindString(node->Left,albumTitle);
FindString(node->Right,albumTitle);
if(!strcpy( node->albumTitle, albumTitle))
{
return node->year;
}
}
And treeAlbum struct
struct treeAlbum{
char albumTitle[100];
int year;
struct treeAlbum *Left;
struct treeAlbum *Right;
}
Finally, This code give an error ( Segmentation Fault). How can I fix this ? Thank You.
My best guess for the segmentation fault is that you aren't checking for your base case.
int FindString(treeAlbum *node,char albumTitle[])
{
if (!node)
{
// Return something sane here
return ERROR_NOT_FOUND;
}
FindString(node->Left,albumTitle);
FindString(node->Right,albumTitle);
if(!strcpy( node->albumTitle, albumTitle))
{
return node->year;
}
}
However, your code has some other issues:
What are you doing with the return values from the recursive calls to FindString. Right now you're not doing anything.
You're using strcpy, but you probably mean strcmp.
You have a binary search tree, but you're doing a post-fix search. This is linear in the size of your tree, but you should be able to use the sorted-ness of the BST to get a log(n) binary tree search. Namely, look at the album at the current node, and see if you're done, should search left, or search right.
The first thing you do in FindString is call FindString again with node->Left. Either node->Left eventually is null (if your tree is correctly constructed) which will cause a segfault or it is an earlier node in the tree (in which case your recursion will cause the stack to fill up). Checking for the null case is certainly required!
You want to use strcmp, not strcpy. You should evaluate the result of two FindString() calls and continue only, when they failed.
Related
I'd just like to note I already saw this post before asking my question: C How to "draw" a Binary Tree to the console
Let's say I have the following tree. If my print function were to print only the numbers (in order traversal), I would have the following printed out: 1,3,4,6,7,8,10,13,14.
What would be the best approach to draw the tree like something below considering the tree gets printed in that order?
I feel that if 8 got printed first followed by 3,10 etc.. it would be easier but since it is in-order traversal 1 is getting printed first which would be the first print statement at the top.
I did this about 2 years ago for some coursework...
I created a node struct that contained its own data and 2 nodes, one left and one right, it looked like this (I couldn't find the final code, that might have used shared pointers):
struct node
{
int data;
node *left;
node *right;
};
I then created my tree by adding more nodes to it using recursion like so:
void insert(node **tree, int value)
{
if (*tree == nullptr)
{
*tree = new node;
(*tree)->data = value;
(*tree)->left = nullptr;
(*tree)->right = nullptr;
}
else if (value < (*tree)->data)
{
insert(&((*tree)->left), value);//memory location of the pointer to the node of the node
}
else if (value > (*tree)->data)
{
insert(&((*tree)->right), value);
}
else
return;
}
Side note: Looking back, I never accounted for adding a node with the same value as an existing node if that's even possible.
I assume you will be doing something similar. Now for the bit that answers your question, printing it out, also using recursion.
void inorder(node *tree)
{
if (!(tree == nullptr))
{
inorder((tree)->left);
cout << (tree->data) << endl;//Prints on new lines, you could comma separate them if you really wanted.
inorder((tree)->right);
}
}
Lastly, you'll want to clean up your tree after you've used it so you'll need to delete it... recursively.
To be honest it's been a while and this recursion thing is still a little confusing to me so I have probably forgotten something, but the theory's there!
Edit, headers used: <iostream> and <memory>, also this was c++ not c but they're very similar.
The question has already been discussed here
Say we don't use the two pointers first and last and simply write
if(*head_ref->next==NULL)
{
p=*head->ref;
return;
}
recursive(&head_ref->next);
p->next-next=p;
p->next=NULL;
This doesn't work, I know it shouldn't, but can't understand why.
First, is there any problem if we pass *head_ref? It does actually change the head, but as we are in recursion, should it cause any problem? Also what should we pass as argument in recursive calling?
The correct code is below I just tried to implement that in a different way and I know it's wrong
struct Node *head;// Declared Global
void Reverse(struct Node *p)
{
if(p->next==NULL)
{
head=p;
return;
}
Reverse(p->next);
p->next->next=p;
p->next=NULL:
}
I have to write a program that reads a .txt file into the tree and then it allows to perform specific operations with it. I'm stuck on the part where I need to sort tree by names and search by name as well, any input would be awesome.
So, my input file is in the format :
3800 Lee, Victor; 2.8
3000 Brown, Joanne; 4.0
So, my binary tree is in the format of:
typedef struct
{
int id;
char name[MAX_NAME_LEN];
float gpa;
} STUDENT;
typedef struct node
{
STUDENT* dataPtr;
struct node* left;
struct node* right;
} NODE;
typedef struct
{
int count;
int (*compare) (void* argu1, void* argu2); // Was provided by teacher, not really sure how this works
NODE* root;
} BST_TREE;
Read file and insert functions are working just fine, but I dont know how to implement search by name(string). Will strcmp work? If so, how would I use it? I have a working search function, but it's optimized to search for id(integer) and it doesn't work with strings.
Here is a part of search function:
/* ===================== _retrieve =====================
Searches tree for node containing requested key
and returns its data to the calling function.
Pre _retrieve passes tree, dataPtr, root
dataPtr is pointer to data structure
containing key to be located
Post tree searched; data pointer returned
Return Address of data in matching node
If not found, NULL returned
*/
static void* _retrieve (BST_TREE* tree,
void* dataPtr, NODE* root)
{
if (root){
if (tree->compare(dataPtr, root->dataPtr) < 0)
return _retrieve(tree, dataPtr, root->left);
else if (tree->compare(dataPtr, root->dataPtr) > 0)
return _retrieve(tree, dataPtr, root->right);
else
// Found equal key
return root;
} // if root
else
// Data not in tree
return NULL;
}// _retrieve
Also, how do I sort the BST? Especially how would I sort it by name which is string and consists of 2 parts (first and last name)? Should I sort it only by the first character? I was thinking of dropping the last name part somehow and making it easier to look only by first names since my teacher didn't really specify how she wants this done. She never told us about sorting BST by non-integer values, therefore I'm lost.
One more thing is that this tree would need to be printed by: level(queue), as indented list and by leaves only.
Example of indented printed list:
1.50
2.70
3.80
3.90
2.60
3.30
I would really appreciate any suggestions on implementing those tasks.
Thank You
No, strcmp() won't work directly, because the comparator is passed two STUDENT * values (disguised as void *. So you will have to write a comparator that unpackages the pointers and then calls strcmp():
int cmp_by_name(const void *v1, const void *v2)
{
const STUDENT *s1 = (STUDENT *)v1;
const STUDENT *s2 = (STUDENT *)v2;
return strcmp(s1->name, s2->name);
}
There will be those who say the casts are not absolutely necessary. There will be those who observe that the variables could be omitted by using slightly more complex expressions in the call to strcmp(). However, if you decide that you need to compare on GPA or ID number too, then having the local variables will be cleaner. The compiler will probably eliminate the variables anyway as a routine optimization, so doing that manually at the cost of clarity is a case of 'premature optimization'.
Because the templates you are working with don't include const in the declaration of the comparator type, you may have to omit const from the function definition line.
You don't need to sort the BST; the data is already stored in a sorted order. You can print it out in sorted order with an in-order traversal of the tree.
You simply set the compare element of the BST_TREE to cmp_by_name:
BST_TREE root = { 0, cmp_by_name, 0 };
You then call your functions with &root as the root of the tree. This is instead of the comparison function you were provided with. You should build and search the tree with a single comparison function; using different comparators at different times will cause chaos.
You don't need to zap the comma if you're using an ISO 8859 code set such as 8859-15, or if you're using Unicode. The comma sorts earlier than any letters, so these names are in order:
Lee, James
Lee, Kirk
Leeds, Shaw
Left, Right
The only time you'd have problems is if the data is not consistent:
Lee James
Lee, Brady
That's the sorted order; you'd probably want the order reversed.
I'm a computer engineering student and I have to write BST as an assignment but the code is not like what everyone written(so far as I search for some example,so I'm desperate now) Here is my code so far(My classroom use C as a main language not C++)
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct bst_node
{
int data;
struct bst_node *right;
struct bst_node *left;
}BST_NODE;
typedef struct bst
{
int size;
BST_NODE *root;
}BST;
void print(BST_NODE *pos)
{
printf("%d(0)",pos->data);
if(pos->left != NULL)
{
printf("%d(L)\n",pos->left->data);
pos=pos->left;
}
if(pos->right != NULL)
{
printf("%d(R)\n",pos->right->data);
pos=pos->right;
}
if(pos->left != NULL)
print(pos->left);
if(pos->right != NULL)
print(pos->right);
}
int main()
{
int number;
BST b;
BST_NODE *pos;
b.root=NULL;
while(1)
{
scanf("%d",&number);
printf("value=%d",number);
if(number<=0)
break;
if(b.root==NULL)
{
b.root=(BST_NODE*)malloc(sizeof(BST_NODE));
pos=b.root;
pos->data=number;
pos->left=NULL;
pos->right=NULL;
}
else
{
pos=b.root;
while(pos)
{
if(number>pos->data)
{
if(pos->right==NULL)
{
pos->right=(BST_NODE*)malloc(sizeof(BST_NODE));
pos->right->left=NULL;
pos->right->right=NULL;
pos->right->data= number;
pos=pos->right;
}
else
{
pos->right->data= number;
pos=pos->right;
}
}
if(number<pos->data)
{
if(pos->left==NULL)
{
pos->left=(BST_NODE*)malloc(sizeof(BST_NODE));
pos->left->left=NULL;
pos->left->right=NULL;
pos->left->data=number;
pos=pos->left;
}
else
{
pos->left->data=number;
pos=pos->left;
}
}
}
}
}
print(b.root);
return 0;
}
I don't know what wrong with this code because it can only receives 2 value then it stops working. The only thing I found out so far to be a problem is while(pos)loop and I try to fix this for week.I would be grateful,if anyone help me solve this problem. Print it out to would be great.
P.S -stop working mean the windows I run program in just freeze or hang.
You want to break out of your while(pos) loop as soon as you malloc a new node. You are done inserting so stop working.
Also you don't want to overwrite all ->data values while traversing the tree in your else branches.
When you add a value to the tree, it looks like you always replace the existing value with the input number instead of just traversing to the next level. Remove
pos->right->data = number;
And
pos->left->data = numbér;
From main()
You also should add an 'else' before the left node check. As it stands, you're checking the right branch and then the left branch every time through the loop. If you check the right branch and make a hit, you'll always check the left branch, too. Probably not a problem, but unnecessary.
Not sure that's the reason 'it stops working' as 'it stops working' is awful darn vague, but that looks suspicious to me.
Additionally...
Be consistent on your indentation. Sometimes the indentation is more spaces than other times
add spaces between struct definitions and Breen function declarations. Think of these things as chapters in a book. Use the whitespace to make separate things clearly separate.
add a prompt within the loop to indicate that it's expecting input. If you think your app has frozen, it may simply be waiting for input
add a check at the start of print() and sensibly handle null roots. This could occur if you type a negative number as your input the first time around. Missing such a check and typing a negative as your first input may crash.
Oh! And use calloc() instead of malloc(). Calloc initializes new memory to nulls, while malloc does not. Malloc just gives you whatever memory it happens to give you, containing whatever random garbage it may contain. If you use calloc, you will have less liklihood of issues with bad memory.
I'm pulling my hair out here. Its been about 1.5 years since I've done any c programming so bear with me.
I need to make a function in c that does what the pwd function does in linux. I have a struct of nodes that represent a folder. Each one has a pointer back to its parent so it should be pretty easy but I'm dying here. I thought I could just keep using strcat to append the name of a nodes parent to the path name. But, even if I was able to get this to work I would be left with a list that is in reverse, which is fine I guess. I could at least deal with that. But if I'm in directory c whose parent is b whose parent is a whose parent is root I should be able to use pwd to output the string "/a/b/c". I'm stuck. Any ideas? When I try to use strcat I get segmentation faults up the ying yang.
void pwd( ){
char *thePath;
NODE *nodePtr;
nodePtr = cwd;
while( nodePtr != root ){
}
printf("%s\n", thePath);
return;
}
If all you want to do is print out the path, this should be pretty easy with recursion.
void pwd_recurse (NODE *nodePtr)
{
if (nodePtr == root)
{
return;
}
pwd_recurse(nodePtr->parent);
printf("/%s",nodePtr->name);
}
void pwd()
{
///however you get the nodePtr;
pwd_recurse(nodePtr);
printf("\n");
}
This nicely sidesteps having to deal with memory allocations (though it does mean if you have a degenerate filesystem with loops (insert obligatory XKCD cartoon here), you'll have a stackoverflow, which is arguable better than an infinite loop.)