Linked list- find_node_data - c

I have previously posted about this same topic. I am self-learning data structures using MIT Open Courseware. I'm doing the 6.S096-Introduction to C/C++ course and attempting the fourth assignment.
It is based on binary search trees and I gave it a try. I wanted to print the values for debugging but kept getting different executions each time.
One time, the cycle doesn't complete and the other time, it goes on to infinity. The debugging block also relates to the other function(find_node_data) I have to complete. So if I can figure what's wrong here, I can easily finish the find_node_data. I have commented a few things to see if it affects anything. What am I doing wrong?
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int node_id;
int data;
struct node* left;
struct node* right;
}node;
///*** DO NOT CHANGE ANY FUNCTION DEFINITIONS ***///
// Declare the tree modification functions below...
node* newNode(int data,int node_id){
node* new_node = (node*) malloc(sizeof(node));
new_node->data = data;
new_node->node_id= node_id;
new_node->right= new_node->left=NULL;
return new_node;
}
node* insert_node(node* root, int node_id, int data) {
if(root==NULL)
return newNode(data,node_id);
else{
node* cur;
if(node_id<root->node_id){
cur=insert_node(root->left,data,node_id);
root->left=cur;
}
else if(node_id>root->node_id){
cur=insert_node(root->right,data,node_id);
root->right=cur;
}
}
return root;
}
// Find the node with node_id, and return its data
/*int find_node_data(node* root, int node_id) {
node* current;
for( current = root->; current->next!=NULL;
current= current->next){
if(current->data == data) return current;
}
return NULL;
}
*/
int main() {
/*
Insert your test code here. Try inserting nodes then searching for them.
When we grade, we will overwrite your main function with our own sequence of
insertions and deletions to test your implementation. If you change the
argument or return types of the binary tree functions, our grading code
won't work!
*/
int T,data,node_id;
printf("Print yo cases");
scanf("%d", &T);
node* root = NULL;
while(T-->0){
printf("Type yo numnums no. %d:",T);
scanf("%d %d",&data,&node_id);
root=insert_node(root,data,node_id);
}
node *lol;
node *king;
for(lol=root;lol->left!=NULL;lol=lol->left){
//for(king=root;king->right!=NULL;king=king->right){
printf("executed!\n");
printf("%d ",lol->node_id);//,king->node_id);
//}
}
return 0;
}

