Why the address returned by the create function is not same as root for the first node - c

Below is my code for the BST :
insert works fine but search doesnt
typedef struct tree_node{
struct tree_node* parent;
struct tree_node* left;
struct tree_node* right;
int x;
}tree_node;
tree_node *strt=NULL;
tree_node *traverse;
tree_node* create(int info){
tree_node *temp=NULL;
temp=(tree_node*)malloc(sizeof(tree_node));
temp->parent=NULL;
temp->left=NULL;
temp->right=NULL;
temp->x=info;
return temp;
}
tree_node* insert(tree_node *root, int a){
/* here i am printing the address of the node which must be same as the root for the first node */
if(root==NULL){
printf("%d ",create(a));
return create(a);
}
else if(a <= root->x)
return insert(root->left,a);
else
return insert(root->right,a);
return root;
}
tree_node* search_ele(tree_node *root,int info){
if(root==NULL || root->x==info)
return root ;
if(info < root->x)
return search_ele(root->left,info);
else
return search_ele(root->right,info);
}
void display_inorder(tree_node *root){
if(root==NULL)
return;
display_inorder(root->left);
printf("%d ",root->x);
display_inorder(root->right);
}
void main(){
int element;
tree_node *search_element;
while(1){
char ch;
int num;
printf("\nWant to enter a node..??\n\n");
scanf(" %c",&ch);
if(ch=='n'||ch=='N')
break;
else{
printf("Enter the number \n");
scanf("%d",&num);
if(strt==NULL)
printf("Tree is empty...entering first node...!!!\n");
strt=insert(strt,num);
printf("%d",strt);
}
}
printf("Enter the element u want to search\n");
scanf("%d ",&element);
if(search_ele(strt,element)==NULL)
printf("no such element\n");
else
printf("element found\n");
display_inorder(strt);
}
The output displays :
Want to enter a node ?
y
Enter the number
6
Tree is empty...entering first node...!!!
5279480 5279504 (why are these different??)

You print the result of calling create, and then call create again for the return value, thus creating a second node.

First the problems with your BST Algorithm: Your node creation algorithm never attaches new nodes to a parent. Create() sets node->parent to NULL and your insert() never updates the parent variable to root. Additionally, you're never setting the new left/right fields of your new node's parent
Change
return create(a)
to
tree_node * new_node = create(a);
new_node->parent=root;
new_node->parent->left/right=new_node; //include some way to distinguish whether you went left or right in the previous recursive call
return new_node
Now for your address question, you call create() twice, which (think procedurally) results in two malloc() calls, and thus two addresses.

Related

Linked List element insertion at nth location

