unable to insert into ordered linked list in C - c

i am new to programming and C. I am trying to create an ordered linked list. For some reason which i cannot figure out, it never enters the first if block in the insert_in_order function even though my linked list is empty when i call the insert_in_order function. Would anyone have any idea what i am doing wrong?
Here is my code:
#include <stdio.h>
#include <stdlib.h>
struct node {
int value;
struct node* next;
};
typedef struct node node_t;
void printlist(node_t *head){
node_t *temporary = head;
while(temporary != NULL){
printf("%d - ", temporary->value);
temporary = temporary->next;
}
printf("\n");
}
node_t *create_new_node(int value){
node_t *result = malloc(sizeof(node_t));
result->value = value;
result->next = NULL;
//printf("result.value = %d\n", result->value);
return result;
}
void insert_in_order (node_t *head, node_t *node_to_insert){
node_t *current_node = head;
node_t *prior_node = head;
//linked list is empty
if (head == NULL){ //never enters if block for some reason
head->next = node_to_insert;
node_to_insert->next = NULL;
break;
//printf("inside the if stmt");
}
if(node_to_insert->value <= current_node->value){
head->next = node_to_insert;
node_to_insert->next = current_node;
break;
}
current_node = current_node->next;
while (current_node->next != NULL){
if(node_to_insert->value <= current_node->value){
node_to_insert->next = current_node;
prior_node->next = node_to_insert;
break;
}
else if (node_to_insert > current_node){
current_node = current_node->next;
prior_node = prior_node->next;
}
}
//node to insert is the largest in the linked list
current_node->next = node_to_insert;
node_to_insert->next = NULL;
}
int main(){
node_t *head;
node_t *node1;
node_t *node2;
head = NULL;
node1 = create_new_node(22);
node2 = create_new_node(33);
printf("node1's value equals %d\n", node1->value);
printf("node2's value equals %d\n", node2->value);
insert_in_order(head, node1);
printlist(head);
}