To find the node_data you can use recursion to find the node.
node* find_node_data(node *root, int node_id) {
if (root == NULL)
return NULL;
else if (root->node_id == node_id)
return root;
else {
node *left = find_node_data(root->left, node_id);
return left? left: find_node_data(root->right, node_id);
}
}
And then get the data for the node e.g. get the data for node with node_id 42:
printf("node data %d", find_node_data(root, 42)->data);
Full program below (I can't guarantee its correctness but maybe you can?)
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int node_id;
int data;
struct node *left;
struct node *right;
} node;
///*** DO NOT CHANGE ANY FUNCTION DEFINITIONS ***///
// Declare the tree modification functions below...
node *newNode(int data, int node_id) {
node *new_node = (node *) malloc(sizeof(node));
new_node->data = data;
new_node->node_id = node_id;
new_node->right = new_node->left = NULL;
return new_node;
}
node *insert_node(node *root, int data, int node_id) {
if (root == NULL)
return newNode(data, node_id);
else {
node *cur;
if (node_id < root->node_id) {
cur = insert_node(root->left, data, node_id);
root->left = cur;
}
else if (node_id > root->node_id) {
cur = insert_node(root->right, data, node_id);
root->right = cur;
}
}
return root;
}
// Find the node with node_id, and return its data
/*
int find_node_data_old(node *root, int node_id) {
node *current;
for (current = root->; current->next != NULL;
current = current->next) {
if (current->data == data) return current;
}
return NULL;
}*/
node* find_node_data(node *root, int node_id) {
if (root == NULL)
return NULL;
else if (root->node_id == node_id)
return root;
else {
node *left = find_node_data(root->left, node_id);
return left? left: find_node_data(root->right, node_id);
}
}
void print(node *np) {
if (np) {
print(np->left);
printf("(%d, %d)", np->node_id, np->data);
print(np->right);
}
}
int main() {
/*
Insert your test code here. Try inserting nodes then searching for them.
When we grade, we will overwrite your main function with our own sequence of
insertions and deletions to test your implementation. If you change the
argument or return types of the binary tree functions, our grading code
won't work!
*/
int T, data, node_id;
printf("Print yo cases");
scanf("%d", &T);
node *root = NULL;
while (T-- > 0) {
printf("Type yo numnums no. %d:", T);
scanf("%d %d", &data, &node_id);
root = insert_node(root, data, node_id);
}
node *lol;
node *king;
for (lol = root; lol->left != NULL; lol = lol->left) {
//for(king=root;king->right!=NULL;king=king->right){
printf("executed!\n");
printf("%d ", lol->node_id);//,king->node_id);
//}
}
print(root);
printf("\n");
printf("node data %d", find_node_data(root, 42)->data);
return 0;
}
Test
Print yo cases3
Type yo numnums no. 2:22 42
Type yo numnums no. 1:21 41
Type yo numnums no. 0:20 40
executed!
42 executed!
41 (40, 20)(41, 21)(42, 22)
node data 22
You may also use Jonathan Leffler's improved recursion to find the node:
node *find_node_data2(node *root, int node_id) {
if (root == NULL)
return NULL;
else if (root->node_id == node_id)
return root;
else if (root->node_id > node_id)
return find_node_data(root->left, node_id);
else
return find_node_data(root->right, node_id);
}
Both functions return the correct values as seen in the second test.
int main() {
/*
Insert your test code here. Try inserting nodes then searching for them.
When we grade, we will overwrite your main function with our own sequence of
insertions and deletions to test your implementation. If you change the
argument or return types of the binary tree functions, our grading code
won't work!
*/
int T, data, node_id;
printf("Print yo cases");
scanf("%d", &T);
node *root = NULL;
while (T-- > 0) {
printf("Type yo numnums no. %d:", T);
scanf("%d %d", &data, &node_id);
root = insert_node(root, data, node_id);
}
node *lol;
node *king;
for (lol = root; lol->left != NULL; lol = lol->left) {
//for(king=root;king->right!=NULL;king=king->right){
printf("executed!\n");
printf("%d ", lol->node_id);//,king->node_id);
//}
}
print(root);
printf("\n");
printf("node data %d\n", find_node_data(root, 42)->data);
printf("node data find_node_data2 %d", find_node_data2(root, 42)->data);
return 0;
}
Test 2
Print yo cases3
Type yo numnums no. 2:11 12
Type yo numnums no. 1:13 14
Type yo numnums no. 0:20 42
(12, 11)(14, 13)(42, 20)
node data 20
node data find_node_data2 20

Related

Printing linked list structure C

