Infinite while-loop while printing nodes in linkedlist - c

If I call createnode(x) in main and then follow that with printNodes(); I will get an infinite while-loop that seems to be printing some memory address. I am guessing the issue lies in the fact that i set head = temp?
SinglyLinkedList *head = NULL;
void createNode(int data){
SinglyLinkedList *temp = malloc(sizeof(SinglyLinkedList));
temp-> data = data;
if(head == NULL){
head = temp;
return;
}
temp->next = head;
head = temp;
}
void printNodes(){
SinglyLinkedList *temp = head;
while ( temp != NULL ){
printf("%d\r\n",temp->data);
temp = temp->next;
}
}

SinglyLinkedList *temp = malloc(sizeof(SinglyLinkedList));
temp->data = data;
if(head == NULL){
head = temp;
return;
}
temp->next = head;
head = temp;
should be
SinglyLinkedList *temp = malloc(sizeof(SinglyLinkedList));
temp->data = data;
temp->next = head; // Moved
if(head == NULL){
head = temp;
return;
}
head = temp;
which is a very complicate way of writing
SinglyLinkedList *temp = malloc(sizeof(SinglyLinkedList));
temp->data = data;
temp->next = head;
head = temp;
Without this fix, printNodes results in undefined behaviour as a result of the lack of initialization of temp->next.

Related

why i get this error when i try to scroll through a list to its last element?

Im trying to resolve the 21. Merge Two Sorted Lists on leetCode. The problem is composed as follows: I have two linked lists already ordered in ascending order and I have to combine them into a single list that is also ordered in ascending order.
This is my code:
struct ListNode *sortList(struct ListNode *headList) {
struct ListNode *ptrHead = headList;
int temp;
if(headList == NULL)
return NULL;
while(ptrHead->next != NULL){
if(ptrHead->val > ptrHead->next->val){
temp = ptrHead->val;
ptrHead->val = ptrHead->next->val;
ptrHead->next->val = temp;
ptrHead = headList;
}else{
ptrHead = ptrHead->next;
}
}
return headList;
}
void addNode(struct ListNode **list, int data){
struct ListNode *newNode = (struct ListNode *) malloc(sizeof (struct ListNode)), *temp = NULL;
if((*list) == NULL){
newNode->val = data;
newNode->next = NULL;
(*list) = newNode;
}else{
temp = (*list);
while (temp->next != NULL){
temp = temp->next;
}
newNode->val = data;
temp->next = newNode;
}
}
struct ListNode *mergeTwoLists(struct ListNode *l1, struct ListNode *l2){
struct ListNode *newList = NULL;
while (l1 != NULL){
addNode(&newList, l1->val);
l1 = l1->next;
}
while (l2 != NULL){
addNode(&newList, l2->val);
l2 = l2->next;
}
return sortList(newList);
}
I tried to run it locally and I had no problem but when I go to run it on the leet code I get an error
The error:
Line 19: Char 20: runtime error: member access within misaligned address
0xbebebebebebebebe for type 'struct ListNode', which requires 8 byte alignment
[solution.c]
0xbebebebebebebebe: note: pointer points here
<memory cannot be printed>
The function addNode has a bug. You forgot to set the data member next to NULL in this code snippet
}else{
temp = (*list);
while (temp->next != NULL){
temp = temp->next;
}
newNode->val = data;
temp->next = newNode;
}
You need to write at least
}else{
temp = (*list);
while (temp->next != NULL){
temp = temp->next;
}
newNode->val = data;
newNode->Next = NULL;
temp->next = newNode;
}
The reason of the error is a duplicated code. I would define the function the following way
int addNode( List **list, int data )
{
struct ListNode *newNode = malloc( sizeof ( *newNode ) );
int success = newNode != NULL;
if ( success )
{
newNode->val = data;
newNode->next = NULL;
while ( *list ) list = &( *list )->next;
*list = newNode;
}
return success;
}
Pay attention to that using two different names for the same entity like List and struct ListNode confuses readers of the code.
And to merge two lists there is no need to create copies of the lists as you are doing in the function mergeTwoLists.

Dereferencing NULL pointer 'head' ,'tail

I made a snake program with Linked List, the program is working but I have some warning, I wonder if I did something wrong or its just something to ignore.The program itself working without any bugs.
I
//Thats what I send from main
SNAKE* snake = (SNAKE*)malloc(sizeof(SNAKE));
//Thats the function
void initialSnaKE(SNAKE* snake){
NODE* tail = (NODE*)(malloc(sizeof(NODE)));
NODE* head = (NODE*)(malloc(sizeof(NODE)));
head->prev = NULL;
tail->prev = head;
head->next = tail;
tail->next = NULL;
head->x = ROWS / 2;
head->y = COLS / 2;
snake->head = head;
snake->tail = tail;
}
There are chances that malloc may fail, that is what compiler is complaining.
You have to have proper NULL checks before dereferencing the pointers.
void initialSnaKE(SNAKE* snake){
if (!snake) return; //invalid input
NODE* tail = (NODE*)(malloc(sizeof(NODE)));
if (!tail) return; //allocation failed.
NODE* head = (NODE*)(malloc(sizeof(NODE)));
if (!head) {
free(tail);
return;
}
head->prev = NULL;
tail->prev = head;
head->next = tail;
tail->next = NULL;
head->x = ROWS / 2;
head->y = COLS / 2;
snake->head = head;
snake->tail = tail;
}

How to reverse a linked list in pairs