I am trying to implement linked list in C and I have two different functions that are supposed to insert elements in the beginning and at nth position. My program crashes when it goes to the part where it starts executing the function to insert at nth position. Can someone please point out my mistake. Also the compiler tends to skip the last scanf statement (marked in the comments).
/****************************************************************
*Date: 12/30/2016
*This program adds an element to the beginning and nth position
*of a linked list and then displays the elements in the list
*****************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
struct node
{
int data;//Refers to the data part of the linked list
struct node* next;//Refers to the pointer which points to the next element
};
/*************************************************************************************
Description : This function is used to print the elements in the linked list
Input : Pointer to the beginning of the linked list
Output : N/A
*************************************************************************************/
void PrintElements(struct node *start)
{
if(start==NULL)//If the list is empty
printf("List is empty");
else
{
while(start!=NULL)
{
printf("%d ",start->data);
start=start->next;
}
}
}
/*************************************************************************************
Description : This function is used to insert elements in the beginning of the
linked list
Input : Element to be inserted
Output : N/A
*************************************************************************************/
struct node* InsertElementInTheBeginning(struct node *start, int x)
{
struct node *new_node=(struct node*)malloc(sizeof(struct node));
if(new_node==NULL)
{
printf("Memory allocation failed");
return start;
}
new_node->data=x;
new_node->next=start;
start=new_node;
return new_node;
}
/*************************************************************************************
Description : This function is used to insert elements in the nth position of the
linked list
Input : Element and position to be inserted, pointer to beginning of linked
list
Output : N/A
*************************************************************************************/
struct node* InsertElementAtN(struct node *start,int x, int n)//Here the starting position for the linked list is assumed to be 1
{
int i;
struct node* new_node=(struct node*)malloc(sizeof(struct node));
if(new_node==NULL)
{
printf("Memory allocation failed");
return start;
}
new_node->data=x;
new_node->next=NULL;
if(n==1)
{
new_node->next=start;
start=new_node;
return start;
}
struct node *ptr;
ptr=start;
for(i=0;i<n-2;i++)
{
ptr=ptr->next;
}
new_node->next=ptr->next;
ptr->next=new_node;
return start;
}
int main()
{
int x, n;
struct node *HEAD;
struct node *ptr;
HEAD=NULL; //Assigning HEAD to null when there are no elements in the list
ptr=NULL;
printf("\n\rEnter numbers to be inserted into the list\n Press q to quit\n");
while(scanf("%d",&x)==1)
{
HEAD=InsertElementInTheBeginning(HEAD,x);
PrintElements(HEAD);
printf("\n\rEnter numbers to be inserted into the list\n Press q to quit\n");
}
printf("\n\rEnter the number and position to be inserted");
scanf("%d %d",&x,&n);//The compiler always skips this scanf no clue why
HEAD=InsertElementAtN(HEAD, x, n);
PrintElements(HEAD);
//Freeing dynamic memory
while(HEAD!=NULL)
{
ptr=HEAD;
HEAD=ptr->next;
free(ptr);
}
return 0;
}
I've always found something like this to be easier for me to understand (I'm assuming your positions must be 1 or more based on your code, unlike the usual C convention of 0 or more):
struct node *insertValueAt(struct node *head, int value, int position) {
struct node *current;
if (head == NULL || position == 1)
return insertBefore(head, value);
for (current = head; position > 1 && current->next != NULL; position--)
current = current->next;
current->next = insertBefore(current->next, value);
return head;
}
Note that I used the name insertBefore, but your InsertElementAtTheBeginning does the same thing. The key to inserting a node N between to existing nodes A and B is to make A->next point to N that is returned from InsertElementAtTheBeginning(B, value).
Another thing to note is the unconditional insertion before a NULL node (i.e. at the beginning of an empty list or at the end of the list), regardless of the value of position because you can't insert an item at position 10 if you only have fewer than 4 items.
Add a getchar() after the first while loop in the main(). For explanation please check C: Multiple scanf's, when I enter in a value for one scanf it skips the second scanf.
you should check that ptr->next is not NULL.
for(i=0;i<n-2;i++)
{
if (ptr->next == NULL) return NULL;
ptr=ptr->next;
}

Why passing an argument of structure pointer in a function which creates link list node isn't working?