So, recently I had to create a linked list structure and I think got a function of creating it to work (hopefully), but now I have such simple problem as printing it into the console. I dont know whether there is something wrong with my structure that I created, or I do something wrong with printing. I would appreciate if somebody could find what is wrong with my code:
struct z { int a; struct z *next; };
struct z *head, *node, *next;
int data, x = 1;
int CreateList() {
printf("Enter 0 to end\n");
printf("Enter data no. %d: ", x);
x++;
scanf("%d", &data);
if (data == 0) return 0;
head = (struct z *)malloc(sizeof(struct z));
if (head == NULL) { printf("Error creating head"); return 0; }
node = head;
node->a = data;
node->next = NULL;
while (data) {
next = (struct z *)malloc(sizeof(struct z));
if (next == NULL) { printf("Error creating next node no. %d", x); return 0;}
node = next;
printf("Enter data no. %d: ", x);
x++;
scanf("%d", &data);
node->a = data;
node->next = NULL;
}
return 0;
}
int main() {
CreateList();
node = head;
while (node != NULL) {
printf("%d ", node->a);
node = node->next; //<=== crash on this line
}
return 0;
}
My output is always just the first entered int and then it all crashes on the marked line.
Your main loop uses the wrong variable:
int main(){
CreateList();
node = head;
while (next != NULL) {
printf("%d ", node->a);
node = node->next; //<=== crash on this line
}
return 0;
}
You should instead use node:
int main(){
CreateList();
node = head;
while (node != NULL) {
printf("%d ", node->a);
node = node->next; //<=== crash on this line
}
return 0;
}
Incidentally, head, node and next should be local variables, and head should be returned by CreateList().
CreateList() does not actually create the list correctly: nodes are not linked to the list as they are created, only the first node is stored in head.
Here is a corrected version that returns the list and the corresponding main function:
struct z { int a; struct z *next; };
struct z *CreateList(void) {
struct z *head, *node, *next;
int data, x = 1;
printf("Enter 0 to end\n");
printf("Enter data no. %d: ", x);
x++;
if (scanf("%d", &data) != 1 || data == 0)
return NULL;
head = malloc(sizeof(struct z));
if (head == NULL) {
printf("Error creating head");
return NULL;
}
node = head;
node->a = data;
node->next = NULL;
for (;;) {
printf("Enter data no. %d: ", x);
x++;
if (scanf("%d", &data) != 1 || data == 0)
break;
next = malloc(sizeof(struct z));
if (next == NULL) {
printf("Error creating next node no. %d", x - 1);
return NULL;
}
node->next = next;
node = next;
node->a = data;
node->next = NULL;
}
return head;
}
int main(void) {
struct z *head = CreateList();
struct z *node;
for (node = head; node != NULL; node = node->next) {
printf("%d ", node->a);
}
printf("\n");
return 0;
}
I think your problem is the global variables. Make them in the function, at least the node and the next. Create these on demand, for when you are actually adding the values. As a final tip, for this case, a do-while loop would make your code look cleaner than what it is right now, definitely you'd have less code repeat.

How to search a binary tree for a match with the given value x?

This is my code,here I need to search a binary tree with the value x of type integer and need to return a pointer window of type BTREE of matching node.
Here programmes run into the case2,but still not searching for the node.I couldn't find my mistake.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct tree
{
int data;
struct tree *left;
struct tree *right;
}tree;
int AddToArray(tree *node, int arr[], int i);
tree *CreateNode(int data);
tree *Insert(tree *node, int data);
void PrintPreorder(tree *node);
int count(tree *node);
int compare(const void * a, const void * b);
//-------------------------------------------------------------------------------------------------
int main()
{
int i;
int choice;
int num;
int count;
int size;
int *arr=NULL;
tree *root=NULL;
while (1)
{
printf("enter your choice \n 1.Insert into tree \n");
printf("enter your choice \n 2.search element \n");
scanf("%d",&choice);
switch (choice)
{
case 1:
printf("Enter the input : \n");
scanf("%d",&num);
root = Insert(root, 4);
root = Insert(root, 3);
root = Insert(root, 5);
root = Insert(root, 10);
root = Insert (root, 8);
root = Insert (root, 7);
root = Insert(root,num);
break;
case 2:
printf("\n enter the element to be searched");
scanf("%d",&num);
for(i=0;i<100;i++)
{
if(arr[i]==num) {
printf("\n element found");
break;
}
}
if(i==count)
printf("\n element not found");
break;
}
printf("\n***BINARY TREE (PREORDER)***\n");
PrintPreorder(root);
}
}
/*intf("\n\n***ARRAY***\n");
arr = calloc(size, sizeof(int));
AddToArray(root, arr, 0);
qsort(arr,size,sizeof(int),compare);
for (i=0; i<size; i++)
{
printf("arr[%d]: %d\n", i, arr[i]);
}*/
//-------------------------------------------------------------------------------------------------
int compare(const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
int AddToArray(tree *node, int arr[], int i)
{
if(node == NULL)
return i;
arr[i] = node->data;
i++;
if(node->left != NULL)
AddToArray(node->left, arr, i);
if(node->right != NULL)
AddToArray(node->right, arr, i);
arr[i] = node->data;
i++;
}
tree *CreateNode(int data)
{
tree *node = (tree *)malloc(sizeof(tree));
node -> data = data;
node -> left = node -> right = NULL;
return node;
}
tree *Insert(tree *node, int data)
{
if(node==NULL)
{
tree *temp;
temp = CreateNode(data);
return temp;
}
if(data >(node->data))
{
node->right = Insert(node->right,data);
}
else if(data < (node->data))
{
node->left = Insert(node->left,data);
}
/* Else there is nothing to do as the data is already in the tree. */
return node;
}
void PrintPreorder(tree *node)
{
if(node==NULL)
{
return;
}
printf("%d ",node->data);
PrintPreorder(node->left);
PrintPreorder(node->right);
}
First of all allocate memory for arr
You are asking for binary tree but your code shows that you are using as if it is BST.[as for the add function].
Answer
If it is binary tree with no ordering then you have to search for all the nodes using standard tree traversal or BFS or DFS etc.
If it is `BST` then it will be easier.
1. Check the value x=root.val return root
2. else if( root.val> x) return search(x,root.left);
3. else return search(x,root.right);
One thing read about MCV example in SO. :)
Note 1: To allocate array you can have arr=malloc(sizeof(int)*n);
Note 2: If you are using array then you will store them this way
[ root root.left root.right root.left.left root.left.right root.right.left ... ]
1
/ \
2 3
/ \ / \
4 5 6 7
Note 3: Why are you using the array in this case..root can have access to any other node..if you don't want to dynamically allocate then only store them in a array otherwise you just dynamically insert necessary nodes when needed.
Code for searching in a BST (Binary Search Tree):
bool search(node * root, int x)
{
if(root->val==x)
return true;
else
{
if(x<root->val) //value is smaller go to the left subtree
return search(root->left,x);
else
return search(root->right,x);
}
}
Insertion algorithm BST
struct node* insert(struct node* node, int val)
{
if (node == NULL)
{
struct node *temp = malloc(sizeof(struct node));
temp->val = val;
temp->left = temp->right = NULL;
return temp;
}
if (val < node->val)
node->left = insert(node->left, val);
else if (val > node->val)
node->right = insert(node->right,val);
/* return the (unchanged) node pointer */
return node;
}
If you are using Binary tree
then you can also use some array [as we do in heap] or use a graph like structure (adjacency list..).
It is really upto your implementation.
Check this link for getting an idea - Binary tree implementation.
Searching in Binary tree
You can simply change the traversal code to this..
int levelOrder_Search(struct node* root)
{
struct Queue* queue = createQueue(SIZE);
Enqueue(root, queue);
while (!isEmpty(queue))
{
struct node* temp = Dequeue(queue);
if(temp->data==x)
return 1; // found :-)
if (temp->left)
Enqueue(temp->left, queue);
if (temp->right)
Enqueue(temp->right, queue);
}
return 0;//not found
}

