C Program to copy one binary search tree to another - c

So, here i have come up with Binary search tree prgram, where i am creating 2 binary trees tmp and tmp2, where i am trying to copy whole tmp2 to tmp, the node which is taken as input from user. But i am getting some segmentation fault, also i am not so sure if the logic is right.
Here is the whole program, please lemme know where is it going wrong in t_cpy() or please just fix it for me..
#include<stdio.h>
#include<stdlib.h>
struct node
{
int data;
struct node *rlink;
struct node *llink;
}*tmp=NULL,*tmp2=NULL,*tmp3=NULL;
typedef struct node NODE;
NODE *create();
void inorder(NODE *);
void insert(NODE *);
void t_cpy(NODE *,NODE *);
int main()
{
int n,m;
do
{
printf("\n1.create tree 1\n2.Insert element to tree1\n3.create tree 2\n4.Insert element to tree2\n5.Inorder tree1\n6.Inorder tree2\n7.Copy tree2 to tree1\n8.exit\n\n");
printf("\nEnter ur choice: ");
scanf("%d",&m);
switch(m)
{
case 1: tmp=create();
break;
case 2: insert(tmp);
break;
case 3: tmp2=create();
break;
case 4:
insert(tmp2);
break;
case 5: printf("\n\nInorder Tree1: ");
inorder(tmp);
break;
case 6: printf("\n\nInorder Tree 2: ");
inorder(tmp2);
break;
case 7: t_cpy(tmp,tmp2);
break;
case 8: return(0);
}
}while(n!=8);
return(0);
}
void insert(NODE *root)
{
NODE *newnode;
if(root==NULL)
{
newnode=create();
root=newnode;
}
else
{
newnode=create();
while(1)
{
if(newnode->data<root->data)
{
if(root->llink==NULL)
{
root->llink=newnode;
break;
}
root=root->llink;
}
if(newnode->data>root->data)
{
if(root->rlink==NULL)
{
root->rlink=newnode;
break;
}
root=root->rlink;
}
}
}
}
NODE *create()
{
NODE *newnode;
int n;
newnode=(NODE *)malloc(sizeof(NODE));
printf("\n\nEnter the Data ");
scanf("%d",&n);
newnode->data=n;
newnode->llink=NULL;
newnode->rlink=NULL;
return(newnode);
}
void t_cpy(NODE *t1,NODE *t2)
{
int val,opt=0;
NODE *temp;
if(t1==NULL || t2==NULL)
{
printf("Can not copy !\n");
}
inorder(t1);
printf("\nEnter the node value where tree 2 should be copied\n");
scanf("%d",&val);
temp=t1;
while(temp!=NULL)
{
if(val<temp->data)
temp=temp->llink;
else
temp=temp->rlink;
}
if(temp->llink!=NULL || temp->rlink!=NULL)
printf("Not possible to copy tree to this node\n");
else
{
printf("Copy tree to \n 1.Left Node \n 2.Right Node\n Enter your choice : ");
scanf("%d",&opt);
if(opt==1)
{
temp->llink=t2;
}
else if(opt==2)
{
temp->rlink=t2;
}
else
printf("Invalid choice\n");
}
printf("Tree1 after copying is\n");
inorder(temp);
}
void inorder(NODE *tmp)
{
if(tmp!=NULL)
{
inorder(tmp->llink);
printf("%d",tmp->data);
inorder(tmp->rlink);
}
}
EDIT : Thanks to #xaxxon , who helped me with this.
Just update the while to make it work :
while(temp!=NULL&&temp->data!=val)
{
if(val<temp->data)
temp=temp->llink;
else
temp=temp->rlink;
if(temp->llink==NULL && temp->rlink==NULL && temp->data!=val)
{
printf("Invalid Node value entered !\n");
//break;
return 0;
}
and, Now it works fine for if entered value is present in the tree.
Thanks :)