I'm trying to make link list which represents polynomial.
Each node consists of coefficient,power of x,link to the next node
I have tried this program without passing arguments it worked .
but when when tried passing arguments the link list isn't being created.
pls help to rectify my program..
*****THIS IS MY PROGRAM WITH STRUCTURE POINTERS AS AN
ARGUMENT IN THE INSERT FUNCTION*****
#include<stdio.h>
#include<stdlib.h>
struct node
{
float coff;
int expo;
struct node *next;
};
struct node *start1=NULL,*current1=NULL;
void insert(struct node *start,struct node *current)
{
struct node *new_node;
new_node=(struct node*)malloc(sizeof(struct node));
if(start==NULL)
{
start=new_node;
current=new_node;
}
else
{
current->next=new_node;
current=new_node;
}
printf("\nEnter coefficient:");
scanf("%f",&new_node->coff);
printf("\nEnter power of x:");
scanf("%d",&new_node->expo);
new_node->next=NULL;
}
void show(struct node *start)
{
struct node *ptr;
ptr=start;
while(ptr!=NULL)
{
printf(" %.2fx^%d",ptr->coff,ptr->expo);
ptr=ptr->next;
}
}
void find(float scoff,int sexpo,struct node *start)
{
//scoff=search coefficient, sexpo=search exponent
int flag=0;
struct node *ptr;
ptr=start;
while(ptr!=NULL)
{
if(ptr->coff==scoff && ptr->expo==sexpo)
{
printf("your term found-> %.1fx^%d",ptr->coff,ptr->expo);
flag=1;
break;
}
else
ptr=ptr->next;
}
if(flag==0)
printf("\nSorry term couldn't be found!!");
else
printf("\nSearch success!!");
}
int main()
{
int c=1,ex=0;
float cf=0;
while(1)
{
insert(start1,current1);
printf("\nWant to continue(1/0)?");
scanf("%d",&c);
if(c==0)
break;
}
show(start1);
while(1)
{
printf("\nEnter coff and expo respectively:");
scanf("%f%d",&cf,&ex);
find(cf,ex,start1);
printf("\nWant to continue(1/0)?");
scanf("%d",&c);
if(c==0)
break;
}
return 0;
}
The problem is that you're modifying a local copy of the start and current pointers (i.e. the copies passed as the function arguments), thus not actually changing the linked list. You should instead modify the start1 and current1 pointers. There's no need for the insertion function to take start and current parameters as it can simply modify the global variables. (I should note that this is a bad design choice.)
More specifically, the problem is when initializing the list in
if (start==NULL)
{
start=new_node;
current=new_node;
}
you only modify the local copy that gets destroyed when it goes out of scope. So start1 and current1 are still NULL after the function returns.
Change the insert function to
void insert(struct node *start,struct node *current)
{
struct node *new_node;
new_node=(struct node*)malloc(sizeof(struct node));
if(start1==NULL)
{
start1=new_node; // You previously had start instead of start1
current1=new_node; // You previously had current instead of current1
}
else
{
current1->next=new_node;
current1=new_node;
}
printf("\nEnter coefficient:");
scanf("%f",&new_node->coff);
printf("\nEnter power of x:");
scanf("%d",&new_node->expo);
new_node->next=NULL;
}
Beware: after this modification, you can call insert() (i.e. no need for insert to have parameters) as the function will operate on the global variables. The other option---better, but more time-consuming---is to somehow initialize the linked list and then use the functions in their current form (except for minor modifications).

Single linkedlist creation in C

#include<stdio.h>
#include<stdlib.h>
struct list
{
int a;
int b;
int c;
struct list *next;
};
struct list* addlistele(struct list*,int,int,int);
/* List c element */
void listc()
{
printf(" soon...\n");
}
void printlist(list)
{
struct list* temp;
temp=list;
while(temp!=NULL)
{
printf("a:%d,b;%d,c:%d\n",temp->a,temp->b,temp->c);
temp=temp->next;
}
}
/* List element */
struct list* addlistele(struct list* listadd,int b,int d,int m)
{
int i;
struct list* temp;
struct list* addelement=(struct list*)malloc(sizeof(struct list));
addelement->a=b;
addelement->b=d;
addelement->c=m;
addelement->next=NULL;
if(listadd==NULL)
{
printf("entering");
return addelement;
}
else
{
temp=listadd;
while(temp->next!=NULL)
{
temp=temp->next;
}
temp->next=addelement;
}
return listadd;
}
int main()
{
int ch,i,a,b,c;
struct list *element,*list;
element=(struct list*)malloc(sizeof(struct list));
printf("Choose any one of the option \n");
printf("1.List All \n 2.List c \n");
scanf("%d",&ch);
switch(ch)
{
case 1:printf("Enter values \n");
for(i=0;i<2;i++)
{
scanf("%d %d %d \n",&a,&b,&c);
list=addlistele(element,a,b,c);
}
printlist(list);
break;
case 2:listc(); break;
default:break;
}
}
Hi all, i have written the code like the above one.In that when i gave inputs
> Choose any one of the option
> 1.List All
> 2.List c 1 Enter values 2 3 4 1 2 3
The output is
a:0,b;0,c:0
a:2,b;3,c:4
a:1,b;2,c:3
and also it is not adding the element first i mean it is not entering into this loop
if(listadd==NULL)
{
printf("entering");
return addelement;
}
how to make the head element to be NULL and also i don't know how 0 is coming first.Could anybody can tell me what will be the issue?
In main() you create head element and pass it to the addlistele() function.
element=(struct list*)malloc(sizeof(struct list));
...
list=addlistele(element,a,b,c);
You are seeing this first element which does not have valid values that you expected.
Solution would be you malloc() the element in the function rather than in main() and do not allocate element in main().
replace
struct list *element,*list;
element=(struct list*)malloc(sizeof(struct list));
with
struct list *list=NULL;
then
replace
list=addlistele(element,a,b,c);
with
list=addlistele(list,a,b,c);
Also
replace
void printlist(list)
with
void printlist(struct list *list)
and
replace scanf("%d %d %d \n",&a,&b,&c); with scanf("%d %d %d",&a,&b,&c);