Not deleting node with two children

When deleting a node with two children from my binary tree of "products", rather than replacing the root to delete with it's left child's most right ancestor and then deleting that descendant, it is simply just replacing that root's value with ancestors value. I have called "free()" on that ancestor but that doesn't seem to work. So what I am left with is two nodes of the same value.
My code:
#include <stdio.h>
#include <stdlib.h>
//Structures
typedef struct Node{
void *dataPtr;
struct Node *left;
struct Node *right;
}node;
typedef struct Product
{
int ProductCode;
char ProductName[30];
int QuantityOnHand;
double ProductCost;
double ProductRetail;
char ProductLocationCode[7];
}product;
//functions
int compareID(void *ptr1, void *ptr2)
{
int temp;
if (((product *)ptr1)->ProductCode > ((product *)ptr2)->ProductCode)
temp = 1;
else
if (((product *)ptr1)->ProductCode < ((product *)ptr2)->ProductCode)
temp = -1;
else
temp = 0;
return temp;
}
void insert(node ** root, node** val, int(*f)(void*,void*)){
if (!(*root)) {
//initalize a temporary node
node *temp = NULL;
temp = (node *)malloc(sizeof(node));
//make both right and left nodes for temp to be NULL
temp->left = NULL;
temp->right = NULL;
temp->dataPtr = (*val)->dataPtr;//store value you were looking for in temp
*root = temp;// root is now the temporary node
return;//end of function.
}
int result = f((*root)->dataPtr, (*val)->dataPtr);
if (result == 1) {//if the value is less than the current root node, go to the left connecting node
insert(&(*root)->left, &(*val), f);
}
else if (result == -1) {//if the value is more than the current root node, go to the right connecting node
insert(&(*root)->right, &(*val), f);
}
}
struct Node* deleteNode(struct Node *root, void *ptr, int(*cptr)(void*, void*))
{
struct Node *temp;
if (cptr(ptr, root->dataPtr) == 0)
{
if (root->left == NULL && root->right == NULL)//no children
{
free(root);
return NULL;
}
if (root->left != NULL && root->right == NULL)//left child
{
temp = root->left;
free(root);
return temp;
}
if (root->left == NULL && root->right != NULL)//right child
{
temp = root->right;
free(root);
return temp;
}
else //two children
{
struct Node* pred = root->left;//go left one of the node you're trying to delete
while (pred->right != NULL){//now get further right ancestor of that node
pred = pred->right;
}
root->dataPtr = pred->dataPtr; //make the original node the value of that right ancestor
return pred;//return that ancestor to delete it
}
}
else
{
int val = cptr(ptr, root->dataPtr);
if (val < 0)
{
root->left = deleteNode(root->left, ptr, cptr);
return root;
}
else
{
root->right = deleteNode(root->right, ptr, cptr);
return root;
}
}
}
void readData(struct Node** vptr, FILE *fp){
product* ptr = (product *)malloc(sizeof(product));
if (fp == stdin){
printf("Enter Product Code: ");
fscanf(fp, "%d", &(ptr->ProductCode));
fflush(stdin);
printf("Enter Name: ");
fscanf(fp, "%30[^\n]", ptr->ProductName);
fflush(stdin);
printf("Enter Quantity: ");
fscanf(fp, "%d", &(ptr->QuantityOnHand));
printf("Enter Cost: ");
fscanf(fp, "%lf", &(ptr->ProductCost));
fflush(stdin);
ptr->ProductRetail = (ptr->ProductCost / 0.7);
printf("Enter Location: ");
fscanf(fp, "%6[^\n]", &(ptr->ProductLocationCode));
fflush(stdin);
}
else{
fscanf(fp, "%d %29[^\n] %d %lf %6[^\n]", &(ptr->ProductCode), ptr->ProductName, &ptr->QuantityOnHand, &ptr->ProductCost, &ptr->ProductLocationCode);
ptr->ProductRetail = (ptr->ProductCost / 0.7);
}
(*vptr)->dataPtr = ptr;
}
int main()
{
int i = 0;
struct Node *newNode, *temp;
struct Node *root = NULL;
int(*compPtr)(void *, void *) = compareID;
for(i; i < 3; i++){
newNode = (struct Node *)malloc(sizeof(struct Node));
newNode->left = newNode->right = NULL;// missing this operation.
readData(&newNode, stdin); // this function call was missing.
insert(&root, &newNode, compPtr);
}
temp = (struct Node *)malloc(sizeof(struct Node));
temp->dataPtr = malloc(sizeof(struct Product));
printf("enter the product ID to delete : ");
fflush(stdin);
scanf("%d", &((struct Product *)temp->dataPtr)->ProductCode);
deleteNode(root, temp->dataPtr, compPtr);
free(temp->dataPtr);
free(temp);
return 0;
}
Why is this ancestor node not being freed from memory? What should I change in order to make sure it is deleted?
Your question and code are confusing at first because you use the word "ancestor" when you mean "descendant." Child nodes are descendants. Ancestors are those that come before.
The problem appears to be that you're returning the descendant rather than deleting it. In all the other cases, you're deleting the root and returning the new node. In the case that's causing you trouble, you're not deleting any node. Instead, you're returning the left child's rightmost descendant. The code that calls deleteNode replaces the node to be deleted with the node that is returned.
In this case you need to return the root after deleting the node whose value replaced the root's value. But before you can delete that descendant node, you have to remove the link from that node's parent.
I think the code you want is:
//go left one of the node you're trying to delete
struct Node* parent = root;
struct Node* pred = root->left;
//now get further right descendant of that node
while (pred->right != NULL){
parent = pred;
pred = pred->right;
}
//make the original node the value of that right descendant
root->dataPtr = pred->dataPtr;
// unlink that node from its parent
if (parent == root)
parent->left = NULL;
else
parent->right = NULL;
free(pred);
return root; //return the root node

