Reputation: 261
I have a homework which ask from me to create a struct of binary search tree where its node of the binary search tree is another binary search tree. The first BST has the Surnames of Students and the other one has the first names and id. Also if someone has the same surname with another student I must not create another "surname" node but I have to create inside the existing "surname" node another "first name and Id" node. To be more specific:
typedef struct nameANDid{ //name and id nodes
char first[20];
int ID;
struct nameANDid *nleft;
struct nameANDid *nright;
}yohoho;
typedef struct node{ //surname nodes
char last[20];
struct nameANDid yohoho;
struct node *left;
struct node *right;
}node;
My main problem is how to create a different nameANDid node for each firstname I found because with the following code I create 2 BST one for the surnames and another for the names but I would like to be like for example: If I have these students
Stallone Sylvester 11111111
Stallone Noah 22222222
Norris Chuck 33333333
Hogan Hulk 44444444
Hogan Daniel 55555555
I want to store them like this:.........
Stallone Sylvester 11111111
Noah 22222222
Norris Chuck 33333333
Hogan Hulk 44444444
Daniel 55555555
Instead of this I take something like:...........
Stallone Sylvester 11111111.
Noah 22222222
Chuck 33333333
Hulk 44444444
Daniel 55555555
Norris Sylvester 11111111.
Noah 22222222
Chuck 33333333
Hulk 44444444
Daniel 55555555
Hogan Sylvester 11111111.
Noah 22222222
Chuck 33333333
Hulk 44444444
Daniel 55555555
I will put here some functions in order to be more specific
The load function loads the names from a txt document.
void loadData(struct node *temp){
int i;
FILE *fp;
fp=fopen(FILENAME,"r");
if (fp == NULL) printf("File does not exist\n");
for (i=0; i<5; i++){
fscanf(fp,"%s",&temp->last);
fscanf(fp,"%s",&temp->yohoho.first);
fscanf(fp,"%d",&temp->yohoho.ID);
top=add_node(top,temp); //this function create a surname node
}
fclose(fp);
printf("\n\nFile loaded\n");
}
where
struct node temp;//just a node pointer
struct node *top=NULL; //shows the top of the tree
The addnode function is : ...
struct node * add_node (struct node *top, struct node *temp){
struct node *newNode;
if (top == NULL){
newNode=(struct node *)malloc(sizeof(struct node));
temp->left=NULL;
temp->right=NULL;
if (memcpy(newNode,temp,sizeof(struct node)) == NULL){
printf("Node addition failed\n");
return NULL;}
else {
topname=add_node_nameANDid(topname,&temp->yohoho); //Call the add_node_nameANDid to create a new name node in the other tree
return newNode;}
}
else {
if (stricmp(temp->last,top->last) < 0){ //Insert node surname left
top->left=add_node(top->left,temp);}
else if (stricmp(temp->last,top->last) == 0){
topname=add_node_nameANDid(topname,&temp->yohoho); //Call the add_node_nameANDid to create a new name node in the other tree if i have the same surname
}
else {
top->right=add_node(top->right,temp);
}
return top;
}
return NULL;
}
And the add_node_nameANDid() function is like the previous function but it has some variables changed:
struct nameANDid * add_node_nameANDid (struct nameANDid *topname, struct nameANDid *temp2){
struct nameANDid *newNode_nameANDid;
if (topname == NULL){
newNode_nameANDid=(struct nameANDid *)malloc(sizeof(struct nameANDid));
temp2->nleft=NULL;
temp2->nright=NULL;
if (memcpy(newNode_nameANDid,temp2,sizeof(struct nameANDid)) == NULL){
printf("Node addition failed\n");
return NULL;}
else {
return newNode_nameANDid;}
}
else {
if (stricmp(temp2->first,topname->first) <= 0){
topname->nleft=add_node_nameANDid(topname->nleft,temp2);}
else {
topname->nright=add_node_nameANDid(topname->nright,temp2);}
return topname;
}
return NULL;
}
Sorry for the huge source code that I just upload but it would be very difficult to explain without this.
I think that I have two problems but I don't have the knowledge to solve them.
FIRST: I have to create different firstname BST for each surname node and I think that I don't do that but I don't know how to do that...
Any suggestions?
Upvotes: 0
Views: 1321
Reputation: 3509
I have given an example implementation of this below, commented to explain how I approached this. You should be able to use my ideas to modify the way your code works. Note that its not a perfect implementation, off the top of my head, I can see the following problems.
for
/while
loops instead of functions calling themselves - this would allow for as many nodes as your machines memory can handle (fixes the problem).add_name_to_tree
to handle insertions for a balanced binary tree (but this just helps the issue, the stack limit is still there).I will leave it as an exercise for you to handle these situations.
#include <stdio.h>
#include <string.h>
/* a single struct type for storing all tree elements */
typedef struct _node
{
char name[50];
int id;
struct _node *subname;
struct _node *left;
struct _node *right;
} node;
/* creates a new node structure for the specified name and id */
node *create_node(const char *name, int id)
{
node *newNode = (node*)malloc(sizeof(node));
memset(newNode, 0, sizeof(*newNode));
newNode->id = id;
strncpy(newNode->name, name, sizeof(newNode->name));
return newNode;
}
/* inserts the name/id pair into the tree specified by root.
note that root is passed as a pointer to a pointer, so that
it can accept NULL if no tree exists yet, and return to the
caller the node the node that contains the name. Note that
id is ignored if "name" already exists, i'll leave it as an
excersice for you to handle situations with the same name
with multiple id's */
node *add_name_to_tree(node **root, const char *name, int id)
{
if (*root == NULL)
{
*root = create_node(name, id);
return *root;
}
const int cmp = strcmp(name, (*root)->name);
if (cmp < 0)
{
return add_name_to_tree(&(*root)->left, name, id);
}
else if (cmp > 0)
{
return add_name_to_tree(&(*root)->right, name, id);
}
else
{
return *root;
}
}
/* adds the specified first/last name and id combo to the tree
specified by root */
node *add_name(node *root, const char *first, const char *last, int id)
{
/* this call will return the node that holds the last name,
we can then use its "subname" tree root to insert the first name */
node *last_node = add_name_to_tree(&root, last, 0);
/* use the "subname" of the node that stores the last name as the
root of the tree that stores first names */
add_name_to_tree(&last_node->subname, first, id);
return root;
}
/* just to demonstrate why I use the same node type for first/last names,
its because it allows you to support any number of names, see
below - an add function that adds people with a middle name to the tree
*/
node *add_with_middle_name(node *root, const char *first,
const char *middle, const char *last, int id)
{
node *last_node = add_name_to_tree(&root, last, 0);
node *mid_node = add_name_to_tree(&last_node->subname, middle, 0);
add_name_to_tree(&mid_node->subname, first, id);
return root;
}
/* recursively traverse the name tree, printing out the names */
void print_names(node *names, int level)
{
const int indent = 10;
if (names == NULL)
{
printf("\n");
}
if (names->left)
{
print_names(names->left, level);
}
if (names->subname)
{
printf("%*c %s \n", (indent * level), ' ', names->name);
print_names(names->subname, level + 1);
printf("\n");
}
else
{
printf("%*c %-*s %d\n",
(indent * level), ' ',
indent, names->name, names->id);
}
if (names->right)
{
print_names(names->right, level);
}
}
int main()
{
node *names = NULL;
names = add_name(names, "Sylvester", "Stallone", 11111111);
names = add_name(names, "Noah", "Stallone", 22222222);
names = add_name(names, "Chuck", "Norris", 33333333);
names = add_name(names, "Hulk", "Hogan", 44444444);
names = add_name(names, "Daniel", "Hogan", 55555555);
names = add_with_middle_name(names, "Peter", "Michael",
"Zachson", 66666666);
print_names(names, 0);
return 0;
}
Upvotes: 2