First of all this code does not compile - these breaks are invalid
if (head == NULL){ //never enters if block for some reason
head->next = node_to_insert;
node_to_insert->next = NULL;
break; <<<<====
//printf("inside the if stmt");
}
and
if (node_to_insert->value <= current_node->value) {
head->next = node_to_insert;
node_to_insert->next = current_node;
break; <<<=====
}
Seems like you meant return when you said break, now compiles with those replaced by return
Now this goes wrong
//linked list is empty
if (head == NULL) { //never enters if block for some reason
head->next = node_to_insert;
You just tested to see if head is NULL and if it is you try to use it, thats never going to work
You mean this
//linked list is empty
if (head == NULL) { //never enters if block for some reason
head = node_to_insert;
node_to_insert->next = NULL;
return;
}
code now runs to completion, although there may be other errors
node1's value equals 22
node2's value equals 33

Related

Linked List in C: Accessing current->next is neither NULL or !NULL; problem with adding new nodes

So I encounter this problem where when I add nodes to an empty head in a specific sequence it doesn't work.
If I insert 2,1,3,4 so the second number is smaller than the first number, then it works. But if I add 2,3,4,5, then it doesn't work. I get a Segmentation fault (core dumped).
Can somebody tell me whats wrong here?
This is my struct and adding-method:
struct list_node{
int value;
struct list_node* next;
};
typedef struct list_node node_t;
node_t* add_element_sorted(node_t* head, int v){
node_t* current = head;
node_t* new = NULL;
new = (node_t *) malloc (sizeof(node_t));
if (new == NULL) {
printf("error");
exit(1);
}
new->value = v;
printf("%d\n", new->value);
if (current != NULL){ //check if first node is empty
while(current->value < v){
current = current->next;
printf("broke \n");
if(current->next == NULL){ // check if current node is the last then its next shoud be null
break;
}
}
}
if (current == head) {
new->next = head;
return new;
} else {
new->next = current->next;
current->next = new;
return head;
}
}
At this part it returns me current->next is neither NULL or !NULL. What is current->next now?
if(current->next == NULL){ // check if current node is the last then its next shoud be null
break;
}
My main looks like this:
int main(){
node_t* head = NULL;
head = add_element_sorted(head, 2);
head = add_element_sorted(head, 3);
head = add_element_sorted(head, 4);
head = add_element_sorted(head, 5);
return 0;
}

How to insert a value into a doubly linked list using C

I am just trying to insert a value to a sorted doubly linked list in C.
When I print it out using the following it never shows the newly created node. I created a new node and then set the values and then update the prev and next pointers for the new node and the node that was in front of it. I am sure it has something to do with pass by reference and would like to understand why?
struct NodeType {
int data;
struct NodeType * prev;
struct NodeType * next;
}*head, *last;
void insert_double(int key);
void displayList();
void find_node(int key);
int main()
{
head = NULL;
last = NULL;
/* Create a list with one as value and set as head */
head = (struct NodeType *)malloc(sizeof(struct NodeType));
head->data = 3;
head->prev = NULL;
head->next = NULL;
last = head;
int value=1;
insert_double(value);
printf("0\n");
displayList();
printf("1\n");
value=2;
printf("2\n");
find_node(value);
printf("3\n");
displayList();
return 0;
}
void displayList()
{
struct NodeType * temp;
int n = 1;
if(head == NULL)
{
printf("List is empty.\n");
}
else
{
temp = head;
printf("DATA IN THE LIST:\n");
while(temp != NULL)
{
printf("DATA of %d node = %d\n", n, temp->data);
n++;
/* Move the current pointer to next node */
temp = temp->next;
}
}
}
void find_node(int key)
{
struct NodeType * temp;
struct NodeType * newnode;
newnode->data=key;
if(head == NULL){
printf("No nodes");
}
else{
temp=head;
while(temp!=NULL)
{
if((temp->data)< key){
newnode->prev=temp->prev;
newnode->next=temp;
temp->prev=newnode;
break;
}
else{
temp=temp->next;
}
}
}
}
void insert_double(int key)
{
struct NodeType * newnode;
if(head == NULL)
{
printf("Empty!\n");
}
else
{
newnode = (struct NodeType *)malloc(sizeof(struct NodeType));
newnode->data = key;
newnode->next = head; // Point to next node which is currently head
newnode->prev = NULL; // Previous node of first node is NULL
/* Link previous address field of head with newnode */
head->prev = newnode;
/* Make the new node as head node */
head = newnode;
}
}
Your code is basically correct. You are just missing two important edge cases when dealing with linked list. First is when you are using find_node to insert some value, but it's gonna be add in the beginning in the list. In this case your newly created node becomes a new head of a list so you have to update a head variable. The second edge case is kind of opposite, it happens when you are inserting the new node to the end of the list. Then it becomes an end of a list so you need to update tail.
Missing those two edge cases happens a lot when first working with the linked lists, so don't worry. I think pretty much everybody who worked with linked list made these mistakes in the beginning of his journey.
Moreover you are using the uninitialized pointer to the NodeType structure in find_node:
struct NodeType * newnode;
it should be:
struct NodeType * newnode = (struct NodeType *)malloc(sizeof(struct NodeType));
Thanks to both of you. Here is the solution I came up based on both of your input:
void insert_sorted_node(int key){
struct NodeType * temp = (struct NodeType *)malloc(sizeof(struct NodeType));
struct NodeType * newnode = (struct NodeType *)malloc(sizeof(struct NodeType));
newnode->data=key;
/* no nodes at all*/
/* insert_sorted_node(value) can't start empty list, need to fix */
if(head == NULL){
printf("head =null");
temp = head;
head->data=key;
head->prev=NULL;
head->next=NULL;
last = head;
}
else{
temp=head;
while(temp!=NULL)
{
printf("\n\ndata = %d\nkey = %d\n", temp->data, key);
/* key is new head
1) check if key < head->data
*/
if(key<head->data)
{
printf("\nnew head\n");
newnode->prev = head->prev;
newnode->next = temp;
temp->prev = newnode;
head = newnode;
break;
}
/* key is tail
if temp->next = NULL
*/
else if(temp->next == NULL)
{
printf("\ntail\n");
newnode->prev = temp;
newnode->next = NULL;
temp->next = newnode;
last = newnode;
break;
}
/* key is middle head
if key > temp->data and key< temp->next->data
*/
else if((key>temp->data)&&(key<temp->next->data))
{
printf("\nmiddle\n");
newnode->prev=temp;
newnode->next=temp->next;
temp->next=newnode;
temp->next->prev=newnode;
break;
}
else{
printf("next\n");
temp=temp->next;
}
}
}
}
Your insertion function works fine, as does displayList.
However, the program has undefined behavior in the find_node function:
void find_node(int key)
{
struct NodeType * temp;
struct NodeType * newnode;
newnode->data=key; //<-- BOOM! (writing to uninitialized pointer)
if(head == NULL){
printf("No nodes");
}
else{
temp=head;
while(temp!=NULL)
{
if((temp->data)< key){
newnode->prev=temp->prev; //<-- BOOM!
newnode->next=temp; //<-- BOOM!
temp->prev=newnode;
break;
}
else{
temp=temp->next;
}
}
}
}
It's not really clear what you're trying to achieve there. If this really is a find function, it should not be attempting to perform operations on nodes or copy any data.
All you really need is something like this:
struct NodeType* find_node(int key)
{
for(struct NodeType* temp = head; temp != NULL; temp = temp->next)
{
if (temp->data == key)
return temp;
}
return NULL;
}

Segfault while printing linked list after stack clear

To be more specific, this code is supposed to be a lesser clone of the Unix function dc. The linked list seems to be working fine. If I attempt to use c to clear the memory, add more numbers, then print again with f I get a segfault. It seems to be printing what should be the Null Node in the linked list.
Interaction:
$ ./test
1 2 3
f
3
2
1
c
4 5
f
5
4
0
Segmentation Fault
Here's the code itself:
#include <stdio.h>
#include <stdlib.h>
struct Node{
int val;
struct Node *next;
};
void cons_node(struct Node **head, int num)
{
struct Node *newNode = malloc(sizeof(struct Node));
newNode->val = num;
newNode->next = NULL;
if (*head == NULL){
*head = newNode;
}
else {
newNode->next = *head;
*head = newNode;
}
}
I'm assuming the problem lies here in the display func:
void display_list(struct Node *head)
{
struct Node *current = head;
while(current != NULL)
{
printf("%d\n", current->val);
current = current->next;}
}
void print_top(struct Node *head)
{
printf("%d\n", head->val);
}
or here in the clear func:
void clear_stack(struct Node *head)
{
struct Node *current;
while ((current = head)!= NULL) {
head = head->next;
free(current);
}
}
void vorpal_func(struct Node *head)
{
struct Node *current;
current = head;
free(current);
}
int main(){
int input;
int first = 1;
char quit = 'n';
char inputchar = ' ';
struct Node *head = NULL;
while (quit == 'n'){
if (scanf("%d", &input) == 1){
cons_node(&head, input);
first = 0;
}
else{
inputchar = getchar();
if(first == 1)
printf("List is empty\n");
else{
switch (inputchar){
case 'q':
quit = 'y';
break;
case 'E':
quit = 'y';
break;
case 'f':
display_list(head);
break;
case 'p':
print_top(head);
break;
case 'c':
clear_stack(head);
first = 1;
break;
case 't':
vorpal_func(head);
break;
}
}
}
}
return 0;
}
I've been attempting to figure out the problem for a few hours now. Any tips?
You don't clear your head after calling clear_stack, so when you add your next node, the next pointer is set to something that points into memory that has been freed. Or you could pass a pointer to head to clear_stack if you preferred.
void clear_stack(struct Node **head)
{
while (*head != NULL)
{
Node *current = *head;
*head = current->next;
free(current);
}
}
In passing, cons_node could be written like this
void cons_node(struct Node **head, int num)
{
struct Node *newNode = malloc(sizeof(struct Node));
newNode->val = num;
newNode->next = *head;
*head = newNode;
}

Malloc with scope and global variables

#include<stdio.h>
#include<stdlib.h>
struct node {
int num;
struct node *next;
}*head=NULL, *curr=NULL;
void print(){
curr = head;
while(curr != NULL){
printf("%d\n", curr->num);
curr = curr->next;
}
}
struct node* memAlo(){
return (struct node *)malloc(sizeof(struct node));
}
void addNode(int no){
curr = head;
while(curr != NULL){
curr = curr->next;
}
curr = memAlo();
if(curr == NULL){
printf("\nmemory up\n");
return;
}
else{
curr->num = no;
curr->next = NULL;
printf("%d\n",curr->num);
}
}
void hellop(){
printf("%d", head->num);
}
int main(){
int i;
curr = head;
for(i=1;i<10;i++){
addNode(i);
}
print();
/*head = memAlo();
head->num = 1;
head->next = NULL;
hellop();*/
}
I am sure I have messed up somewhere. The thing is that the head pointer doesn't get the memory allocated by the memAlo() fn() but how to get there? Please help
What I am trying is to create a singly linked list holding numbers from 1 to 9 and to print them using print(). Actually AddNode() is to create single node at the end of the linked list each time the for loop in main() executes.
You set head = NULL at the point where you first defined head. Except in that one place, we never see head on the left-hand side of = anywhere in your program. So of course head is always equal to NULL and never anything else.
You will probably want to insert some code at the start of your addNode function to test whether head == NULL at that point; and if that is true, you will want to assign the result of memAlo() to head instead of curr. You will have to adjust some of the other logic as well.
Your code for allocating a node is wrong. It should create a node, make some space for it, then return it.
struct node *memAlo() {
struct node *nd = malloc(sizeof(*nd));
return nd;
}
This creates a pointer to a node, properly allocates it, then returns it.
Problems I see:
Not dealing with empty list, i.e. when head == NULL.
Creating nodes that are not linked to each other.
curr = memAlo();
allocated memory for a node and returns it to you, but it does not connect the node with anything else.
Try this:
void addNode(int no){
struct node* temp = NULL;
// Deal with an empty list.
if ( head == NULL )
{
head = memAlo();
head->num = no;
head->next = NULL;
}
// Move curr until we reach the last node of the list.
curr = head;
while(curr->next != NULL){
curr = curr->next;
}
temp = memAlo();
if(temp == NULL){
printf("\nmemory up\n");
return;
}
else{
// Link the new node to the previous last node.
temp->num = no;
temp->next = NULL;
printf("%d\n",temp->num);
curr->next = temp;
}
}
It seems that since head is initially NULL, and then you start allocating nodes without saving the address of the first one, you lose the address of the first one, and then can't walk the list from the beginning.
The part you commented out illustrate the problem.
As a side note, there is no free in your program. Remember to always free the memory you alloc
#include<stdio.h>
#include<stdlib.h>
struct node
{
int num;
struct node *next;
};
struct node *head, *curr;
struct node *pos;
void addNode(int n)
{
if(head==NULL)
{
head = (struct node*)malloc(sizeof(struct node));
head->num = n;
head->next = NULL;
curr = head;
}
else
{
while(curr != NULL)
{
pos = curr;
curr = curr->next;
}
curr = (struct node*)malloc(sizeof(struct node));
curr->num = n;
curr->next = NULL;
pos->next = curr;
}
}
void printList()
{
curr = head;
while(curr != NULL)
{
printf("%d",curr->num);
curr = curr->next;
}
}
int main()
{
head = NULL;
curr = head;
int i, a[] = {4,5,1,2,3,9,0};
for(i=0;i<7;i++)
{
addNode(a[i]);
}
curr = head;
printList();
}
This seems to have solved my problem. I figured it out though. Thanks for all your help.

Inserting in Binary Search Tree (C) using for loop

I'm having trouble inserting in a Binary Search Tree using for loop, when I call the InorderTraversal function, there is no output all I get is a blank line, as far as I think rest of the code is okay the only problem is in the insert function.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct BinaryTree{
int data;
struct BinaryTree *left;
struct BinaryTree *right;
} node;
node* Insert(node* head, int value)
{
_Bool flag = true;
for(node *temp = head; flag == true; (temp = (value >= temp->data)?(temp->right):(temp->left)))
{
if(temp == NULL)
{
temp = (node*)malloc(sizeof(node*));
temp->data = value;
temp->left = NULL;
temp->right = NULL;
flag = false;
}
}
return head;
}
void InorderTraversal(node* head)
{
if(head == NULL)
{
return;
}
InorderTraversal(head->left);
printf("%d ",head->data);
InorderTraversal(head->right);
}
int main(void)
{
node *head = NULL;
for(int i = 0; i < 40; i++)
{
head = Insert(head,i);
}
InorderTraversal(head);
return 0;
}
Here try these changes in your Insert function
node* Insert(node *head, int value)
{
if(!head) //Explicitly insert into head if it is NULL
{
head = malloc(sizeof *head);
head->data = value;
head->left = NULL;
head->right = NULL;
return head;
}
for(node *temp = head,*temp2 = head; ;(temp = (value >= temp->data)?(temp->right):(temp->left)))
{
if(temp == NULL)
{
temp = malloc(sizeof *temp);
temp->data = value;
temp->left = NULL;
temp->right = NULL;
if(value >= temp2->data) //update previous nodes left or right pointer accordingly
temp2->right = temp;
else
temp2->left = temp;
break;
}
temp2 = temp; //Use a another pointer to store previous value of node
}
return head;
}
Call me crazy, but shouldn't that malloc(sizeof(node*)) be malloc(sizeof node)?
I am not that so informed, other than being able to read C, so excuse me if this is simply wrong...
Edit: ... or malloc(sizeof * temp)
When you insert the first node you dereference an uninitialized pointer here:
temp->data
Where temp is head and head in uninitialized and pointing to NULL.
So you first have to make special case when head is NULL:
if( !head )
{
head = malloc(sizeof(node));
head->data = value;
head->left = NULL;
head->right = NULL;
return head ;
}
When you continue adding elements you don't update the pointer of the last node. Your for loop should have an extra pointer to the previous node and when you get to the last node and find NULL update the previous nodes left or right pointer.
if(temp == NULL) //wrong, should be: not equal
{
temp = (node*)malloc(sizeof(node*)); //wrong, should be: sizeof the node not the pointer
temp->data = value;
temp->left = NULL;
temp->right = NULL;
flag = false; //use break instead
}
here the previous node pointer left or right is not updated and when you search you can't find any node.

Resources