I want to reverse a linked list in pair such that if the list is 1->2->3->4->X
then it should output the following 2->1->4->3->X
I have tried to solve this problem but it doesn't seem to run. Guys, can you please help me with what is wrong in my code.
ListNode* reverseListInPairs(ListNode *head){
ListNode *current = head,*newHead = NULL,*temp = NULL,*prev = NULL;
while(current != NULL && current->next != NULL){
temp = current->next;
current->next = current->next->next;
temp->next = current;
prev->next = temp;
prev = current;
current = current->next;
if(newHead == NULL){
newHead = temp;
}
}
return newHead;
}
what is wrong in my code.
The main problem I see is here:
prev->next = temp;
On the first iteration of the loop, prev is still NULL at that point, so you're performing a null-pointer dereference.
You can resolve that issue and also remove the special case for the list head by introducing a synthetic head node in front of the real nodes:
ListNode* reverseListInPairs(ListNode *head) {
ListNode fake_head = { .next = head };
ListNode *prev = &fake_head;
ListNode *current = head;
while (current != NULL && current->next != NULL) {
ListNode *temp = current->next;
current->next = current->next->next;
temp->next = current;
prev->next = temp;
prev = current;
current = current->next;
}
return fake_head.next;
}
I've stuck as close as possible to your original code there, but personally, I'd tighten it up a little further. In particular, you don't need to maintain both current and prev across iterations; just the latter would be sufficient.
ListNode* reverseListInPairs(ListNode *head) {
ListNode fake_head = { .next = head };
ListNode *prev = &fake_head;
while (prev->next && prev->next->next) {
ListNode *first = prev->next;
ListNode *second = first->next;
prev->next = second;
first->next = second->next;
second->next = first;
prev = first;
}
return fake_head.next;
}
Node *reverse (Node *head, int k)
{
Node* current = head;
Node* next = NULL;
Node* prev = NULL;
int count = 0;
while (current != NULL && count < k)
{
next = current->next;
current->next = prev;
prev = current;
current = next;
count++;
}
if (next != NULL)
head->next = reverse(next, k);
return prev;
}
pass the value of k is 2
void pairWiseSwap(struct Node* head)
{
struct Node* temp = head;
/* Traverse further only if there are at-least two nodes left */
while (temp != NULL && temp->next != NULL) {
/* Swap data of node with its next node's data */
swap(&temp->data, &temp->next->data);
/* Move temp by 2 for the next pair */
temp = temp->next->next;
}
}
Sourced from GeeksForGeeks.
As for what is the error, it has been pointed out that prev is already NULL.
ListNode *current = head,*newHead = NULL,*temp = NULL,*prev = NULL;
.
.
prev->next = temp;
We can't have NULL->next as it will throw a segmentation fault.

C - Inserting into linked list in ascending order

I am trying to create a program that inserts numbers into a linked list in ascending order. This is my insert function. It works for inserting some numbers but not others. I think it has something to do with the last part, but i cant figure it out.
node* insert(node* head, int value) {
//check if head hasn't been created
if (head == NULL) {
head = malloc(sizeof(node));
if(head == NULL) {
printf("Failed to create head node");
return head;
}
head->value = value;
head->next = NULL;
return head;
}
//create a new node
node *newNode;
newNode = malloc(sizeof(node));
if(newNode == NULL) {
printf("Failed to create node");
return newNode;
}
newNode->value = value;
newNode->next = NULL;
//see if new node should be placed before head
if (value < head->value) {
newNode->next = head;
return newNode;
}
//search through to find correct spot and insert the node
node *temp = NULL;
temp = head;
while(temp->next != NULL && temp->value < value) {
temp = temp->next;
}
newNode->next = temp->next;
temp->next = newNode;
return head;
}
Part of the following bad
//search through to find correct spot and insert the node
node *temp = NULL;
temp = head;
while(temp->next != NULL && temp->value < value) {
temp = temp->next;
}
newNode->next = temp->next;
temp->next = newNode;
e.g. to fix like this:
node *temp ,*prev;
temp = head;
while(temp != NULL && temp->value <= value) {
prev = temp;
temp = temp->next;
}
newNode->next = temp;
prev->next = newNode;
or
node *temp ,*prev;
temp = head->next;
prev = head;
while(temp != NULL && temp->value < value) {
prev = temp;
temp = temp->next;
}
newNode->next = temp;
prev->next = newNode;
You need to check for temp->next->value inside the last while loop.
//This code of mine works perfectly.
void insertInAscOrder(int val)
{
node *new1;
node *temp;
node *previous;
//create new node
new1 = (node *)malloc(sizeof(node));
//check whether node is created or not
if(new1 == NULL)
{
printf("Insufficient memory.");
return;
}
//Updating different parts of the node
new1 -> info = val;
new1 -> next = NULL;
//checking whether the node created is only node or not
if (start == NULL)
{
start = new1;
}
//If value is less than the value of first node
else if(val < start -> info)
{
new1 -> next = start;
start = new1;
}
else
{
previous = start;
temp = start -> next;
//Go to the position where node is to be inserted
while(temp != NULL && val > temp -> info)
{
previous = temp;
temp = temp -> next;
}
//Insert the node at particular position
if(temp == NULL)
{
previous -> next = new1;
}
else
{
new1 -> next = temp;
previous -> next = new1;
}
}
}
It would be much better if you firstly implement (and test) functions like: push_front(), insert() (insert before), and push_back(), (probably advance (Node* curr, int steps);) and then simply take into consideration all the possibilities of insertion, i.e.:
empty list (current node is first, so just push_front / back())
iterate (advance()) over all elements from head and on, till:
element with value larger than the new is found, insert() before it.
last element reached, push_back().
in your new function insert_ordered().

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