Creating binary tree and passing node as pass by reference

I am trying to create a binary tree and i am new to data structure.
What i have to do is:
(1) Take the size of tree (total number of nodes) at terminal.
(2) Then up to size read nodes from the user at terminal
(3) Then create Binary search tree.
Note: I have to pass the node by reference only` in the function call(No other options).
It compiles without error but i guess there is any logical problem.It gives segmentation fault when i try to insert second node in for loop (for first it works fine) but compile without errors .I am not able to predict it's due to which line of code?
When I do:
How many nodes are to be inserted ?
5
enter the nodes
1 //I am not able to add more nodes
Segmentation fault (core dumped)
Answer in any language c/c++ or even algorithm are welcome.
My code to do so is :
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
struct node
{
int freq;
struct node * left, * right;
};
typedef struct node node;
/////////////////////////////////////////////////////////////Function definitions //////////////////////////////////////////////////
insert_first_node(int data, node * * Node)
{
node * temp1 ;
temp1 = Node;
temp1= (node * ) malloc(sizeof(node));
temp1 -> freq = data;
temp1 -> left = NULL;
temp1 -> right = NULL;
}
////////////////////////////////////////////////////////////////////
insert_beginning(int data, node * * Node)
{
root = * Node;
root = (node * ) malloc(sizeof(node));;
if (root ==NULL)
{
insert_first_node(data, & root);
}
if (data <= root -> freq)
{
insert_beginning(data, & root -> left);
} else
{
insert_beginning(data, & root -> right);
}
*Node = root;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
main()
{
int i, size, data;
node * head;
head = NULL;
printf("How many nodes are to be inserted ?\n");
scanf("%d", & size);
for (i = 1; i <= size; i++)
{
printf("enter the nodes \n");
scanf("%d", & data);
insert_beginning(data, & head);
}
}
I would write it like this (although I wouldn't necessarily use recursion, but maybe you are supposed to...):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node
{
int freq;
struct Node *left;
struct Node *right;
} Node;
///////////////////////////////////////////////////////////
// Function definitions //
///////////////////////////////////////////////////////////
int insert_leaf_node(int freq, Node **parent_ptr)
{
Node *node;
if ((node = malloc(sizeof *node)) == NULL)
return -1;
node->freq = freq;
node->left = NULL;
node->right = NULL;
*parent_ptr = node;
return 0;
}
///////////////////////////////////////////////////////////
int insert_node(int freq, Node **parent_ptr)
{
Node *node = *parent_ptr;
if (node == NULL) {
return insert_leaf_node(freq, parent_ptr);
}
else if (freq <= node->freq) {
return insert_node(freq, &node->left);
}
else {
return insert_node(freq, &node->right);
}
}
///////////////////////////////////////////////////////////
int main()
{
int i, size, freq;
Node *root = NULL;
printf("How many nodes are to be inserted ?\n");
scanf("%d", &size);
for (i = 0; i < size; i++) {
printf("enter the freq of node %d\n", i+1);
scanf("%d", &freq);
insert_node(freq, &root);
}
return 0;
}
And here's how I would write insert_node without recursion:
int insert_node(int freq, Node **parent_ptr)
{
Node *node;
while ((node = *parent_ptr) != NULL) {
parent_ptr = (freq <= node->freq) ? &node->left : &node->right;
}
return insert_leaf_node(freq, parent_ptr);
}
You are getting segmentation fault starting from first input only. Let me clear the reason for that.
In insert_beginning function, first line is root = * Node;. Here *Node is NULL already. So root would have NULL value also. You expected that root also points to same address as *Node but this is not the case as *Node is pointing to nothing, so root and *Node are still unrelated. Now you have allocated the memory to root in previous line, but now you have assigned NULL to root. So previous assigned address to root is lost. So that is the leak memory, Dalibor is talking about.
Lets go ahead.
Now root==NULL is checked, which is true, so insert_first_node is called. There is temp1=Node, which is syntactically wrong. I think you intended temp1 = *Node. But still that is wrong as *Node is NULL, so would be temp1. Now you are assigning value to NULL object. So next line gives segmentation fault.
The working code can be
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
struct node
{
int freq;
struct node * left, * right;
};
typedef struct node node;
/////////////////////////////////////////////////////////////Function definitions //////////////////////////////////////////////////
void insert_first_node(int data, node * * Node,int direction)
{
node * temp1 = (node * ) malloc(sizeof(node));
temp1 -> freq = data;
temp1 -> left = NULL;
temp1 -> right = NULL;
if(*Node == NULL)
*Node = temp1;
else if(direction == 1)
(*Node)->right = temp1;
else
(*Node)->left = temp1;
}
////////////////////////////////////////////////////////////////////
void insert_beginning(int data, node * * Node)
{
node *root;
root = * Node;
if (root == NULL)
{
insert_first_node(data,Node,0);
return;
}
if (data <= root -> freq)
{
if(root->left == NULL)
insert_first_node(data,&root,0);
else
insert_beginning(data,&root->left);
} else
{
if(root->right == NULL)
insert_first_node(data,&root,1);
else
insert_beginning(data,&root->right);
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
main()
{
int i, size, data;
node * head;
head = NULL;
printf("How many nodes are to be inserted ?\n");
scanf("%d", & size);
for (i = 1; i <= size; i++)
{
printf("enter the nodes \n");
scanf("%d", & data);
insert_beginning(data, & head);
}
}
It seg-faults during the insertion of your first node. If it was during the second insert, you would see the message "enter the nodes" twice.
Now to the reason. In the function insert_beginning, the first if statement does not compare root to NULL, but sets it to NULL. Since NULL is treated as false, the code inside the if is not evaluated and the execution moves to the second if statement. In it, you're trying to access freq field of root, which is set to NULL from the first if statement. So you are trying to dereference NULL pointer, which leads to the seg-fault.

improvement in my linklist program

Here is a program it is working
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next, *prev;
};
struct node *root = NULL;
void push(int);
void pop(void);
struct node *create_node(int);
void travel(void);
int main()
{
int i, j, choice, count;
printf("enter choice\n");
scanf("%d", &choice);
count = 0;
while (choice == 1) {
printf("enter a data element");
scanf("%d", &j);
if (count == 0) {
root = (struct node *)malloc(sizeof(struct node));
root->next = NULL;
root->data = j;
} else
push(j);
count++;
printf("enter choice\n");
scanf("%d", &choice);
}
printf("the link list is \n");
//travel function to be created
travel();
}
void push(int data)
{
struct node *t1;
t1 = root;
while (t1->next != NULL) {
t1 = t1->next;
}
t1->next = create_node(data);
}
void pop()
{
}
void travel(void)
{
struct node *t1;
t1 = root;
while (t1->next != NULL) {
printf("%d ", t1->data);
t1 = t1->next;
}
printf("%d ", t1->data);
}
struct node *create_node(int data)
{
struct node *p = (struct node *)malloc(sizeof(struct node));
p->data = data;
p->next = NULL;
p->prev = NULL;
return p;
}
the above program is fully working,I have used a global pointer root.
My problem is if I do not want to use a global pointer root here then how do I maintain
that list because each time I will have to return the root of list in my push pop functions
is there any other way to achieve the same?
The simplest way to achieve this is to pass a pointer to the root node pointer to each of your functions:
void push(struct node **root, int data) { ... }
void pop(struct node **root) { ... }
void travel(struct node *root) { ... }
So, in your main function you might declare a local variable to hold the root pointer:
struct node *root = NULL;
and then when you call push, for example, you pass the address of the root poiner:
push(&root, data);
I strongly recommend that you fix your push and travel functions so that they are robust to the root pointer being NULL. This was discussed in a previous question of yours and you should heed the advice.
If you did that then you could get rid of the test for count being zero and the associated special case code. You would then replace this:
if (count == 0) {
root = (struct node *)malloc(sizeof(struct node));
root->next = NULL;
root->data = j;
} else
push(&root, j);
with this:
push(&root, j);
To drive home the message, your new push would look like this:
void push(struct node **root, int data)
{
if (*root == NULL)
*root = create_node(data);
else
{
struct node *last = *root;
while (last->next != NULL) {
last = last->next;
}
last->next = create_node(data);
}
}
You would need to modify travel also to include a check for the root node being NULL. I will leave that as an exercise for you.
Maintaining both head and tail pointers could be a better approach since it would avoid so many list traversals.

Resources