How to reverse a linked list in pairs - c

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.

Related

Infinite while-loop while printing nodes in linkedlist

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.

Removing an element in a linked list whose value is less than the next adjacent element

Is there any error in this code? I am getting segmentation fault in this.
Question is about deleting elements whose value are less than the next element.
void Remove()
{
struct Node* prev = NULL;
struct Node* curr = head;
struct Node* Next = NULL;
while(curr!=NULL)
{
Next = curr->next;
if(curr->data < Next->data)
{
if(curr == head)
{
struct Node* temp2 = head;
head = head->next;
free(temp2);
curr = head;
//Next = curr->next;
}
else
{
struct Node* temp1 = curr;
prev->next = curr->next;
free(temp1);
curr = Next;
//Next = curr->next;
}
}
else
{
prev = curr;
curr = Next;
//Next = curr->next;
}
}
}
Here is one problem:
while(curr!=NULL)
{
Next = curr->next;
if(curr->data < Next->data)
When you reach the end of the list curr->next is NULL. So Next is NULL. Still you dereference it (i.e. Next->data), so your program will (likely) crash with a seg fault.
You must check for Next being NULL before you access Next->data

Linked List, delete tail function

I am trying to build a head delete and tail delete function for Linked Lists.
I have succeeded in head delete, but my tail delete function does not actually delete the tail.
First, how my Linked List is created:
typedef struct node
{
int data;
struct node *next;
} node;
typedef struct LinkedList
{
node *head;
node *tail;
} LinkedList;
node *createNode(int data)
{
node *new_node;
if ((new_node = malloc(sizeof(node))) == NULL)
return NULL;
new_node->data = data;
new_node->next = NULL;
return new_node;
}
LinkedList *createLinkedList(void)
{
LinkedList *LL;
if ((LL = calloc(1, sizeof(LinkedList))) == NULL)
return NULL;
return LL;
}
void tailInsert(LinkedList *LL, int data)
{
if (LL == NULL)
return;
if (LL->tail == NULL)
{
LL->head = LL->tail = createNode(data);
return;
}
LL->tail->next = createNode(data);
LL->tail = LL->tail->next;
}
These are the two functions:
This one does not work:
int tail_Delete(LinkedList *list)
{
int retval;
node *temp;
if (list == NULL || list->head == NULL)
return EMPTY_LIST_ERR;
// if only one node
if (list->head->next == NULL)
{
retval = list->head->data;
free(list->head);
list->head = NULL;
list->tail = NULL;
return retval;
}
// make temp the node before the tail
for (temp = list->head; temp->next != list->tail; temp = temp->next)
;
retval = list->tail->data;
free(list->tail);
list->tail = temp;
return retval;
}
This one does work:
int head_delete(LinkedList *list)
{
int retval;
node *temp;
if (list == NULL || list->head == NULL)
return EMPTY_LIST_ERR;
retval = list->head->data;
temp = list->head->next;
free (list->head);
list->head = temp;
if (list->head == NULL)
list->tail = NULL;
return retval;
}
Print function and main:
void print_Linked_list(LinkedList *LL)
{
node *temp;
if (LL == NULL || LL->head == NULL)
return;
for (temp = LL->head; temp != NULL; temp = temp->next)
printf("%d%c", temp->data, (temp->next == NULL) ? '\n' : ' ');
}
int main(void)
{
LinkedList *LL;
int val;
LL = createLinkedList();
tailInsert(LL, 1);
tailInsert(LL, 2);
tailInsert(LL, 3);
print_Linked_list(LL);
val = tail_Delete(LL);
//val = head_delete(LL);
printf("%d\n", val);
print_Linked_list(LL);
return 0;
}
Output for head_delete:
1 2 3
Deleted node: 1
2 3
Output for tail_delete:
1 2 3
Deleted node: 3
1 2 3
It may be a simple mistake, but they seem to be practically equivalent functions.
Thank you for your help.
A tail delete needs to be managed from the node before the tail. If you don't have a back pointer in the list (doubly linked), then you'll need to walk forward to the tail.
Untested, tail delete (with no back pointer) should look like this.
LinkedList *node = list->head;
LinkedList *next = node->next;
while(next != list->tail) { // walk to the end
node = next;
next = node->next;
}
// now node is the node before the tail and next is the tail
int retval = next->data;
free(next);
// this is why we needed to walk here
node->next = NULL;
You should assign 0 to temp->next pointer when for loop was executed. By this you indicate that this element is last one.
for (temp = list->head; temp->next != list->tail; temp = temp->next)
;
temp->next = 0; // <---
retval = list->tail->data;

Linked list delete largest

typedef struct _node *Node;
typedef struct _list *List;
typedef struct _list {
Node head;
} list;
typedef struct _node {
int value;
Node next;
} node;
int listDeleteLargest(List l) {
Node meme = l->head;
int largest = meme->value;
while (meme != NULL) {
if (largest < meme->value) {
largest = meme->value;
}
meme = meme->next;
}
Node prev = l->head;
Node temp = prev->next;
Node current = prev->next;
while (current != NULL) {
if (prev->value == largest) {
temp = prev;
prev = prev->next;
l->head = prev;
free(temp);
} else if (current->value == largest) {
if (current->next == NULL) {
prev->next = NULL;
temp = current;
free(temp);
} else {
prev->next = current->next;
current = current->next;
temp = current;
free(temp);
}
}
current = current->next; //runtime error here
}
return 0;
}
//the struct typedef here.
For this code, I'm trying to delete the largest. The logic seems right but i keep getting a runtime error during current = current->next;
For example, if there are two large numbers in the linked list, it'll delete both. I wrote the code on the account that it caters for if the node is at the end, the end and the rest. I've run my tests but I still can't see why it wont compile properly.
If current->value != largest, you end up doing current = current->next twice, and risk running off the end of the list.
Also, this code:
temp = current;
free(temp);
will delete current, because both temp and current will be pointing at the same thing.

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().

Resources