Among other possible problems, you traverse temp until it is null, and on the next line you dereference it.
while(temp!=NULL)
{
if(val<temp->data)
temp=temp->llink;
else
temp=temp->rlink;
}
if(temp->llink!=NULL || temp->rlink!=NULL)
printf("Not possible to copy tree to this node\n");
You most likely mean to break out of this loop if val == temp->data, but you don't. Also, you still need to check to see if temp is null after the loop in case you didn't find val in your tree. Most likely you just meant to say:
if(temp==NULL)
printf("Not possible to copy tree to this node\n");
Also, you can't ask which side of the found node the user wants to copy a tree to. If you have a binary search tree, it has to be the side where the value should go. If you say to copy it to the right side, but all the values are less than the node, it's no longer a BST. In fact, you can't even ask where the value should go and still have a binary search tree. Each node has to be traversed from the root of the tree you want to put the other tree into to maintain the BST mechanics.

When you first use insert(tmp) the value of tmp does not change after you call insert(). Pass the address of tmp to insert(), using a *root within it instead of root.

Related

Node value changing automatically in C

I'm creating a program for binary search trees and this is a function that I'm using. As seen in the output, the value of
root->rightChild is changing for unknown reasons and the program end without showing any errors.
typedef struct node * BST;
struct node
{
struct node *leftChild;
int data;
struct node *rightChild;
};
BST temp=NULL, ptr=NULL, root=NULL, prev=NULL;
BST newNode()
{
BST X;
X=(BST)malloc(sizeof(BST));
X->leftChild=X->rightChild=NULL;
return X;
}
void createBST(int elem)
{
temp=newNode();
temp->data=elem;
if(!root)
{
root=temp;
printf("\nroot-?rightChild= %p",root->rightChild);
printf("\nroot-?leftChild= %p",root->leftChild);
}
else
{
printf("\nroot-?rightChild= %p",root->rightChild);
printf("\nroot-?leftChild= %p",root->leftChild);
prev=NULL;
ptr=root;
while(ptr!=NULL)
{
prev=ptr;
ptr=(ptr->data<temp->data)?ptr->rightChild:ptr->leftChild;
}
if(prev->data<temp->data)
prev->rightChild=temp;
else
prev->leftChild=temp;
}
}
int main()
{
int choice;
while(1)
{
printf("\nPick a Binary Search Tree operation\n1) Create a Binary Search Tree\n2) Traverse the Binary Search Tree\n3) Seach for a KEY element in the Binary Search Tree\n4) Exit\n>| ");
scanf("%d",&choice);
switch(choice)
{
case 1:
{
int num,elem;
printf("\nEnter the number of elements to be inserted into the Binary Search Tree: ");
scanf("%d",&num);
printf("\nEnter the elements to be inserted into the Binary Search Tree: ");
for(int i=1;i<=num;i++)
{
scanf("%d",&elem);
createBST(elem);
}
}
break;
case 2:
traverBST();
break;
case 3:
searchBST();
break;
case 4:
exitProgram();
break;
default:
printf("\nInvalid Choice\n");
}
}
return 0;
}
This is the output of the code:
This statement has a typo
X=(BST)malloc(sizeof(BST));
^^^
That is the call of malloc allocates a memory for a pointer to node instead of for a node itself.
There must be
X=(BST)malloc(sizeof( *X));
or
X=(BST)malloc(sizeof( struct node ));
As a result of the typo the program has undefined behavior.

Data Structures - Linked list library in C