Creating two link list using one function

This is a program to print two link lists using one function.
I have used two functions i.e create and display.Create() is to create the linklist and display() to display the result of linklist.
But this code is printing NULL. I'm not not getting where is the error???
`#include<stdio.h>
#include<conio.h>
struct node
{
int data;
struct node* next;
}
*start=NULL,*start1=NULL;
//to create the linklist
struct node* create(struct node* ptr)
{ int ch;
do
{
struct node* new_node=(struct node*)malloc(sizeof(struct node));
struct node* current;
printf("enter the data\n");
scanf("%d",&new_node->data);
new_node->next=NULL;
if(ptr==NULL)
{
ptr=new_node;
current=new_node;
}
else
{
current->next=new_node;
current=new_node;
}
printf("Do u want to add more ");
scanf("%d",&ch);
}while(ch!=0);
return ptr;
}
//to display the linklist
void display(struct node* temp)
{
while(temp!=NULL)
{
printf("%d--->",temp->data);
temp=temp->next;
}
printf("NULL\n");
}
int main()
{
clrscr();
create(start);
display(start);
printf("\n 2nd linklist\n");
create(start1);
display(start1);
getch();
return 0;
}
First problem
current must be declared outside the do/while loop, otherwise you will get undefined behaviour because there is no guarantee that current will keep it'svalue from one iteration to the next. However with certain compilers you may get away with it.
Second problem
Calling create(start); will not modify start because variables in C are passed by value. You need to write start = create(start);. See also this SO question. In your program start is still NULL after the call to the create function. You could have found out that easily by yourself.

Using Pointer to Pointer of Struct while adding nodes in the binary tree

I want to know the reason why do we use, pointer to pointer while inserting nodes in the binary tree.
But, While traversing the binary tree, we just refer the tree by simple pointer to the root node. But why while inserting node?
Can anyone help me in providing the reason or reference link to understand why it is pointer to pointer .
/*This program clears out all the three methods of traversal */
#include<stdio.h>
#include<stdlib.h>
/* Let us basically describe how a particular node looks in the binary tree .... Every node in the tree has three major elements , left child, right child, and and the data. */
struct TreeNode {
int data;
struct TreeNode *leftChild;
struct TreeNode *rightChild;
};
void inorder(struct TreeNode *bt);
void preorder(struct TreeNode *bt);
void postorder(struct TreeNode *bt);
int insert(struct TreeNode **bt,int num);
main()
{
int num,elements;
struct TreeNode *bt;
int i;
printf("Enter number of elements to be inserted in the tree");
scanf("%d",&num);
printf("Enter the elements to be inserted inside the tree");
for(i=0;i<num;i++)
{
scanf("%d",&elements);
insert(&bt,elements);
printf("\n");
}
printf("In Order Traversal \n");
inorder(bt);
printf("Pre Order Traversal \n");
preorder(bt);
printf("Post Order Traversal \n");
postorder(bt);
return 0;
}
int insert(struct TreeNode **bt,int num)
{
if(*bt==NULL)
{
*bt= malloc(sizeof(struct TreeNode));
(*bt)->leftChild=NULL;
(*bt)->data=num;
(*bt)->rightChild=NULL;
return;
}
else{
/* */
if(num < (*bt)->data)
{
insert(&((*bt)->leftChild),num);
}
else
{
insert(&((*bt)->rightChild),num);
}
}
return;
}
void inorder(struct TreeNode *bt){
if(bt!=NULL){
//Process the left node
inorder(bt->leftChild);
/*print the data of the parent node */
//printf(" %d ", bt->data);
/*process the right node */
inorder(bt->rightChild);
}
}
void preorder(struct TreeNode *bt){
if(bt)
{
//Process the parent node first
printf("%d",bt->data);
//Process the left node.
preorder(bt->leftChild);
//Process the right node.
preorder(bt->rightChild);
}
}
void postorder(struct TreeNode *bt){
if(bt)
{
//process the left child
postorder(bt->leftChild);
//process the right child
postorder(bt->rightChild);
//process the parent node
printf("%d",bt->data);
}
}
"I want to know the reason why do we use, pointer to pointer while inserting nodes in the binary tree. But, While traversing the binary tree, we just refer the tree by simple pointer to the root node. But why while inserting node?"
We actually don't even need the code to answer this. If you want to modify (write to) data in an external function in C, you need to have the address of the data. Just like:
main() {
int x = 2;
change_me(x);
printf("%d\n", x); // prints 2
}
void change_me(int x){
x++;
}
has no meaning. You're (in this example) getting a local copy of the vairable, any changes made to the value are only within the local scope. If you want those changes to propagate back to the calling function you need the address:
main() {
int x = 2;
change_me(&x);
printf("%d\n", x); // prints 3
}
void change_me(int* x){
(*x)++;
}
The same applies to pointers. In the example of a linked list, if I want to print the values, I need to traverse the tree and read data. I don't need to change anything so just the pointer will do. However if I want to modify the tree:
struct node{
int val;
sturct node* next;
};
main() {
struct node* head = malloc(sizeof(struct node));
head->val = 3;
insert_a_node_in_front(head);
}
insert_a_node_in_front(node * ptr) {
struct node* temp = ptr;
ptr = malloc(sizeof(struct node));
ptr->val = 5;
ptr->next = temp;
}
Well, guess what? We didn't actually just insert that node because head's value never changed. It's still pointing to the original node with a val==3. The reason is the same as before, we tried to change the value of the local copy of the parameter. If we want those changes to stick it needs the address of the original copy:
insert_a_node_in_front(&head);
}
insert_a_node_in_front(node ** ptr) {
struct node* temp = (*ptr);
(*ptr) = malloc(sizeof(struct node));
(*ptr)->val = 5;
(*ptr)->next = temp;
}
It's because of the first part of insert where it mallocs a new struct treenode. If you only passed in a struct treenode * this would look something like this:
int insert(struct TreeNode *bt,int num)
{
if(bt==NULL)
{
bt= malloc(sizeof(struct TreeNode));
(bt)->leftChild=NULL;
(bt)->data=num;
(bt)->rightChild=NULL;
return;
}
...
}
The problem with that would be that bt is local to insert so the bt in main would be unchanged. So you pass in a pointer to main's bt, which allows insert to change it.
a very good tips on using pointer is given here :
Try this basics : -
http://www.geeksforgeeks.org/how-to-write-functions-that-modify-the-head-pointer-of-a-linked-list/

Resources