I have created a linked list in C. I dynamically allocate memory as
'''
struct node* createNode(value) {
struct node* newNode =
malloc(sizeof(struct node));
newNode->data = value;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
struct node* insertLeft(struct node* root, int value) {
root->left = createNode(value);
return root->left;
}
int main() {
struct node* root = createNode(1);
insertLeft(root,12);
//Create more nodes
postorder(root);
}
void postorder(struct node* root) {
if (root == NULL) return;
postorder(root->left);
postorder(root->right);
printf("%d ->", root->data);
}
'''
Now the root node I am getting after insertion is of the newly inserted element.Because I return this new node. How come while traversing the top-most root is passed to postorder.
Also if I don't return this new node it should still exist in the memory so why return?
Now the root node I am getting after insertion is of the newly inserted element.Because I return this new node.
That's not the case. When you call insertLeft(), you don't assign its return value to anything. So root still points to the node with data == 1.
Related
I am trying to implement the insert operation of a binary search tree using C. Why does the following code show a Segmentation fault when trying to print the value of the left and right nodes of the root?
Please explain what caused this error exactly.
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node* left;
struct node* right;
};
struct node *root, *temp = NULL;
void insert(int data) {
struct node *newNode = (struct node*) malloc(sizeof(struct node));
newNode->data = data;
newNode->left = NULL;
newNode->right = NULL;
if (root == NULL){
// if tree is empty insert the node as root
root = newNode;
}else {
// if the tree is not empty
temp = root;
while(temp != NULL) {
if(data <= root->data) {
temp = temp->left;
}
if(data > root->data) {
temp = temp->right;
}
}
temp = newNode;
}
}
int main() {
insert(7);
insert(4);
insert(8);
printf("\n\n------%d------", root->left->data);
printf("\n\n------%d------", root->right->data);
return 0;
}
The assignment temp = newNode only stores a pointer in the temp variable, not somewhere in the tree. So your tree's root node will never get any child. By consequence the main program is dereferencing a root->left pointer that is NULL, and this explains the error you get.
In order to really attach the new node at the right place in the tree, you need to modify a left or right member of some node. You can do this in several ways. One is to make temp a pointer-pointer, so that it will have the address of a left or right member. Then the assignment to *temp, will be an assignment to a node's left or right member, effectively extending the tree with that new node.
Here is the updated part of the code:
struct node **temp = &root;
while(*temp != NULL) {
if(data <= root->data) {
temp = &(*temp)->left;
}
if(data > root->data) {
temp = &(*temp)->right;
}
}
*temp = newNode;
okay you have a few issues here,
first of all, temp will point back to newNode, as you have not copied newNode's values to where temp is pointing now.
second and no less important, newNode is created within the scope of insert() - therefore, root will always remain null, as root points after execution of insert() to data wich no longer exists.
I have improved your code, and this definitely works as expected
hope it has helped.
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node* left;
struct node* right;
}node;
node *root=NULL;
void insert(int data) {
node *temp = NULL;
if (root == NULL){
/* if tree is empty insert the node as root*/
root = malloc(sizeof(struct node));
root->data=data;
}else {
/*if the tree is not empty*/
temp = root;
while(temp->left!= NULL||temp->right!=NULL) {
if(data <= temp->data){
if(temp->left==NULL)
break;
else
temp = temp->left;
}
else if(data > temp->data){
if(temp->right==NULL)
break;
else
temp = temp->right;
}
}
if(data<= temp->data){
temp->left=malloc(sizeof(struct node));
(temp->left)->data=data;
}
else {
temp->right=malloc(sizeof(struct node));
(temp->right)->data=data;
}
/*temp=newNode;*/
}
}
int main() {
insert(7);
insert(4);
insert(8);
printf("\n\n------%d------", root->left->data);
printf("\n\n------%d------", root->right->data);
return 0;
}
I was trying to implement level order traversal of binary search tree using linked list implementation of queue.
I have checked the binary search tree implementation and it is fine.
The linked list implementation of queue is also correct.
Here i am trying to visit the node and enqueue its children to the queue.
and then use the pop function to actually visit the node.
This is being done via a recursive call in the end.
When i run the following code i am getting the output in different order.
// Trees
#include <stdio.h>
#include <stdlib.h>
//Node declaration for binary search tree
struct node
{
int data;
struct node *left;
struct node *right;
};
// LINKED LIST BASED IMPLEMENTATION OF QUEUE
struct qnode
{
struct node *data;
struct qnode *next;
};
struct qnode *head = NULL;
void insertq (struct node *); //This function enqueue node in the queue.
struct node *pop (); // dequeue function
//The function declaration for level order traversal.
void leorder ();
struct node *make (int);
struct node *insert (struct node *, int);
void
main ()
{
struct node *root = NULL;
root = insert (root, 10);
root = insert (root, 9);
root = insert (root, 8);
root = insert (root, 5);
root = insert (root, 2);
root = insert (root, 4);
root = insert (root, 3);
root = insert (root, 6);
root = insert (root, 7);
root = insert (root, 1);
insertq (root); //Insertion of first root.
leorder ();
}
//The program that makes nodes for the bst.
struct node* make(int x){
struct node* temp = (struct node*)malloc(sizeof(struct node));
temp->data = x;
temp->left = NULL;
temp->right = NULL;
return temp;
};
//The node insertion function.(BINARY SEARCH TREE)
struct node* insert(struct node* root,int x){
if(root == NULL){
root = make(x);
}
else{
if(x <= root->data){
root->left = insert(root->left,x);
}
else{
root->right = insert(root->right,x);
}}
return root;
}
// This function will insert node in the queue.
void insertq(struct node* x){
if(head == NULL){
struct qnode* temp = (struct qnode*)malloc(sizeof(struct qnode));
temp->data = x;
temp->next = NULL;
head = temp;
}
else{
struct qnode* temp = (struct qnode*)malloc(sizeof(struct qnode));
temp->data = x;
temp->next = head;
head = temp;
}
}
struct node* pop(){
struct node* r;
if(head == NULL){
return NULL;
}
else{
struct qnode* pt;
pt = head;
head = head->next;
r = pt->data;
free(pt);
return r;
}
}
// dequeue function.
struct node* pop(){
struct node* r;
if(head == NULL){
return NULL;
}
else{
struct qnode* pt;
pt = head;
head = head->next;
r = pt->data;
free(pt);
return r;
}
}
// Function to print tree in level order.
void leorder(){
struct node* popped;
popped = pop();
printf("%d ",popped->data);
if(popped != NULL){
if(popped->left != NULL){
insertq(popped->left);
}
if(popped->right != NULL){
insertq(popped->right);
}
leorder();
}
}
Right now, you insert at the head, and you remove at the head. This means you have a stack (last in, first out), not a queue (first in, first out).
Add a tail pointer, and remove from the opposite end that you add. If you add at the head, remove from the tail, or vice-versa.
I am trying to implement a linked list from scratch in C:
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node * next;
};
void insert(struct node** root, int data){
// Create a Node
struct node * temp = malloc(sizeof(struct node));
temp->data = data;
temp->next = NULL;
// Either root is NULL or not
if (*root == NULL){
*root = temp; // Directly modify the root
}
else {
struct node * t = *root;
while (t->next!=NULL){
t = t->next;
}
t->next = temp; // Append at the last
}
}
void printList(struct node * root){
while(root!=NULL){
printf("%d\t", root->data);
}
}
struct node * search(struct node* root, int key){
while (root!=NULL) {
if (root->data == key) return root;
}
return NULL;
}
int main(){
struct node * head = NULL;
insert(&head,0);
insert(&head,1);
insert(&head,2);
insert(&head,3);
insert(&head,4);
printList(head);
}
Now, when I run the program, my output is:
0 0 0 0 0 0 0 0 0 0
However, my list doesn't contain all zeroes or 10 elements.
My logic seems correct but somehow code has a bug.
On a side note, is there a way to avoid double pointers, can't I work with only pointers while inserting in a linked list?
There is a small bug in the printList() function.
In printList() function, root not updated, to iterate whole list you should do root = root->next
void printList(struct node * root){
while(root!=NULL){
printf("%d\t", root->data);
root = root->next; /* you miss this one */
}
}
Same mistake is repeated in search() function also,
struct node * search(struct node* root, int key){
while (root!=NULL) {
if (root->data == key)
return root;
else
root = root->next; /* if key not found root should be updated to next one */
}
return NULL;
}
So I've use pass by reference on my linked list code but the problem is it's not printing soo how do I actually fix this?
my code:
#include<stdio.h>
#include<stdlib.h>
struct node
{
int x;
struct node *next;
};
void add(struct node **root, int x)
{
struct node *conductor;
if(root==NULL)
{
(*root)=malloc(sizeof(struct node));
(*root)->x=x;
(*root)->next=NULL ;
}
else
{
conductor = *root;
while(conductor->next!=NULL)
{
conductor = conductor -> next;
}
conductor->next=malloc(sizeof(struct node));
conductor->next->x=x;
conductor->next->next=NULL;
}
}
void display(struct node *root)
{
struct node *conductor;
conductor=root;
while(conductor!=NULL)
{
printf("%d",conductor->x);
conductor = conductor ->next;
}
}
int main()
{
struct node *root;
root=NULL;
add(&root,5);
add(&root,4);
display(root);
free(root);
system("pause");
}
In better form
http://codepad.org/CPdUvK0x
Isn't it all nodes in my program are linked?
void add(struct node **root, int x)
{
struct node *conductor;
if(root==NULL)
That should be if (*root == NULL)
Since you're calling add(&root... root will never be NULL.
The check:
if(root==NULL)
should be
if(*root==NULL)
as root is being passed by address.
Also you do free(root) to free the entire list which is incorrect as it frees only the first node and makes the other nodes unreachable causing memory leak. To fix this you need to free the nodes one by one as:
struct node *tmp = root;
while(root) {
tmp = root->next;
free(root);
root = tmp;
}
the problem is in add():
if(root==NULL)
this test is wrong: root being passed by reference is never NULL (see in the main, it contains the address of the root node). you should correctly test if the rrot node is NULL:
if (*root == NULL)
i would also add that your way of freeing the memory allocated for the ist is wrong:
free(root)
will only free the root node, but will leak the child nodes...
Going through classic data structures and have stopped on linked lists.Just implemented a circular singly-linked list, but I'm under overwhelming impression that this list could be expressed in a more elegant manner, remove_node function in particular.
Keeping in mind efficiency and code readability, could anybody present a more concise and efficient solution for singly-linked circular list?
#include <stdio.h>
#include <stdlib.h>
struct node{
struct node* next;
int value;
};
struct list{
struct node* head;
};
struct node* init_node(int value){
struct node* pnode;
if (!(pnode = (struct node*)malloc(sizeof(struct node)))){
return NULL;
}
else{
pnode->value = value;
}
return pnode;
}
struct list* init_list(){
struct list* plist;
if (!(plist = (struct list*)malloc(sizeof(struct list)))){
return NULL;
}
plist->head = NULL;
return plist;
}
void remove_node(struct list*a plist, int value){
struct node* current, *temp;
current = plist->head;
if (!(current)) return;
if ( current->value == value ){
if (current==current->next){
plist->head = NULL;
free(current);
}
else {
temp = current;
do {
current = current->next;
} while (current->next != plist->head);
current->next = plist->head->next;
plist->head = current->next;
free(temp);
}
}
else {
do {
if (current->next->value == value){
temp = current->next;
current->next = current->next->next;
free(temp);
}
current = current->next;
} while (current != plist->head);
}
}
void print_node(struct node* pnode){
printf("%d %p %p\n", pnode->value, pnode, pnode->next);
}
void print_list(struct list* plist){
struct node * current = plist->head;
if (!(current)) return;
if (current == plist->head->next){
print_node(current);
}
else{
do {
print_node(current);
current = current->next;
} while (current != plist->head);
}
}
void add_node(struct node* pnode,struct list* plist){
struct node* current;
struct node* temp;
if (plist->head == NULL){
plist->head = pnode;
plist->head->next = pnode;
}
else {
current = plist->head;
if (current == plist->head->next){
plist->head->next = pnode;
pnode->next = plist->head;
}
else {
while(current->next!=plist->head)
current = current->next;
current->next = pnode;
pnode->next = plist->head;
}
}
}
Take a look at the circular linked list in the Linux kernel source: http://lxr.linux.no/linux+v2.6.36/include/linux/list.h
Its beauty derives from the fact that you don't have a special struct for your data to fit in the list, you only have to include the struct list_head * in the struct you want to have as a list. The macros for accessing items in the list will handle the offset calculation to get from the struct list_head pointer to your data.
A more verbose explanation of the linked list used in the kernel can be found at kernelnewbies.org/FAQ/LinkedLists (Sorry, I dont have enough karma to post two hyperlinks).
Edit: Well, the list is a double-linked list and not a single-linked one like you have, but you could adopt the concept and create your own single-linked list.
List processing (particularly of circular lists) gets way easier when you treat the list head like an element of the list (a so-called "sentinel"). A lot of special cases just disappear. You can use a dummy node for the sentinel, but if the next pointer is first in the struct, you don't need to do even that. The other big trick is to keep a pointer to the next pointer of the previous node (so you can modify it later) whenever you modify the list. Putting it all together, you get this:
struct node* get_sentinel(struct list* plist)
{
// use &plist->head itself as sentinel!
// (works because struct node starts with the next pointer)
return (struct node*) &plist->head;
}
struct list* init_list(){
struct list* plist;
if (!(plist = (struct list*)malloc(sizeof(struct list)))){
return NULL;
}
plist->head = get_sentinel(plist);
return plist;
}
void add_node_at_front(struct node* pnode,struct list* plist){
pnode->next = plist->head;
plist->head = pnode;
}
void add_node_at_back(struct node* pnode,struct list* plist){
struct node *current, *sentinel = get_sentinel(plist);
// search for last element
current = plist->head;
while (current->next != sentinel)
current = current->next;
// insert node
pnode->next = sentinel;
current->next = pnode;
}
void remove_node(struct list* plist, int value){
struct node **prevnext, *sentinel = get_sentinel(plist);
prevnext = &plist->head; // ptr to next pointer of previous node
while (*prevnext != sentinel) {
struct node *current = *prevnext;
if (current->value == value) {
*prevnext = current->next; // remove current from list
free(current); // and free it
break; // we're done!
}
prevnext = ¤t->next;
}
}
void print_list(struct list* plist){
struct node *current, *sentinel = get_sentinel(plist);
for (current = plist->head; current != sentinel; current = current->next)
print_node(current);
}
A few comments:
I think the remove function doesn't correctly adjust the circular list pointers when you delete the head node and the list is larger than 3 elements. Since the list is circular you have to point the last node in the list to the new head.
You might be able to shorten the remove function slightly by creating a "find_node" function. Since the list is circular, however, there will still be the edge case of deleting the head node which will be more complex than in a non-circular list.
Code "beauty" is in the eye of the beholder. As code goes yours is easy to read and understand which beats a lot of code in the wild.
I use the following to create a dynamic circular singly linked list. All it requires is the size.
Node* createCircularLList(int size)
{
Node *it; // to iterate through the LList
Node *head;
// Create the head /1st Node of the list
head = it = (Node*)malloc(sizeof(Node));
head->id = 1;
// Create the remaining Nodes (from 2 to size)
int i;
for (i = 2; i <= size; ++i) {
it->next = (Node*)malloc(sizeof(Node)); // create next Node
it = it->next; // point to it
it->id = i; // assign its value / id
if (i == 2)
head->next = it; // head Node points to the 2nd Node
}
// close the llist by having the last Node point to the head Node
it->next = head;
return head; // return pointer to start of the list
}
And i define Node ADT like so:
typedef struct Node {
int id;
struct Node *next;
} Node;