I'm new to C so I'm seeking help because I'm stuck.
After creating a linked-list library, from which I can add, delete and print all the nodes the user wants, I should add to the program an additional function of integer type and return a -1 if the value doesn't exist inside of the linked-list. If the value does exist inside the linked list, it should return the position of the element.
For example in this linked-list (a -> b -> c -> d -> NULL) if I want to know the position of c it should return me a 3, if I want to know the position of G it should return me -1
This is the program I was able to make until now:
#include <stdio.h>
#include <stdlib.h>
struct ListNode
{
char data;
struct ListNode *nextNode;
};
typedef struct ListNode node;
int main()
{
node *startNodePtr= NULL;
int choice;
char value;
printf("\t\t\tLIST OF CHARACTERS\n");
do
{
printf("\n1.Add New Node \t2.Delete Node \t3.Print Current List \t4.QUIT\n\n");//user friendly interface
scanf("%d",&choice);
switch(choice)
{
case 1: printf("Enter Character: ");
scanf("\n%c",&value);
insertNode(&startNodePtr,value);//calling the function to add a node
break;
case 2: printf("Delete Character: ");
scanf("\n%c",&value);
deleteNode(&startNodePtr,value);//calling the function to remove a node
break;
case 3: printList(startNodePtr);//calling the function to list the nodes
break;
case 4: continue;//if we type 4 it won't show the default answer
default:printf("\t\tINVALID ANSWER! Please type 1. 2. 3. or 4.\n");// in case we type any other character that is not 1, 2, 3 or 4. In this way the program will not crash
break;
}
} while(choice!=4);//keep adding or deleting nodes until we enter 4 which refers to "QUIT"
return 0;
}
void insertNode(node **sPtr, char add)//function to add a node
{
node *newPtr;
node *curPtr;
node *prevPtr;
newPtr=malloc(sizeof(node));
newPtr->data=add;
newPtr->nextNode=NULL;
prevPtr=NULL;
curPtr=*sPtr;
while(curPtr!=NULL)
{
prevPtr=curPtr;
curPtr=curPtr->nextNode;
}
if (prevPtr==NULL)
{
*sPtr=newPtr;
}
else
{
prevPtr->nextNode=newPtr;
}
}
void deleteNode(node **sPtr, char remove)//function to remove a node
{
node *curPtr;
node *prevPtr;
curPtr=*sPtr;
prevPtr=NULL;
if(curPtr->data==remove)
{
*sPtr=curPtr->nextNode;
free(curPtr);
return;
}
while (curPtr!=NULL)
{
if (curPtr->data==remove)
{prevPtr->nextNode=curPtr->nextNode;
free(curPtr);
return;}
else
{prevPtr=curPtr;
curPtr=curPtr->nextNode;}
}
}
void printList(node *sPtr)//function to list the nodes
{
if (sPtr==NULL)
{
printf("The list is empty!\n");
}
else
{
while (sPtr!=NULL)
{
printf("\n%c-->", sPtr->data);
sPtr=sPtr->nextNode;
}
} printf("NULL\n\n");
}
You have basically solved it already, you just have to count the number of iterations until you find the correct element.
int search(struct ListNode *node, char data) {
int position = 1;
// List is empty
if (node == NULL) {
return -1;
}
while (node != NULL) {
if (node->data == data) {
return position;
}
position++;
node = node->nextNode;
}
// Element was not in the list
return -1;
}

Delete function for binary tree

