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;
}
Related
I am struggling to implement the following function:
Given a binary search tree, return the smallest node, then move the pointer to the next smallest node in the tree. Upon calling the function another time, it should return the next smallest node and so on.
Any help would be greatly appreciated.
Here is my program so far with some helper functions and their definitions:
#include <stdio.h>
#include <stdlib.h>
/* A binary tree node has data,
the pointer to left child
and a pointer to right child */
struct node {
int data;
struct node *left;
struct node *right;
struct node *parent;
};
struct node *minValue(struct node *node);
struct node *inOrderSuccessor(
struct node *root,
struct node *n)
{
if (n->right != NULL)
return minValue(n->right);
struct node *p = n->parent;
while (p != NULL && n == p->right) {
n = p;
p = p->parent;
}
return p;
}
/* Given a non-empty binary search tree,
return the minimum data
value found in that tree. Note that
the entire tree does not need
to be searched. */
struct node *minValue(struct node *node)
{
struct node *current = node;
/* loop down to find the leftmost leaf */
while (current->left != NULL) {
current = current->left;
}
return current;
}
/* Helper function that allocates a new
node with the given data and
NULL left and right pointers. */
struct node *newNode(int data)
{
struct node *node = (struct node *)malloc(sizeof(struct node));
node->data = data;
node->left = NULL;
node->right = NULL;
node->parent = NULL;
return (node);
}
/* Give a binary search tree and
a number, inserts a new node with
the given number in the correct
place in the tree. Returns the new
root pointer which the caller should
then use (the standard trick to
avoid using reference parameters). */
struct node *insert(struct node *node,
int data)
{
/* 1. If the tree is empty, return a new,
single node */
if (node == NULL)
return (newNode(data));
else {
struct node *temp;
/* 2. Otherwise, recur down the tree */
if (data <= node->data) {
temp = insert(node->left, data);
node->left = temp;
temp->parent = node;
} else {
temp = insert(node->right, data);
node->right = temp;
temp->parent = node;
}
/* return the (unchanged) node pointer */
return node;
}
}
Here are some remarks about your code:
the function minValue is correct, by it should accept a null argument (which is an empty tree) and return null for that.
the function new_node should check for memory allocation failure to avoid undefined behavior.
function inOrderSuccessor should stop scanning when it goes back up to the root node from its right child and return NULL. Also testing for a null parent node will avoid undefined behavior.
you can check for failure in insert and return a null pointer.
Here is a modified version with a functional test:
#include <stdio.h>
#include <stdlib.h>
/* A binary tree node has data,
the pointer to left child
a pointer to right child
and a pointer to parent node
*/
struct node {
int data;
struct node *left;
struct node *right;
struct node *parent;
};
/* Given a binary search tree,
return the node with the minimum data. */
struct node *minValue(struct node *node) {
if (node) {
/* loop down to find the leftmost leaf */
while (node->left != NULL) {
node = node->left;
}
}
return node;
}
struct node *inOrderSuccessor(struct node *root,
struct node *n)
{
if (n == NULL)
return minValue(root);
if (n->right != NULL)
return minValue(n->right);
for (;;) {
struct node *p = n->parent;
/* sanity test */
if (p == NULL)
return NULL;
/* coming back from the left child, return parent node */
if (n != p->right)
return p;
/* coming back from the right child, stop at the root node */
if (p == root)
return NULL;
n = p;
}
}
/* Helper function that allocates a new
node with the given data and
NULL left and right pointers. */
struct node *newNode(int data) {
struct node *node = malloc(sizeof(*node));
if (node) {
node->data = data;
node->left = NULL;
node->right = NULL;
node->parent = NULL;
}
return node;
}
/* Give a binary search tree and
a number, inserts a new node with
the given number in the correct
place in the tree. Returns the new
root pointer which the caller should
then use (the standard trick to
avoid using reference parameters).
Return a null pointer on memory allocation failure */
struct node *insert(struct node *node,
int data)
{
/* 1. If the tree is empty, return a new,
single node */
if (node == NULL) {
return newNode(data);
} else {
struct node *temp;
/* 2. Otherwise, recurse down the tree */
if (data <= node->data) {
temp = insert(node->left, data);
if (temp == NULL) /* return NULL on failure */
return NULL;
node->left = temp;
temp->parent = node;
} else {
temp = insert(node->right, data);
if (temp == NULL) /* return NULL on failure */
return NULL;
node->right = temp;
temp->parent = node;
}
/* return the (unchanged) node pointer */
return node;
}
}
void freeNode(struct node *node) {
if (node) {
freeNode(node->left);
freeNode(node->right);
free(node);
}
}
int main() {
struct node *tree = NULL;
printf("inserting values:");
for (int i = 0; i < 20; i++) {
int data = rand() % 1000;
tree = insert(tree, data);
printf(" %d", data);
}
printf("\n");
printf("enumerate values:");
for (struct node *cur = NULL;;) {
if ((cur = inOrderSuccessor(tree, cur)) == NULL)
break;
printf(" %d", cur->data);
}
printf("\n");
freeNode(tree);
return 0;
}
Output:
inserting values: 807 249 73 658 930 272 544 878 923 709 440 165 492 42 987 503 327 729 840 612
enumerate values: 42 73 165 249 272 327 440 492 503 544 612 658 709 729 807 840 878 923 930 987
Given a binary search tree, return the smallest node, then move the pointer to the next smallest node in the tree. Upon calling the function another time, it should return the next smallest node and so on.
struct node *next_smallest_node(struct node *root, struct node *min)
{
if (!min)
return min_node(root);
if (min->right)
return min_node(min->right);
for (struct node *p = min->parent; p; p = min->parent) {
// Coming from left: return parent
if (min != p->right)
return p;
// Coming from right: stop at root
if (p == root)
return NULL;
min = p;
}
return NULL;
}
min_node() returns the smallest node in a tree:
struct node *min_node(struct node *root)
{
struct node *min = NULL;
for (struct node *i = root; i; i = i->left)
min = i;
return min;
}
Usage:
int main(void)
{
struct node *tree = NULL;
// Fill tree with data ...
struct node *min = NULL;
while (min = next_smallest_node(tree, min)) {
printf("Next smallest = %d\n", min->data);
}
}
Update:
The code in next_smallest_node() now parses the left sub-tree (thanks to #chqrlie).
There's no need to compute the minimum value prior to calling the function.
I was trying to create a BST in C. I was just adding bare basic functionalities. However, I have seemed to run into a problem either adding a node or with the in-order traversal - somehow created an infinite loop. Please offer feedback as I am trying to improve. Thanks!
#include <stdio.h>
#include <stdlib.h>
//node structure
struct node{
int data;
struct node* left;
struct node* right;
}typedef node;
//create node
node * createLeaf(int x){
node * temp = (node*)malloc(sizeof(node));
temp->data = x;
temp->left = NULL;
temp->right = NULL;
return temp;
}
//insert node
node *insert(node *root,int x){
if(root == NULL){
root = createLeaf(x);
return root;
}
else{
if(x > root->data){
root->right = insert(root->right,x);
}
else if(x < root->data){
root->left = insert(root->left,x);
}
}
return root;
}
//in-order traversal
void inorder(node * root){
while(root!=NULL){
inorder(root->left);
printf("%d\n",root->data);
inorder(root->right);
}
}
int main()
{
node * root = NULL;
root = insert(root,5);
insert(root,8);
insert(root,1);
inorder(root);
printf("Hello World");
return 0;
}
What #Eugene suggested replacing while with if will fix the problem
Or you can add a break at the end of while loop and it should also solve your problem.
But I will suggest to only use either recursion or iteration.
**I was doing insertion operation in BST using itteraton mechanism. I did inorder traversal using recursion for swift display of my tree and to know whether i am doing it right or wrong. However, the output is always 4 . I donot understand ummwhat might be the problem. Is my root not updating? **
#include<stdio.h>
#include<stdlib.h>
typedef struct Node{
int data;
struct Node *left;
struct Node *right;
}node;
node *new(int data){ //create node
node *pw;
pw = (node *)malloc(sizeof(node *));
pw->data = data;
pw->left = NULL;
pw->right= NULL;
return pw;
}
node *insert(node *root, int data ){ //insert using itteration
node *pr;
pr = root;
if(root==NULL)
return new(data);
while(pr!= NULL){
if(data< pr->data){
if(pr->left==NULL){
pr->data = data;
pr=NULL;
}
else{
pr= pr->left;
}
}else if(data> pr->data){
if(pr->right==NULL){
pr->data = data;
pr=NULL;
}
else{
pr= pr->right;
}
}
}
return pr;
}
void inorder(node *root) {
if (root != NULL) {
// Traverse left
inorder(root->left);
// Traverse root
printf("%d -> ", root->data);
// Traverse right
inorder(root->right);
}
}
void main(){
node* root = NULL;
root = insert(root,5);
root = insert(root,6);
root = insert(root,4);
inorder(root); //inorder traversal for displaying tree
}
it seems like you are always changing the parent node's data instead of creating a new node to be the child of the parent node.
so instead of:
if(pr->left==NULL){
pr->data = data;
pr=NULL;
}
it needs to be:
if(pr->left==NULL){
pr->left = new(data);
break; /*you have inserted the node, a break will stop the loop*/
}
same change should be applied for the right if statement.
And further - insert has this return statement: return pr and that you save into root in the caller. However, root is only to be changed when root is NULL to start with. In other words: Returning pr is wrong.
Therefore do this change:
return pr; ---> return root;
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.
So up until now this is the code I have. I'm having problems implementing the main function because linked-lists are a new subject for me. Could someone explain me what should I include to have an output like this
The output should look like that after inserting 2, 0, 3, 5 and 4 in an, initially, empty list:
2
0 2
0 2 3
0 2 3 5
0 2 3 4 5
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int number;
struct node *next;
} NODE;
NODE* insert(NODE *, int);
NODE* delete(NODE *, int);
void traverse(NODE *);
NODE * search(NODE *head, int data);
main(){
list *newnode, *start = NULL; // this will point to the first node of the list
}
NODE *search(NODE *head, int data){ //search for the right position to add data
NODE *previous=NULL;
NODE *current=head;
while (current !=NULL && data > current->number)
{
previous=current;
current= current->next;
}
return previous;
}
NODE *insert(NODE *head, int data){ //allocates a new node with data value
NODE * temp;
if (temp = (NODE *)malloc(sizeof(NODE)==(NODE*)NULL))
return 1; //malloc have failed
temp->number = data;
NODE *previous;
previous=search(head,data);
//two cases 1) add at front 2)add elsewhere
if (previous==NULL)
{
temp->next=head;
head=temp;
}
else
{
temp->next = previous->next;
previous->next = temp;
}
return head;
}
void traverse (NODE *head){
NODE * current = head;
while (current != NULL)
{
printf(" %d ", current->number);
current = current->next;
}
printf("\n");
}
NODE* delete(NODE *head, int data)
{
NODE *previous, *temp;
previous=search(head,data);
if(previous==NULL && head->number==data)
{
temp=head;
head=head->next;
free(temp);
}
else if (previous->next !=NULL && previous->next->number==data)
{
temp=previous->next;
previous->next = previous->next->next;
free(temp);
}
return head;
}
void printList (list *currentPtr)
{
if (currentPtr == NULL)
printf("list is empty.\n\n");
else
{
printf("The list is:\n");
while (currentPtr != NULL){
printf("%d --> ", currentPtr->number);
currentPtr = currentPtr ->next;
}
printf("NULL\n\n");
}
}
The list is:
0 -> 2 -> 3 -> 4 -> 5 -> NULL
Yo can take away the NULL and the -> if you want.