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.
Related
My program is not giving the desired output. Pls check. What I am doing is, I am first building the queue and then printing every node in the order mentioned in the queue.
The desired output should be F D J B E G K A C I H. The output I am getting is F D J B A C.
#include <stdio.h>
#include <stdlib.h>
struct node
{
char data;
struct node *left;
struct node *right;
};
struct queue
{
struct node *root;
struct queue *next;
};
struct queue *head;
struct node* newnode(char c)
{
struct node *n = (struct node*)malloc(sizeof(struct node));
n->data = c;
n->left = NULL;
n->right = NULL;
return n;
}
void enqueue(struct node *tree)
{
if(head == NULL)
{
struct queue *n = (struct queue*)malloc(sizeof(struct queue));
n->root = tree;
n->next = NULL;
head = n;
}
else
{
struct queue *p = head;
while(p->next != NULL)
{
p = p->next;
}
struct queue *n = (struct queue*)malloc(sizeof(struct queue));
n->root = tree;
n->next = NULL;
p->next = n;
}
}
void traverse(struct node *tree)
{
if(tree != NULL)
{
enqueue(tree->left);
enqueue(tree->right);
traverse(tree->left);
traverse(tree->right);
}
}
void display()
{
struct queue *p = head;
while(p->next != NULL)
{
printf("%c ",p->root->data);
p = p->next;
}
printf("%c \n",p->root->data);
}
int main()
{
struct node *root = newnode('F');
root->left = newnode('D');
root->right = newnode('J');
root->left->left = newnode('B');
root->left->right = newnode('E');
root->right->left = newnode('G');
root->right->right = newnode('K');
root->left->left->left = newnode('A');
root->left->left->right = newnode('C');
root->right->left->left = newnode('I');
root->right->left->left->right = newnode('H');
enqueue(root);
traverse(root);
display();
return 0;
}
Several issues in the traverse function:
enqueue(tree->left) will eventually add NULL to the queue, and this will cause problems in the display function, where it is expected that all p have a non-NULL p->root member.
It doesn't perform a level by level traversal. It is more like a depth-first traversal (after traversing direct siblings). In a level order traversal, there is no recursion. You should iterate the queue (lagging behind as it grows), to fetch values for tree.
Here is a correction for traverse:
void traverse(struct node *tree)
{
struct queue *current = head;
while (current != NULL)
{
tree = current->root;
if (tree->left != NULL) enqueue(tree->left);
if (tree->right != NULL) enqueue(tree->right);
current = current->next; // Walk along the queue while it is being built
}
}
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
struct node *head = NULL;
struct node *second = NULL;
struct node *third = NULL;
void insertAtBeg(struct node *n, int data) {
struct node *temp;
temp = (struct node *)malloc(sizeof(struct node));
temp->data = data;
temp->next = head;
head = temp;
}
void insertAtEnd(struct node *n, int data) {
struct node *temp;
temp = (struct node*)malloc(sizeof(struct node));
temp->data = data;
temp->next = NULL;
while (n->next != NULL) {
n = n->next;
}
n->next = temp;
}
void deleteElement(struct node *head, int data) {
if (head->data == data) {
struct node *temp;
temp = head;
head = head->next;
free(temp);
printf("after deletion at head in function\n");
printList(head);
}
}
void printList(struct node *n) {
while (n != NULL) {
printf("%d\n", n->data);
n = n->next;
}
}
void main() {
head = (struct node*)malloc(sizeof(struct node));
second = (struct node*)malloc(sizeof(struct node));
third = (struct node*)malloc(sizeof(struct node));
head->data = 1;
head->next = second;
second->data = 2;
second->next = third;
third->data = 3;
third->next = NULL;
printList(head);
insertAtBeg(head, 0);
printf("after insertion at beginning\n");
printList(head);
insertAtEnd(head, 4);
printf("after insertion at End\n");
printList(head);
deleteElement(head, 0);
printf("after deletion at head in main\n");
printList(head);
}
output of the code is
1
2
3
after insertion at beginning
0
1
2
3
after insertion at End
0
1
2
3
4
after deletion at head in function
1
2
3
4
after deletion at head in main
0
1
2
3
4
Why is there a difference in output of the function called in main and the function called in another function.ie.after deletion at head in function and after deletion at head in main, when both are supposed to be deleting element from the same list
The problem is you need a way to modify the head of the list when inserting and/or deleting elements from the list.
A simple way to do this is for these functions to return a potentially updated value of the head pointer and for the caller to store this return value into it's head variable.
Here is a modified version of your code with these semantics:
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
struct node *insertAtBeg(struct node *head, int data) {
struct node *temp;
temp = (struct node *)malloc(sizeof(struct node));
// should test for memory allocation failure
temp->data = data;
temp->next = head;
return temp;
}
struct node *insertAtEnd(struct node *head, int data) {
struct node *temp;
struct node *n;
temp = (struct node*)malloc(sizeof(struct node));
// should test for memory allocation failure
temp->data = data;
temp->next = NULL;
if (head == NULL)
return temp;
n = head;
while (n->next != NULL) {
n = n->next;
}
n->next = temp;
return head;
}
struct node *deleteElement(struct node *head, int data) {
// delete the first node with a given data
if (head->data == data) {
struct node *temp = head;
head = head->next;
free(temp);
} else {
struct node *n = head;
while (n->next != NULL) {
if (n->next->data == data) {
struct node *temp = n->next;
n->next = temp->next;
free(temp);
break;
}
}
}
return head;
}
void printList(const struct node *n) {
while (n != NULL) {
printf("%d\n", n->data);
n = n->next;
}
}
int main() {
struct node *head = NULL;
head = insertAtBeg(head, 1);
head = insertAtEnd(head, 2);
head = insertAtEnd(head, 3);
printList(head);
head = insertAtBeg(head, 0);
printf("after insertion at beginning\n");
printList(head);
head = insertAtEnd(head, 4);
printf("after insertion at End\n");
printList(head);
head = deleteElement(head, 0);
printf("after deletion at head in main\n");
printList(head);
// should free the list
return 0;
}
An alternative is to pass the address of the list head pointer so the function can modify it if needed.
Here is a modified version of your code with this alternative approach:
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
struct node *insertAtBeg(struct node **headp, int data) {
struct node *temp = malloc(sizeof(*temp));
if (temp != NULL) {
temp->data = data;
temp->next = *headp;
*headp = temp;
}
return temp;
}
struct node *insertAtEnd(struct node **headp, int data) {
struct node *temp = malloc(sizeof(*temp));
if (temp != NULL) {
temp->data = data;
temp->next = NULL;
if (*headp == NULL) {
*headp = temp;
} else {
struct node *n = *headp;
while (n->next != NULL) {
n = n->next;
}
n->next = temp;
}
}
return temp;
}
int deleteElement(struct node **headp, int data) {
// delete the first node with a given data
struct node *head = *headp;
if (head->data == data) {
*headp = head->next;
free(temp);
return 1; // node was found and freed
} else {
struct node *n = head;
while (n->next != NULL) {
if (n->next->data == data) {
struct node *temp = n->next;
n->next = temp->next;
free(temp);
return 1; // node was found and freed
}
}
return 0; // node not found
}
}
void printList(const struct node *n) {
while (n != NULL) {
printf("%d\n", n->data);
n = n->next;
}
}
int main() {
struct node *head = NULL;
insertAtBeg(&head, 1);
insertAtEnd(&head, 2);
insertAtEnd(&head, 3);
printList(head);
insertAtBeg(&head, 0);
printf("after insertion at beginning\n");
printList(head);
insertAtEnd(&head, 4);
printf("after insertion at End\n");
printList(head);
deleteElement(&head, 0);
printf("after deletion at head in main\n");
printList(head);
// free the list
while (head != NULL) {
deleteElement(&head, head->data);
}
return 0;
}
This alternative approach uses double pointers, so it is a bit more difficult for beginners to comprehend, but it has a strong advantage: the functions can update the list pointer and provide a meaningful return value that can be tested to detect errors. For example insertAtBeg() and insertAtEnd() return NULL if the new node could not be allocated but preserve the list. Similarly deleteElement() can return an indicator showing whether the element was found or not.
With this approach, you can write functions to pop the first or last element of the list, or the one at a given index, or one with a given data, while updating the list pointer as needed.
In the function void deleteElement(struct node *head,int data) you are passing a pointer to the head node. If you make changes to the node, then that works because you are pointing to the actual node. However, the variable head is a local copy of the pointer, which is not the one in main. When you change head to head->next that is only changing the local copy, so it has no effect outside deleteElement.
ADVANCED LEVEL POINTERS
To actually change head you have to pass a pointer to it, making a double pointer:
void deleteElement(struct node **phead,int data) {
struct node *temp;
temp = *phead;
*phead = (*phead)->next;
this means you have to pass the address of head &head as the parameter.
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'm trying to do operations in a doubly linked list, and I tried applying the logic of deletion but it's showing some sort of void error. Please tell me what's wrong in this code.
The error message is written alongside the line of code.
Function to get new node:
void getnewnode(int x)
{
struct node* temp = (struct node*)malloc(sizeof(struct node*));
temp->data = x;
temp->next = NULL;
temp->prev = NULL;
}
Insert function:
void insertatbeg(int x)
{
struct node* newnode=getnewnode(x); /* void value not ignored as it ought to be. */
if(head==NULL)
{
head = newnode;
}
else
{
head->prev = newnode;
newnode->next = head;
head = newnode;
}
}
Delete(nth node) function:
void delete(int n)
{
struct node* temp1=head;
int i;
if(temp1 == NULL)
return;
for(i = 0; i < n-2; i++)
{
temp1 = temp1->next;
}
struct node* temp2 = temp1->next;
(temp2->next)->prev = temp1;
temp1->next = temp2->next;
free(temp2);
}
Here is the main function:
struct node /* List called node */
{
struct node* next;
int data;
struct node* prev;
};
struct node* head;
void insertatbeg(int x);
void delete(int n);
int main()
{
int x;
head = NULL;
insertatbeg(x);
insertatbeg(x);
insertatbeg(x);
delete(2);
}
Looks to me your problem is here:
void getnewnode(int x)
{
struct node* temp = (struct node*)malloc(sizeof(struct node*));
temp->data = x;
temp->next = NULL;
temp->prev = NULL;
}
Specifically, in the first line. You probably want that to be sizeof(struct node), so that your pointer references a node, not a pointer to a node.
You also need to make your function return a value. So change it to:
void getnewnode(int x)
{
....
return temp;
}
The reason you're getting the error on this line:
struct node* newnode=getnewnode(x); /* void value not ignored as it ought to be. */
Is that your getnewnode function doesn't return a value. So newnode can't be assigned a value. That error should go away when you make the suggested change to getnewnode().
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;