Given the below code what could I use to make a delete function? I have tried multiple things and I keep getting snagged on trying to get it to work. My main problem is trying to delete a node that has a left and right child. For a node that has no children I can just set its parent to point to null and free the node. For one child just set the parent to point to the child and free the node. How would I do it for a node with two children both conceptually and in my code?
#include<stdlib.h>
#include<stdio.h>
struct bin_tree {
int data;
struct bin_tree * right, * left;
} bin_tree;
typedef struct bin_tree node;
void help()//help
{
printf("Options:\n");
printf(" # -Put in any number to add it to the tree if not already there\n");
printf(" s # -Put in s and a number to search the tree for the number\n");
printf(" d # -Delete the number from the tree\n");
printf(" p -Put in p to print the tree\n");
printf(" ? -At any time you can press ? to display the help message\n");
printf(" Q -If you decide the leave the realm of the tree then you can press Q to quit this program\n");
}
int max(int a,int b)//max tree length
{
if(a>b)
return a;
else
return b;
}
int height(node* tree)//height
{
if(tree != NULL)
return(1 + max(height(tree->left),height(tree->right)));
else
return 0;
}
void insert(node ** tree, int val)//insert
{
node *temp = NULL;
if(!(*tree))
{
temp = (node *)malloc(sizeof(node));
temp->left = temp->right = NULL;
temp->data = val;
*tree = temp;
return;
}
if(val < (*tree)->data)
{
insert(&(*tree)->left, val);
}
else if(val > (*tree)->data)
{
insert(&(*tree)->right, val);
}
}
void print(node * tree)//print
{
if (tree)
{
print(tree->left);
printf("[%d] ",tree->data);
print(tree->right);
}
}
node* search(node ** tree, int val)
{//search
if(!(*tree))
{
return NULL;
}
if(val < (*tree)->data)
{
search(&((*tree)->left), val);
}
else if(val > (*tree)->data)
{
search(&((*tree)->right), val);
}
else if(val == (*tree)->data)
{
return *tree;
}
}
void main()
{
node *root;
node *tmp;
int no;
char ch, buff[500];
root = NULL;
printf("Options:\n");
printf(" # -Put in any intiger to add it to the tree if not already there\n");
printf(" s # -Put in s and a number to search the tree for the number\n");
printf(" d # -Delete the number from the tree\n");
printf(" p -Print the tree\n");
printf(" ? -At any time you can press ? to display the help message\n");
printf(" Q -If you decide the leave the realm of the tree then you can press Q to quit this program\n");
while(1){
printf(">");
fgets(buff,499,stdin); //grabs input from user
if(sscanf(buff,"%i",&no)==1){//decides if just a number
tmp = search(&root, no);//looks for number in the tree
if (tmp)
{
printf("Node already in tree!\n", tmp->data);
}
else
{
insert(&root, no);//if not in tree insert it
}
}
else if(sscanf(buff,"%c %i",&ch,&no)>=1)//checks if character
{
switch(ch)
{
case 's'://search for number
{
tmp = search(&root, no);
if (tmp)
{
printf("Node found=%d\n", tmp->data);
}
else
{
printf("Node not found in tree.\n");
}
break;
}
case 'd':
tmp = search(&root, no);
if (tmp)
{
//Call delete function
printf("Node %i deleted", no);
break;
}
else
{
printf("Node not found in tree.\n");
break;
}
case 'Q'://quit
exit(0);
case 'p'://print tree
printf("\n\n");
print(root);
printf("\nHeight= %i\n\n",height(root));
break;
case '?'://display help
help();
break;
default://idiot >.>
printf("Invalid input!\n\n");
help();
break;
}
}
}
return;
}
Either the largest of the nodes to the left or the smallest of the nodes to the right will take it's place!
Simply put one of these where the deleted node was (and delete them from your previous position) and your tree will still be a valid binary search tree. Take a look at this example:
15
/ \
… 25
/ \
20 30
\
23
Suppose you wanted to delete node 25:
By the properties of the binary search tree you already know that all children have to be larger than the parent (15), therefore using one of them instead of the 25 is valid. ✓
If you choose the largest node from the left sub tree (23) it will be larger than any of the nodes to the left, but it also will be smaller than any of the nodes to the right, therefore it fits nicely in the middle and can take the place of the deleted node. ✓
The same is true for the smallest node from the right sub tree (30). ✓
In case the chosen node is a leaf everything is fine and you can delete it. Otherwise perform the delete operation on your chosen node.
You can also take a look at the Wikipedia article of the binary search tree for a pseudocode implementation.

Doubly Linked List Insert After Function

I already posted something similar before but this is another part of a problem that I'm having and I would appreciate your ideas and if you can help me fix my mistake.
As stated on my title i'm building a Doubly Linked List and I would like to know if my function insert_after works or not. When I run the full code I can't insert after the value that I chose which is why I'm posting this. Please let me know if I'm not clear or if this question is wrongly asked. I'm new in C and just need your help understanding.
This is my struct:
struct node
{
char data[100];
struct node *previous; // Points to the previous node
struct node *next; // Points out to the next node
}*head, *last;
This is my function to insert after a the chosen word:
char insert_after(char words[99], char loc[99])
{
struct node *temp, *var, *temp1;
var=(struct node *)malloc(sizeof(struct node));
strncpy(var->data, words,100);
if (head==NULL)
{
head=var;
head->previous=NULL;
head->next=NULL;
}
else
{
temp=head;
while ((temp!=NULL) && (temp->data!=loc))
{
temp=temp->next;
}
if (temp==NULL)
{
printf("\n %s not presented at list\n", loc);
}
else
{
temp1=temp->next;
temp->next=var;
var->previous=temp;
var->next=temp1;
temp1->previous=var;
}
}
last=head;
while (last->next!=NULL)
{
last=last->next;
}
return 0;// take it out after
}
And this is my main: --> Case 3 is my problem
int main()
{
char loc[99];
char words[99];
int i, dat;
head=NULL;
printf("Select the choice of operation on link list");
printf("\n1.) Insert At Begning\n2.) Insert At End\n3.) Insert At Middle");
printf("\n4.) Delete From End\n5.) Reverse The Link List\n6.) Display List\n7.)Exit");
while(1)
{
printf("\n\n Enter the choice of operation you want to do ");
scanf("%d",&i);
switch(i)
{
case 1:
{
printf("Enter a word you want to insert in the 1st node ");
scanf(" %s",words);
insert_beginning(words);
display();
break;
}
case 2:
{
printf("Enter a word you want to insert in the last node ");
scanf(" %s",words);
insert_end(words);
display();
break;
}
case 3:
{
printf("After which data you want to insert your new data ");
scanf(" %s",words);
printf("Enter the data you want to insert in list ");
scanf(" %s",loc);
insert_after(words, loc);
display();
break;
}
I didn't put the full code because it's pretty long which is why i posted the important stuff.
Please let me know if my question is not clear.
Thanks
This is a problem:
while ((temp!=NULL) && (temp->data!=loc))
temp->data != loc is not comparing strings, it just compares pointer addresses.
You could use strcmp or a similar string comparision function. strcmp returns non-zero if
the two parameters differ.
while ((temp!=NULL) && (strcmp(temp->data, words))
Note that it is words that is to compared to the values in the list as words is the value that loc is to be inserted after.
If you use char arrays as the parameters to insert_after function care will be needed to ensure that the entire length of the array is initialised correctly.
Note that a check on the following node is necessary in case there is only one node in the list (the following node will be NULL in this case).
char insert_after(char *words, char *loc)
{
struct node *temp, *var;
var=(struct node *)malloc(sizeof(struct node));
strcpy(var->data, loc);
if (head==NULL)
{
head=var;
head->previous=NULL;
head->next=NULL;
}
else
{
temp=head;
while ((temp!=NULL) && (strcmp(temp->data, words)))
{
temp=temp->next;
}
if (temp==NULL)
{
printf("\n %s not presented at list\n", words);
}
else
{
struct node * followingNode = temp->next;
temp->next=var;
var->previous=temp;
var->next= followingNode;
if (followingNode)
followingNode->previous = var;
}
}
}
Issues
char words[99] has 99 elements but you're allowing up to 100 here, strncpy(var->data, words,100);. That may cause a problem if words is not '\0' terminated. You could unintentially write word[99] to var->data which shouldn't be allowed. Change the statement to this:
strncpy(var->data, words, 99);
var->data[99] = '\0'; // In case words wasn't a string
You cannot compare strings like this, temp->data!=loc. You're actually comparing addresses. Change this line to the following:
while((temp != NULL) && (strcmp(temp->data, loc) != 0));
var->next=temp1 is incorrect. We're at the end of the list so this line should be rewritten as follows:
var->next = NULL;
You must use memcmp or, better yet, strcmp for string comparison instead of !=.

Inorder successor of Threaded Binary Tree

I am writing a c program to create threaded binary tree and then to find INORDER SUCCESSOR of a particular node. For this, i am displaying inorder sequence for the TBT constructed and then asking user to input the node to which successor is to be displayed.. I have written function to do this. But i am not getting successor for the FIRST NODE .. Last node's successor is 0 any ways its working fine.. Can any one help me fix this ?
Here is the whole program :
#include<stdio.h>
#include <stdlib.h>
struct tbtnode {
int data;
struct tbtnode *left,*right;
int lbit,rbit,flag;
int child;
}*root=NULL;
typedef struct tbtnode TBT;
TBT *insuc(TBT *t);
void inorder(TBT *);
void create(TBT *);
void create(TBT *root)
{
int x,op,flag,y;
flag=0;
char ch;
TBT *curr=root;
TBT *q,*p;
do
{
printf("\nCurrent node %d \n\n 1.Left Direction.\n\n2.Right Direction",curr->data);
printf("\nEnter ur choice :");
scanf("%d",&op);
switch(op)
{
case 1: if(curr->lbit==1)
{
printf("Enter left child of %d : ",curr->data);
scanf("%d",&x);
q=(TBT *)malloc(sizeof(TBT));
q->data=x;
q->lbit=q->rbit=1;
q->left=curr->left;
q->right=curr;
curr->left=q;
curr->lbit=0;
q->child=0;
flag=1;
}
else
curr=curr->left;
break;
case 2: if(curr->rbit==1)
{
printf("Enter right child of %d :",curr->data);
scanf("%d",&x);
q=(TBT *)malloc(sizeof(TBT));
q->data=x;
q->lbit=q->rbit=1;
q->left=curr;
q->right=curr->right;
curr->right=q;
curr->rbit=0;
q->child=1;
flag=1;
}
else
curr=curr->right;
break;
}
}while(flag==0);
}
void inorder(TBT *head)
{
TBT *t;
t=head->left;
printf("\n");
while(t->lbit==0)
t=t->left;
while(t!=head)
{
printf(" %d",t->data);
t=insuc(t);
}
}
TBT *insuc(TBT *t)
{
if(t->rbit==0)
{
t=t->right;
while(t->lbit==0)
t=t->left;
return(t);
}
else
return(t->right);
}
void inorder_successor(TBT *head,int x)
{
TBT *t;
t=head->left;
printf("\n");
while(t->lbit==0)
t=t->left;
while(t!=head)
{
t=insuc(t);
if(t->data==x)
{
t=insuc(t);
printf(" %d",t->data);
}
}
}
int main()
{
int op,x,n,i=0,item;
char ch;
TBT *head,*root,*succ; //here head indicates dummy variable
head=(TBT *)malloc(sizeof(TBT));
head->left=head;
head->right=head;
head->lbit=1;
head->rbit=1;
do
{
printf("\n****Threaded binary tree operations****");
printf("\n1)create\n2)inorder\n3)Successor\n4)exit");
printf("\nEnter ur choice: ");
scanf("%d",&op);
switch(op)
{
case 1:
printf("\nEnter Number Of Nodes :");
scanf("%d",&n);
printf("\nEnter root data: ");
scanf("%d",&x);
root=(TBT *)malloc(sizeof(TBT));
root->data=x;
root->lbit=root->rbit=1;
root->child=0;
root->left=head->left;
head->left=root;
head->lbit=0;
root->right=head->right;
for(i=0;i<n-1;i++)
create(root);
break;
case 2:
printf("\nInorder Traversal Is:\n");
inorder(head);
break;
case 3: printf("Enter the node to which successor is to be found\n");
scanf("%d",&item);
inorder_successor(head,item);
break;
case 4:
return(0);
break;
}
}while(op<=4);
return 0;
}
please fix - inorder_successor() function for me..
Thank you
You have many problems with your code. To start with you never check for NULL pointers. To continue, you have both a global and a local variable in main called root.
The last thing means that when you allocate memory for root in main, you allocate for the local variable, and the global variable will still be NULL.
There are also other things that look weird, like you assigning the left and right pointer of head to itself.
I think you need to lay it all out on paper first, both how you have it now and how you want it to be. It will help you to better visualize the tree.

Resources