So, I am relatively new to C and trying to implement a Queue using Linked Lists. Here is some code I wrote with help from the internet.
#include <stdio.h>
#include <stdlib.h>
#define pscan(prompt, x) printf(prompt); scanf("%d", &x)
#define nl() printf("\n");
typedef struct Node {
int data;
struct Node* next;
} Node;
typedef struct LinkedList {
Node* head;
Node* tail;
int size;
int (*add) (struct LinkedList*, int, int);
int (*append) (struct LinkedList*, int);
int (*get) (struct LinkedList*, int);
int (*remove) (struct LinkedList*, int);
void (*display_list) (struct LinkedList*);
Node* (*createNode) (int);
} LinkedList;
int add (LinkedList* self, int data, int position);
int append (LinkedList* self, int data);
int get (LinkedList* self, int position);
int rmv (LinkedList* self, int position);
void display_list (LinkedList* self);
LinkedList createLinkedList ();
Node* createNode (int data);
int add(LinkedList* self, int data, int position)
{
if (position > self->size || position < 0)
{
printf("Index out of bounds\n");
return 0;
}
Node* newNode = self->createNode(data);
Node* head = self->head;
Node* tail = self->tail;
if (position == 0)
{
if (head == NULL) self->head = newNode;
else
{
if (tail == NULL) tail = head;
newNode->next = head;
self->head = newNode;
}
self->size++;
}
else if (position == self->size)
{
if (head == NULL) self->head = newNode;
else
{
if (tail == NULL) tail = head;
tail->next = newNode;
self->tail = newNode;
}
self->size++;
}
else
{
Node* prev = head;
for(int i = 0; i < position-1; i++)
{
prev = prev->next;
}
Node* node = prev->next;
prev->next = newNode;
newNode->next = node;
self->size++;
}
return 0;
}
int append(LinkedList* self, int data)
{
return self->add(self, data, self->size);
}
int get(LinkedList* self, int position)
{
if (self->size == 0)
{
printf("The list is empty.");
return 0;
}
else if (position >= self->size || position < 0)
{
printf("Index out of bound.");
return 0;
}
if (position == 0) return self->head->data;
else if (position+1 == self->size) return self->tail->data;
else
{
Node* node = self->head;
for(int i = 0; i < position; i++) node = node->next;
return node->data;
}
}
int rmv (LinkedList* self, int position)
{
int dt;
if (self->size == 0)
{
printf("The list is empty.");
return 0;
}
else if (position >= self->size || position < 0)
{
printf("Index out of bound");
return 0;
}
if (position == 0)
{
Node* head = self->head;
Node* next = head->next;
self->head = next;
dt = head->data;
free(head);
self->size--;
}
else if (position+1 == self->size)
{
Node* node = self->head;
Node* tail = self->tail;
for(int i = 0; i < self->size-2; i++) node = node->next;
node->next = NULL;
self->tail = node;
dt = tail->data;
free(tail);
self->size--;
}
else
{
Node* prev = self->head;
Node* next;
Node* node;
for(int i = 0; i < position-1; i++) prev = prev->next;
node = prev->next;
next = node->next;
prev->next = next;
dt = node->data;
free(node);
self->size--;
}
return dt;
}
void display_list(LinkedList* self)
{
if (self->size == 0) printf("This list is empty.\n\n");
else
{
Node* node = self->head;
printf("[");
for (int i = 0; i < self->size; i++)
{
if (i > 0) printf(", ");
printf("%d", node->data);
node = node->next;
}
printf("]\n\n");
}
}
Node* createNode (int data)
{
Node* node = (Node*) malloc(sizeof(Node));
node->data = data;
node->next = NULL;
return node;
}
LinkedList createLinkedList ()
{
LinkedList l;
l.head = NULL;
l.tail = NULL;
l.add = &add;
l.append = &append;
l.get = &get;
l.remove = &rmv;
l.display_list = &display_list;
l.createNode = &createNode;
l.size = 0;
return l;
}
typedef struct queue
{
LinkedList items;
int *size;
int (*enqueue) (struct queue*, int);
int (*dequeue) (struct queue*);
int (*peek) (struct queue*, int);
void (*display) (struct queue*);
} Queue;
Queue CreateQueue();
int enqueue(Queue* self, int item);
int dequeue(Queue* self);
int peek(Queue* self, int pos);
void display(Queue* self);
Queue CreateQueue()
{
Queue q;
q.items = createLinkedList();
q.size = &(q.items.size);
q.enqueue = &enqueue;
q.dequeue = &dequeue;
q.peek = &peek;
q.display = &display;
return q;
}
int enqueue(Queue* self, int item)
{
self->items.append(&(self->items), item);
return 1;
}
int dequeue(Queue* self)
{
return self->items.remove(&(self->items), 0);
}
int peek(Queue* self, int pos)
{
return self->items.get(&(self->items), pos);
}
void display(Queue* self)
{
printf("%d items in queue.\n", *(self->size));
self->items.display_list(&(self->items));
}
void main()
{
Queue q = CreateQueue();
q.enqueue(&q, 3);
q.enqueue(&q, 7);
q.enqueue(&q, 4);
q.display(&q);
int item = q.dequeue(&q);
printf("Dequeued: %d\n", item);
q.display(&q);
q.enqueue(&q, 14);
q.display(&q);
}
The part I'm having an issue with is making the Queue's size pointer point to the LinkedList's size integer and then accessing that value.
On compiling and running, I get this:
Output from the above code
Thanks in advance.
The problem is in createQueue:
Queue CreateQueue()
{
Queue q;
q.items = createLinkedList();
q.size = &(q.items.size);
q.enqueue = &enqueue;
q.dequeue = &dequeue;
q.peek = &peek;
q.display = &display;
return q;
}
You set q.size to point to q.items.size. This is a pointer to a local variable. You then return a copy of q, but the size member now points to a local that doesn't exist. Dereferencing a pointer to a variable whose lifetime has ended triggers undefined behavior.
There's no need for the size element in Queue. Just access the size element of the items member directly.
[ WOW - Someone gave me and negative point for my question ]
[ You could at least put a comment why you did not like my question ]
I am stuck.
I remember doing something similar in C++ but for some reason, I can't get it to work in plain C.
I'm trying to swap 2 nodes in a singly linked list.
The starting list is populated as [9,8,7,5,3,2] and I'm trying to bubble sort it, 2 nodes at a time to final list of [2,3,5,7,8,9]
The first iteration(swap) works find with the head. The list returns perfect with [8,9,7,5,3,2]
...but in the second iteration, I loose the 7 and get [8,9,5,3,2] which is WTF and I tried changing the code a bit but I have lost hope.
Can someone actually find what I did wrong. Please no double pointers... if it's only possible with double pointers... Why and How? since I have no idea what are double pointers?
Here is my program so far:
/*
___ENTER TITLE HERE___
Author : Patrick Miron
Date : Oct 20, 2021
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef struct listNode
{
int data;
struct listNode *next;
} listNode;
typedef struct list
{
struct listNode *head;
struct listNode *tail;
} list;
int isEmpty( const list *l)
{
return (l == NULL);
}
void printList(list *ptrToList, char *title)
{
int counter = 0; //Counter to count the listItem printed so we can add a carriage return at each 5th element.
printf("%s\n", title);
listNode *ptrToCurrentItem = ptrToList->head;
while (ptrToCurrentItem != NULL)
{
counter++;
printf("%d", ptrToCurrentItem->data);
if (counter % 5 != 0)
{
printf(" : ");
}
else
{
printf("\n");
}
ptrToCurrentItem = ptrToCurrentItem->next;
}
}
list *createListWithHeadData(int data)
{
list *ptrList = malloc((sizeof(ptrList)));
listNode *ptrNewNode = malloc(sizeof(listNode));
ptrNewNode->data = data;
ptrList->head = ptrNewNode;
ptrList->tail = ptrNewNode;
return ptrList;
}
void addToFrontList(list *ptrList, listNode *ptrListNode)
{
listNode *tempPtr = ptrList->head;
ptrList->head = ptrListNode;
ptrListNode->next = tempPtr;
}
list *arrayToList(int data[], int size)
{
list *ptrToNewList = createListWithHeadData(data[0]);
for (int i = 1; i < size; i++)
{
listNode *ptrToNewListNode = malloc(sizeof(listNode));
ptrToNewListNode->data = data[i];
addToFrontList(ptrToNewList, ptrToNewListNode);
}
return ptrToNewList;
}
int count(listNode *ptrToHead)
{
if (ptrToHead == NULL)
{
return 0;
}
else
{
return (1 + count(ptrToHead->next));
}
}
void concat(listNode *head1, listNode *head2)
{
assert(head1 != NULL);
if (head1->next == NULL)
{
head1->next = head2;
}
else
{
concat(head1->next, head2);
}
}
void insert(
listNode *p1, // first element
listNode *p2, // second element
listNode *q) // new element to insert between first and second element
{
assert(p1->next == p2);
p1->next = q;
q->next = p2;
}
void delete(listNode *listNode)
{
assert(listNode != NULL);
listNode = NULL;
}
void deleteList(list *list)
{
if (list->head != NULL)
{
list->head = list->head->next;
deleteList(list);
}
}
void swapListNodeWithNext(listNode *ptrToListNode1)
{
//Swap items
listNode *ptrTempNode1 = ptrToListNode1->next;
listNode *ptrTempNode2 = ptrToListNode1->next->next;
//Set the next node from temp1 (ptrToListNode->next->next) to itself
//Could be written as ptrToListNode->next->next = ptrToListNode
ptrTempNode1->next = ptrToListNode1;
ptrToListNode1->next = ptrTempNode2;
ptrToListNode1 = ptrTempNode1;
ptrTempNode1 = NULL;
ptrTempNode2 = NULL;
}
void sortList(list *ptrToListToSort)
{
if (ptrToListToSort->head == NULL)
{
return;
}
listNode *ptrToCurrentItem = ptrToListToSort->head;
listNode *ptrToLastUnsortedItem = ptrToListToSort->tail;
while (ptrToLastUnsortedItem != ptrToListToSort->head)
{
ptrToCurrentItem = ptrToListToSort->head;
while(ptrToCurrentItem->next != NULL)
{
if (ptrToCurrentItem->data > ptrToCurrentItem->next->data)
{
listNode *ptrToHead = ptrToListToSort->head;
if (ptrToCurrentItem == ptrToListToSort->head)
{
ptrToHead = ptrToCurrentItem->next;
}
//Swap items
swapListNodeWithNext(ptrToCurrentItem);
ptrToListToSort->head = ptrToHead;
}
else
{
ptrToCurrentItem = ptrToCurrentItem->next;
}
}
ptrToLastUnsortedItem = ptrToCurrentItem;
}
}
int main(void)
{
printf("\n");
list listOfInt;
int data[6] = { 2, 3, 5, 7, 8, 9 };
list *ptrToNewList = arrayToList(data, 6);
printList(ptrToNewList, "Array to Element List");
sortList(ptrToNewList);
printList(ptrToNewList, "Sorted List");
printf("\n");
printf("...End of line...\n");
printf("\n");
return 0;
}
I found a couple issues but the major one was that I did not change my previous ptr's next ( ptrPreviousItem->next) to point to the correct item after the swap. I was only changing the pointer to current item which was just a copy of the head advancing thru my iterations and the previous->next was still pointing to the original item.
Why in the world did it work for my first iteration? Probably because I would not update the last item since it was in correct order it would not get updated after that.
I have included a correct version of my singly linked list bubble sort with pointers. It works and I hope it can help the next person. Believe me alot of the tutorial on the subject barely make the code more readable then identifiers like "a" and "b"...
Oh, and #chqrlie, I don't understand some of the corrections you made in my previous question, some of them are quite unnecessary the others were formated like that when I put the code in brackets and the * in pointers can be put where you want. int* likeThis; int * likeThis; or int *likeThis. But I do usually format it like you with the asterix right against the identifier. I use a space between them when I mean the dereferenced value. Cheers!
/*
Singly Linked List Bubble Sort with Pointers
Author : Patrick Miron
Date : Nov 17, 2021
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef struct listNode
{
int data;
struct listNode * next;
} listNode;
typedef struct list
{
struct listNode *head;
struct listNode *tail;
} list;
int isEmpty( const list *l)
{
return (l == NULL);
}
void printList(list *ptrToList, char *title)
{
int counter = 0; //Counter to count the listItem printed so we can add a carriage return at each 5th element.
printf("%s\n", title);
listNode *ptrToCurrentItem = ptrToList->head;
while (ptrToCurrentItem != NULL)
{
counter++;
printf("%d", ptrToCurrentItem->data);
if ((counter % 5) != 0 && (ptrToCurrentItem->next != NULL))
{
printf(" : ");
}
else
{
printf("\n");
}
ptrToCurrentItem = ptrToCurrentItem -> next;
}
}
list *createListWithHeadData(int data)
{
list *ptrList = malloc((sizeof(list)));
listNode *ptrNewNode = malloc(sizeof(listNode));
ptrNewNode->data = data;
ptrNewNode->next = NULL;
ptrList->head = ptrNewNode;
ptrList->tail = ptrNewNode;
return ptrList;
}
void addToFrontList(list *ptrList, listNode *ptrListNode)
{
listNode *tempPtr = ptrList->head;
ptrList->head = ptrListNode;
ptrListNode->next = tempPtr;
}
list *arrayToList(int data[], int size)
{
list *ptrToNewList = createListWithHeadData(data[0]);
for (int i =1; i<size; i++)
{
listNode *ptrToNewListNode = malloc(sizeof(listNode));
ptrToNewListNode->data = data[i];
addToFrontList(ptrToNewList, ptrToNewListNode);
}
return ptrToNewList;
}
int count(listNode *ptrToHead)
{
if (ptrToHead == NULL)
{
return 0;
}
else
{
return (1 + count(ptrToHead->next));
}
}
void concat(listNode *head1, listNode *head2)
{
assert(head1 != NULL);
if (head1->next == NULL)
{
head1->next = head2;
}
else
{
concat(head1->next, head2);
}
}
void insert(
listNode *p1, // first element
listNode *p2, // second element
listNode *q) // new element to insert between first and second element
{
assert(p1->next == p2);
p1->next = q;
q->next = p2;
}
void delete(listNode *listNode)
{
assert(listNode != NULL);
listNode = NULL;
}
void deleteList(list *list)
{
if (list->head != NULL)
{
list->head = list->head->next;
deleteList(list);
}
}
void swapListNodeWithNext(listNode *ptrToCurrentNode, listNode *ptrToPreviousNode)
{
//Swap items
listNode *ptrTempNode1 = ptrToCurrentNode->next;
listNode *ptrTempNode2 = ptrToCurrentNode->next->next;
//Set the next node from temp1 (ptrToListNode->next->next) to itself
//Could be written as ptrToListNode->next->next = ptrToListNode
ptrTempNode1->next = ptrToCurrentNode;
ptrToCurrentNode->next = ptrTempNode2;
ptrToCurrentNode = ptrTempNode1;
if (ptrToPreviousNode != NULL)
{
ptrToPreviousNode->next = ptrToCurrentNode;
}
ptrTempNode1 = NULL;
ptrTempNode2 = NULL;
}
void sortList(list *ptrToListToSort)
{
if (ptrToListToSort->head == NULL)
{
return;
}
listNode *ptrToCurrentItem = ptrToListToSort->head;
listNode *ptrToPreviousItem = NULL;
int sizeOfList = count(ptrToListToSort->head);
int innerLoopCounter = 0;
int unsortedElementLeft = sizeOfList;
listNode *ptrToHead = ptrToListToSort->head;
int swappedAtLeastOneItem = 0;
for (int indexOuterLoop = 0; indexOuterLoop < sizeOfList; indexOuterLoop++)
{
ptrToCurrentItem = ptrToListToSort->head;
while((ptrToCurrentItem->next != NULL) && (innerLoopCounter < unsortedElementLeft))
{
// If the data in the next item greater then the current item, swap nodes.
if (ptrToCurrentItem->data > ptrToCurrentItem->next->data)
{
swappedAtLeastOneItem = 1;
// If the current item is the head of the list, and since it will be swap, point to the next item.
if (ptrToCurrentItem == ptrToListToSort->head)
{
ptrToHead = ptrToCurrentItem->next;
}
//Swap items
swapListNodeWithNext(ptrToCurrentItem, ptrToPreviousItem);
//if the ptrToHead has changed, then update the changes.
if (ptrToListToSort->head != ptrToHead)
{
ptrToListToSort->head = ptrToHead;
}
}
// if the nodes do not need to swap, make sure to update the current item and previous items.
else
{
if (ptrToCurrentItem->next != NULL)
{
ptrToCurrentItem = ptrToCurrentItem->next;
}
}
if (ptrToPreviousItem != NULL)
{
ptrToPreviousItem = ptrToPreviousItem->next;
}
else
{
ptrToPreviousItem = ptrToHead;
}
innerLoopCounter++;
}
// If during the first loop no items were swap then exit early all items are already in order.
if (!swappedAtLeastOneItem)
{
printf("**List is already sorted!**\n");
return;
}
unsortedElementLeft--;
innerLoopCounter=0;
ptrToPreviousItem = NULL;
if (ptrToCurrentItem->next == NULL)
{
ptrToListToSort->tail = ptrToCurrentItem;
}
}
}
int main(void)
{
printf("\n");
int data1[6] = {2,3,5,7,8,9};
list *ptrToNewList = arrayToList(data1,6);
printList(ptrToNewList, "Array to Element List");
sortList(ptrToNewList);
printList(ptrToNewList, "Sorted List");
printf("\n");
printf("----------------------------\n");
printf("\n");
int data2[8] = {10,11,2,3,5,7,8,9};
ptrToNewList = arrayToList(data2,8);
printList(ptrToNewList, "Array to Element List");
sortList(ptrToNewList);
printList(ptrToNewList, "Sorted List");
printf("\n");
printf("\n");
printf("----------------------------\n");
printf("\n");
int data3[10] = {10,11,2,3,5,7,8,1,9,1};
ptrToNewList = arrayToList(data3,10);
printList(ptrToNewList, "Array to Element List");
sortList(ptrToNewList);
printList(ptrToNewList, "Sorted List");
printf("\n");
printf("\n");
printf("----------------------------\n");
printf("\n");
int data4[10] = {1,1,1,1,1,1,1,1,1,1};
ptrToNewList = arrayToList(data4,10);
printList(ptrToNewList, "Array to Element List");
sortList(ptrToNewList);
printList(ptrToNewList, "Sorted List");
printf("\n");
printf("\n");
printf("----------------------------\n");
printf("\n");
int data5[10] = {21,19,16,13,10,9,6,2,1,1};
ptrToNewList = arrayToList(data5,10);
printList(ptrToNewList, "Array to Element List");
sortList(ptrToNewList);
printList(ptrToNewList, "Sorted List");
printf("\n");
printf("\n");
printf("----------------------------\n");
printf("\n");
printf("...End of line...\n");
printf("\n");
return 0;
}
Please note, I did not finish my commenting so don't judge me, I always complete it last.
Hope this helps for anyone having similar issues to me.
Here I have a header file to include functions:
#ifndef driver_h
#define driver_h
#include <stdio.h>
#include <stdlib.h>
typedef struct node node;
typedef struct nodePtrs nodePtrs;
struct node {
node* next;
node* prev;
int data;
};
void sortedInsert(node** top, node* newNode, node** last) {
node* current;
if (*top == NULL) {
*top = newNode;
} else if ((*top)->data >= newNode->data) {
newNode->next = *top;
newNode->next->prev = newNode;
*top = newNode;
if ((*top)->next == NULL) {
*last = *top;
}
} else {
current = *top;
while (current->next != NULL &&
current->next->data < newNode->data) {
current = current->next;
}
newNode->next = current->next;
if (current->next != NULL) {
newNode->next->prev = newNode;
}
current->next = newNode;
newNode->prev = current;
}
if ((*top)->next == NULL) {
*last = *top;
}
}
void insertionSort(node** top, node** last) {
node* sorted = NULL;
node* current = *top;
while (current != NULL) {
node* next = current->next;
current->prev = current->next = NULL;
sortedInsert(&sorted, current, last);
current = next;
}
*top = sorted;
}
node* deleteByPos(node* list, node** last, int position) {
int c = 0;
node* temp;
node* prev;
temp=list;
if (temp==NULL) {
printf("No nodes available to delete\n\n");
return list;
} else {
while(temp!=NULL && c != position) {
prev=temp;
temp=temp->next;
c++;
}
if (temp==NULL) {
printf("Reached end of list, position not available\n\n");
return list;
} else if (temp->next == NULL) {
prev->next=temp->next;
*last = prev;
free(temp);
return list;
} else {
prev->next=temp->next;
temp->next->prev = prev;
free(temp);
return list;
}
}
}
node* makeNode(int n) {
node* np = malloc(sizeof (node));
np->data = n;
np->prev = NULL;
np->next = NULL;
return np;
}
void printList(node* np) {
while (np != NULL) {
printf("%d\n", np->data);
np = np->next;
}
}
void printListReverse(node* np) {
while (np != NULL) {
printf("%d\n", np->data);
np = np->prev;
}
}
#endif /* driver_h */
and a main file:
#include "driver.h"
int main() {
int n;
node* np;
node* top;
node* last;
printf("Enter integers to add to list\n");
do {
if (scanf("%d", &n) != 1) {
n = 0;
}
if (n != 0) {
np = makeNode(n);
if (top == NULL) {
top = np;
} else {
last->next = np;
np->prev = last;
}
last = np;
}
} while (n != 0);
printf("\n\n");
printf("You entered:\n");
printList(top);
printf("\n\n");
printf("In reverse:\n");
printListReverse(last);
printf("\n\n");
printf("Enter a position to delete:");
scanf("%d", &n);
top = deleteByPos(top, &last, n);
printf("\n\n");
printf("In reverse after delete:\n");
printListReverse(last);
insertionSort(&top, &last);
printf("From top after sort:\n");
printList(top);
printf("In reverse after Sort:\n");
printListReverse(last);
}
What this program does is take user input of integers, stores them in a doubly linked list, deletes a node at a user defined point and then performs an insertion sort. What I am trying to do is save a pointer to the last node in the sortedInsert function with the following code:
if ((*top)->next == NULL) {
*last = *top;
}
However, if you enter 6 5 3 1 9 8 4 2 7 4 2, then delete at position 2, when printing in reverse it prints out 6 5 4 4 2 2 1. For some reason it skips over 9 7 8. I cannot figure out why or how to fix this. How can I do this properly?
With lists, it helps to draw a diagram for all the cases. It's natural to use induction on lists to prove your code is correct.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h> /* Asserting is useful when it come to lists especially. */
struct node {
struct node* next;
struct node* prev;
int data;
};
/* Saves you from dealing with 'top' and 'tail' every time. */
struct list {
struct node *head, *tail;
};
/* https://en.wikipedia.org/wiki/Insertion_sort */
void insertionSort(struct list* list) {
struct node* i = list->head, *j0, *j1;
while(i) {
j1 = i, j0 = j1->prev;
while(j0 && j0->data > j1->data) {
/* Swap. */
int temp = j0->data;
j0->data = j1->data;
j1->data = temp;
/* Decrement. */
j1 = j0;
j0 = j0->prev;
}
i = i->next;
}
}
/* Returns whether the position was deleted. */
int deleteByPos(struct list* list, int position) {
struct node* n;
assert(list);
/* Node n is the position's in the list. */
for(n = list->head; n && position; n = n->next, position--);
if (n==NULL) {
printf("No nodes available to delete\n\n");
return 0;
}
/* Fixme: If I'm not mistaken, there are 9 cases for you to be
mathematically certain this works, and I haven't tried them all.
Eg, 1 node, 2 nodes x2, 3 nodes x3, where the internal node is the 2nd of
the 3 nodes. */
if(n->prev == NULL) {
/* The first one. */
assert(list->head == n);
list->head = n->next;
if(n->next) n->next->prev = NULL;
} else {
/* Skip over. */
n->prev->next = n->next;
}
if(n->next == NULL) {
/* The last one. */
assert(list->tail == n);
list->tail = n->prev;
if(n->prev) n->prev->next = NULL;
} else {
/* Skip over. */
n->next->prev = n->prev;
}
n->prev = n->next = NULL; /* Helps in debugging. */
free(n);
return 1;
}
struct node* makeNode(struct list *list, int n) {
struct node* np = malloc(sizeof *np);
if(!np) return 0;
np->data = n;
np->prev = list->tail;
np->next = NULL;
/* Push it in the list. */
if(list->tail) {
assert(list->head != NULL && list->tail->next == NULL);
list->tail->next = np;
} else {
/* The first one. */
assert(list->head == NULL && list->tail == NULL);
list->head = np;
}
list->tail = np;
return np;
}
void printList(const struct list*const list) {
const struct node *n = list->head;
while (n) {
printf("%d\n", n->data);
n = n->next;
}
}
void printListReverse(const struct list*const list) {
const struct node *n = list->tail;
while (n) {
printf("%d\n", n->data);
n = n->prev;
}
}
int main(void) {
int n;
struct list list = { 0, 0 };
printf("Enter integers to add to list\n");
while(scanf("%d", &n) == 1 && n)
if(!makeNode(&list, n)) return perror("node"), EXIT_FAILURE;
printf("\n\n");
printf("You entered:\n");
printList(&list);
printf("\n\n");
printf("In reverse:\n");
printListReverse(&list);
printf("\n\n");
printf("Enter a position to delete:");
scanf("%d", &n);
printf("You entered %d.\n", n);
deleteByPos(&list, n);
printf("\n\n");
printf("In reverse after delete:\n");
printListReverse(&list);
insertionSort(&list);
printf("From top after sort:\n");
printList(&list);
printf("In reverse after Sort:\n");
printListReverse(&list);
return EXIT_SUCCESS;
}
*One would ideally free memory on exit.
It is usually much simpler to use a sentinel node rather than NULL to indicate the end of a list. So an empty list consists of a node whose head and tail point to itself. Once you add elements, sentinel->next is the first in the list and sentinel->prev is the last in the list. This removes many of the cases you have to test for NULL in your code:
#ifndef driver_h
#define driver_h
#include <stdio.h>
#include <stdlib.h>
typedef struct node node;
typedef struct nodePtrs nodePtrs;
struct node {
node* next;
node* prev;
int data;
};
void sortedInsert(node* top, node* newNode) {
node* current = top;
while (current->next != top &&
current->next->data < newNode->data) {
current = current->next;
}
newNode->next = current->next;
newNode->next->prev = newNode;
current->next = newNode;
current->next->prev = current;
}
void insertionSort(node* top) {
node* current = top->next;
// make top an empty ring so can append to it
top->next = top->prev = top;
while (current != top) {
node* next = current->next;
sortedInsert(top, current);
current = next;
}
}
node* deleteByPos(node* top,int position) {
int c = 0;
node* temp = top->next;
while (true) {
if (temp == top) {
printf("Reached end of list, position not available\n\n");
return top;
}
if (c == position) {
temp->prev->next = temp->next;
temp->next->prev = temp->prev;
free(temp);
return top;
}
temp = temp->next;
c++;
}
}
node* makeNode(int n) {
node* np = malloc(sizeof(node));
np->data = n;
np->prev = np;
np->next = np;
return np;
}
void printList(node* top) {
for (node* np = top->next; np != top; np = np->next) {
printf("%d\n", np->data);
}
}
void printListReverse(node* top) {
for (node* np = top->prev; np != top; np = np->prev) {
printf("%d\n", np->data);
}
}
#endif /* driver_h */
main file :
#include "driver.h"
int main() {
int n;
node* np;
node* top;
top= makeNode(0);
printf("Enter integers to add to list\n");
do {
if (scanf_s("%d", &n) != 1) {
n = 0;
}
if (n != 0) {
np = makeNode(n);
np->prev = top->prev;
top->prev = np;
top->prev->next = top;
np->prev->next = np;
}
} while (n != 0);
I wonder if there exists some logic to reverse a singly-linked list using only two pointers.
The following is used to reverse the single linked list using three pointers namely p, q, r:
struct node {
int data;
struct node *link;
};
void reverse() {
struct node *p = first,
*q = NULL,
*r;
while (p != NULL) {
r = q;
q = p;
p = p->link;
q->link = r;
}
first = q;
}
Is there any other alternate to reverse the linked list? What would be the best logic to reverse a singly linked list, in terms of time complexity?
Any alternative? No, this is as simple as it gets, and there's no fundamentally-different way of doing it. This algorithm is already O(n) time, and you can't get any faster than that, as you must modify every node.
It looks like your code is on the right track, but it's not quite working in the form above. Here's a working version:
#include <stdio.h>
typedef struct Node {
char data;
struct Node* next;
} Node;
void print_list(Node* root) {
while (root) {
printf("%c ", root->data);
root = root->next;
}
printf("\n");
}
Node* reverse(Node* root) {
Node* new_root = 0;
while (root) {
Node* next = root->next;
root->next = new_root;
new_root = root;
root = next;
}
return new_root;
}
int main() {
Node d = { 'd', 0 };
Node c = { 'c', &d };
Node b = { 'b', &c };
Node a = { 'a', &b };
Node* root = &a;
print_list(root);
root = reverse(root);
print_list(root);
return 0;
}
I hate to be the bearer of bad news but I don't think your three-pointer solution actually works. When I used it in the following test harness, the list was reduced to one node, as per the following output:
==========
4
3
2
1
0
==========
4
==========
You won't get better time complexity than your solution since it's O(n) and you have to visit every node to change the pointers, but you can do a solution with only two extra pointers quite easily, as shown in the following code:
#include <stdio.h>
// The list element type and head.
struct node {
int data;
struct node *link;
};
static struct node *first = NULL;
// A reverse function which uses only two extra pointers.
void reverse() {
// curNode traverses the list, first is reset to empty list.
struct node *curNode = first;
first = NULL;
// Until no more in list, insert current before first and advance.
while (curNode != NULL) {
// Need to save next node since we're changing the current.
struct node *nxtNode = curNode->link;
// Insert at start of new list.
curNode->link = first;
first = curNode;
// Advance to next.
curNode = nxtNode;
}
}
// Code to dump the current list.
static void dumpNodes() {
struct node *curNode = first;
printf ("==========\n");
while (curNode != NULL) {
printf ("%d\n", curNode->data);
curNode = curNode->link;
}
}
// Test harness main program.
int main (void) {
int i;
struct node *newnode;
// Create list (using actually the same insert-before-first
// that is used in reverse function.
for (i = 0; i < 5; i++) {
newnode = malloc (sizeof (struct node));
newnode->data = i;
newnode->link = first;
first = newnode;
}
// Dump list, reverse it, then dump again.
dumpNodes();
reverse();
dumpNodes();
printf ("==========\n");
return 0;
}
This code outputs:
==========
4
3
2
1
0
==========
0
1
2
3
4
==========
which I think is what you were after. It can actually do this since, once you've loaded up first into the pointer traversing the list, you can re-use first at will.
#include <stddef.h>
typedef struct Node {
struct Node *next;
int data;
} Node;
Node * reverse(Node *cur) {
Node *prev = NULL;
while (cur) {
Node *temp = cur;
cur = cur->next; // advance cur
temp->next = prev;
prev = temp; // advance prev
}
return prev;
}
Here's the code to reverse a singly linked list in C.
And here it is pasted below:
// reverse.c
#include <stdio.h>
#include <assert.h>
typedef struct node Node;
struct node {
int data;
Node *next;
};
void spec_reverse();
Node *reverse(Node *head);
int main()
{
spec_reverse();
return 0;
}
void print(Node *head) {
while (head) {
printf("[%d]->", head->data);
head = head->next;
}
printf("NULL\n");
}
void spec_reverse() {
// Create a linked list.
// [0]->[1]->[2]->NULL
Node node2 = {2, NULL};
Node node1 = {1, &node2};
Node node0 = {0, &node1};
Node *head = &node0;
print(head);
head = reverse(head);
print(head);
assert(head == &node2);
assert(head->next == &node1);
assert(head->next->next == &node0);
printf("Passed!");
}
// Step 1:
//
// prev head next
// | | |
// v v v
// NULL [0]->[1]->[2]->NULL
//
// Step 2:
//
// prev head next
// | | |
// v v v
// NULL<-[0] [1]->[2]->NULL
//
Node *reverse(Node *head)
{
Node *prev = NULL;
Node *next;
while (head) {
next = head->next;
head->next = prev;
prev = head;
head = next;
}
return prev;
}
Robert Sedgewick, "Algorithms in C", Addison-Wesley, 3rd Edition, 1997, [Section 3.4]
In case that is not a cyclic list ,hence NULL is the last link.
typedef struct node* link;
struct node{
int item;
link next;
};
/* you send the existing list to reverse() and returns the reversed one */
link reverse(link x){
link t, y = x, r = NULL;
while(y != NULL){
t = y->next;
y-> next = r;
r = y;
y = t;
}
return r;
}
Yes. I'm sure you can do this the same way you can swap two numbers without using a third. Simply cast the pointers to a int/long and perform the XOR operation a couple of times. This is one of those C tricks that makes for a fun question, but doesn't have any practical value.
Can you reduce the O(n) complexity? No, not really. Just use a doubly linked list if you think you are going to need the reverse order.
Just for fun (although tail recursion optimization should stop it eating all the stack):
Node* reverse (Node *root, Node *end) {
Node *next = root->next;
root->next = end;
return (next ? reverse(next, root) : root);
}
root = reverse(root, NULL);
You need a track pointer which will track the list.
You need two pointers :
first pointer to pick first node.
second pointer to pick second node.
Processing :
Move Track Pointer
Point second node to first node
Move First pointer one step, by assigning second pointer to one
Move Second pointer one step, By assigning Track pointer to second
Node* reverselist( )
{
Node *first = NULL; // To keep first node
Node *second = head; // To keep second node
Node *track = head; // Track the list
while(track!=NULL)
{
track = track->next; // track point to next node;
second->next = first; // second node point to first
first = second; // move first node to next
second = track; // move second node to next
}
track = first;
return track;
}
How about the more readable:
Node *pop (Node **root)
{
Node *popped = *root;
if (*root) {
*root = (*root)->next;
}
return (popped);
}
void push (Node **root, Node *new_node)
{
new_node->next = *root;
*root = new_node;
}
Node *reverse (Node *root)
{
Node *new_root = NULL;
Node *next;
while ((next = pop(&root))) {
push (&new_root, next);
}
return (new_root);
}
To swap two variables without the use of a temporary variable,
a = a xor b
b = a xor b
a = a xor b
fastest way is to write it in one line
a = a ^ b ^ (b=a)
Similarly,
using two swaps
swap(a,b)
swap(b,c)
solution using xor
a = a^b^c
b = a^b^c
c = a^b^c
a = a^b^c
solution in one line
c = a ^ b ^ c ^ (a=b) ^ (b=c)
b = a ^ b ^ c ^ (c=a) ^ (a=b)
a = a ^ b ^ c ^ (b=c) ^ (c=a)
The same logic is used to reverse a linked list.
typedef struct List
{
int info;
struct List *next;
}List;
List* reverseList(List *head)
{
p=head;
q=p->next;
p->next=NULL;
while(q)
{
q = (List*) ((int)p ^ (int)q ^ (int)q->next ^ (int)(q->next=p) ^ (int)(p=q));
}
head = p;
return head;
}
Here's a simpler version in Java. It does use only two pointers curr & prev
public void reverse(Node head) {
Node curr = head, prev = null;
while (head.next != null) {
head = head.next; // move the head to next node
curr.next = prev; //break the link to the next node and assign it to previous
prev = curr; // we are done with previous, move it to next node
curr = head; // current moves along with head
}
head.next = prev; //for last node
}
Work out the time complexity of the algorithm you are using now and it should be obvious that it can not be improved.
I don't understand why there is need to return head as we are passing it as argument. We are passing head of the link list then we can update also. Below is simple solution.
#include<stdio.h>
#include<conio.h>
struct NODE
{
struct NODE *next;
int value;
};
typedef struct NODE node;
void reverse(node **head);
void add_end(node **head,int val);
void alloc(node **p);
void print_all(node *head);
void main()
{
node *head;
clrscr();
head = NULL;
add_end( &head, 1 );
add_end( &head, 2 );
add_end( &head, 3 );
print_all( head );
reverse( &head );
print_all( head );
getch();
}
void alloc(node **p)
{
node *temp;
temp = (node *) malloc( sizeof(node *) );
temp->next = NULL;
*p = temp;
}
void add_end(node **head,int val)
{
node *temp,*new_node;
alloc(&new_node);
new_node->value = val;
if( *head == NULL )
{
*head = new_node;
return;
}
for(temp = *head;temp->next!=NULL;temp=temp->next);
temp->next = new_node;
}
void print_all(node *head)
{
node *temp;
int index=0;
printf ("\n\n");
if (head == NULL)
{
printf (" List is Empty \n");
return;
}
for (temp=head; temp != NULL; temp=temp->next,index++)
printf (" %d ==> %d \n",index,temp->value);
}
void reverse(node **head)
{
node *next,*new_head;
new_head=NULL;
while(*head != NULL)
{
next = (*head)->next;
(*head)->next = new_head;
new_head = (*head);
(*head) = next;
}
(*head)=new_head;
}
#include <stdio.h>
#include <malloc.h>
tydef struct node
{
int info;
struct node *link;
} *start;
void main()
{
rev();
}
void rev()
{
struct node *p = start, *q = NULL, *r;
while (p != NULL)
{
r = q;
q = p;
p = p->link;
q->link = r;
}
start = q;
}
curr = head;
prev = NULL;
while (curr != NULL) {
next = curr->next; // store current's next, since it will be overwritten
curr->next = prev;
prev = curr;
curr = next;
}
head = prev; // update head
No, nothing faster than the current O(n) can be done. You need to alter every node, so time will be proportional to the number of elements anyway and that's O(n) you already have.
Using two pointers while maintaining time complexity of O(n), the fastest achievable, might only be possible through number casting of pointers and swapping their values. Here is an implementation:
#include <stdio.h>
typedef struct node
{
int num;
struct node* next;
}node;
void reverse(node* head)
{
node* ptr;
if(!head || !head->next || !head->next->next) return;
ptr = head->next->next;
head->next->next = NULL;
while(ptr)
{
/* Swap head->next and ptr. */
head->next = (unsigned)(ptr =\
(unsigned)ptr ^ (unsigned)(head->next =\
(unsigned)head->next ^ (unsigned)ptr)) ^ (unsigned)head->next;
/* Swap head->next->next and ptr. */
head->next->next = (unsigned)(ptr =\
(unsigned)ptr ^ (unsigned)(head->next->next =\
(unsigned)head->next->next ^ (unsigned)ptr)) ^ (unsigned)head->next->next;
}
}
void add_end(node* ptr, int n)
{
while(ptr->next) ptr = ptr->next;
ptr->next = malloc(sizeof(node));
ptr->next->num = n;
ptr->next->next = NULL;
}
void print(node* ptr)
{
while(ptr = ptr->next) printf("%d ", ptr->num);
putchar('\n');
}
void erase(node* ptr)
{
node *end;
while(ptr->next)
{
if(ptr->next->next) ptr = ptr->next;
else
{
end = ptr->next;
ptr->next = NULL;
free(end);
}
}
}
void main()
{
int i, n = 5;
node* dummy_head;
dummy_head->next = NULL;
for(i = 1; i <= n ; ++i) add_end(dummy_head, i);
print(dummy_head);
reverse(dummy_head);
print(dummy_head);
erase(dummy_head);
}
I have a slightly different approach. I wanted to make use of the existing functions (like insert_at(index), delete_from(index)) to reverse the list (something like a right shift operation). The complexity is still O(n) but the advantage is more reused code. Have a look at another_reverse() method and let me know what you all think.
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node* next;
};
struct node* head = NULL;
void printList(char* msg) {
struct node* current = head;
printf("\n%s\n", msg);
while (current != NULL) {
printf("%d ", current->data);
current = current->next;
}
}
void insert_beginning(int data) {
struct node* newNode = (struct node*) malloc(sizeof(struct node));
newNode->data = data;
newNode->next = NULL;
if (head == NULL)
{
head = newNode;
} else {
newNode->next = head;
head = newNode;
}
}
void insert_at(int data, int location) {
struct node* newNode = (struct node*) malloc(sizeof(struct node));
newNode->data = data;
newNode->next = NULL;
if (head == NULL)
{
head = newNode;
}
else {
struct node* currentNode = head;
int index = 0;
while (currentNode != NULL && index < (location - 1)) {
currentNode = currentNode->next;
index++;
}
if (currentNode != NULL)
{
if (location == 0) {
newNode->next = currentNode;
head = newNode;
} else {
newNode->next = currentNode->next;
currentNode->next = newNode;
}
}
}
}
int delete_from(int location) {
int retValue = -1;
if (location < 0 || head == NULL)
{
printf("\nList is empty or invalid index");
return -1;
} else {
struct node* currentNode = head;
int index = 0;
while (currentNode != NULL && index < (location - 1)) {
currentNode = currentNode->next;
index++;
}
if (currentNode != NULL)
{
// we've reached the node just one prior to the one we want to delete
if (location == 0) {
if (currentNode->next == NULL)
{
// this is the only node in the list
retValue = currentNode->data;
free(currentNode);
head = NULL;
} else {
// the next node should take its place
struct node* nextNode = currentNode->next;
head = nextNode;
retValue = currentNode->data;
free(currentNode);
}
} // if (location == 0)
else {
// the next node should take its place
struct node* nextNode = currentNode->next;
currentNode->next = nextNode->next;
if (nextNode != NULL
) {
retValue = nextNode->data;
free(nextNode);
}
}
} else {
printf("\nInvalid index");
return -1;
}
}
return retValue;
}
void another_reverse() {
if (head == NULL)
{
printf("\nList is empty\n");
return;
} else {
// get the tail pointer
struct node* tailNode = head;
int index = 0, counter = 0;
while (tailNode->next != NULL) {
tailNode = tailNode->next;
index++;
}
// now tailNode points to the last node
while (counter != index) {
int data = delete_from(index);
insert_at(data, counter);
counter++;
}
}
}
int main(int argc, char** argv) {
insert_beginning(4);
insert_beginning(3);
insert_beginning(2);
insert_beginning(1);
insert_beginning(0);
/* insert_at(5, 0);
insert_at(4, 1);
insert_at(3, 2);
insert_at(1, 1);*/
printList("Original List\0");
//reverse_list();
another_reverse();
printList("Reversed List\0");
/* delete_from(2);
delete_from(2);*/
//printList();
return 0;
}
using 2-pointers....bit large but simple and efficient
void reverse()
{
int n=0;
node *temp,*temp1;
temp=strptr;
while(temp->next!=NULL)
{
n++; //counting no. of nodes
temp=temp->next;
}
// we will exchange ist by last.....2nd by 2nd last so.on....
int i=n/2;
temp=strptr;
for(int j=1;j<=(n-i+1);j++)
temp=temp->next;
// i started exchanging from in between ....so we do no have to traverse list so far //again and again for exchanging
while(i>0)
{
temp1=strptr;
for(int j=1;j<=i;j++)//this loop for traversing nodes before n/2
temp1=temp1->next;
int t;
t=temp1->info;
temp1->info=temp->info;
temp->info=t;
i--;
temp=temp->next;
//at the end after exchanging say 2 and 4 in a 5 node list....temp will be at 5 and we will traverse temp1 to ist node and exchange ....
}
}
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
struct node
{
int data;
struct node *link;
};
struct node *first=NULL,*last=NULL,*next,*pre,*cur,*temp;
void create()
{
cur=(struct node*) malloc(sizeof(struct node));
printf("enter first data to insert");
scanf("%d",&cur->data);
first=last=cur;
first->link=NULL;
}
void insert()
{
int pos,c;
cur=(struct node*) malloc(sizeof(struct node));
printf("enter data to insert and also its position");
scanf("%d%d",&cur->data,&pos);
if(pos==1)
{
cur->link=first;
first=cur;
}
else
{
c=1;
next=first;
while(c<pos)
{
pre=next;
next=next->link;
c++;
}
if(pre==NULL)
{
printf("Invalid position");
}
else
{
cur->link=pre->link;
pre->link=cur;
}
}
}
void display()
{
cur=first;
while(cur!=NULL)
{
printf("data= %d\t address= %u\n",cur->data,cur);
cur=cur->link;
}
printf("\n");
}
void rev()
{
pre=NULL;
cur=first;
while(cur!=NULL)
{
next=cur->link;
cur->link=pre;
pre=cur;
cur=next;
}
first=pre;
}
void main()
{
int choice;
clrscr();
do
{
printf("Options are: -\n1:Create\n2:Insert\n3:Display\n4:Reverse\n0:Exit\n");
printf("Enter your choice: - ");
scanf("%d",&choice);
switch(choice)
{
case 1:
create();
break;
case 2:
insert();
break;
case 3:
display();
break;
case 4:
rev();
break;
case 0:
exit(0);
default:
printf("wrong choice");
}
}
while(1);
}
Yes there is a way using only two pointers. That is by creating new linked list where the first node is the first node of the given list and second node of the first list is added at the start of the new list and so on.
Here is my version:
void reverse(ListElem *&head)
{
ListElem* temp;
ListElem* elem = head->next();
ListElem* prev = head;
head->next(0);
while(temp = elem->next())
{
elem->next(prev);
prev = elem;
elem = temp;
}
elem->next(prev);
head = elem;
}
where
class ListElem{
public:
ListElem(int val): _val(val){}
ListElem *next() const { return _next; }
void next(ListElem *elem) { _next = elem; }
void val(int val){ _val = val; }
int val() const { return _val;}
private:
ListElem *_next;
int _val;
};
I am using java to implement this and approach is test driven development hence test cases are also attached.
The Node class that represent single node -
package com.adnan.linkedlist;
/**
* User : Adnan
* Email : sendtoadnan#gmail.com
* Date : 9/21/13
* Time : 12:02 PM
*/
public class Node {
public Node(int value, Node node){
this.value = value;
this.node = node;
}
private int value;
private Node node;
public int getValue() {
return value;
}
public Node getNode() {
return node;
}
public void setNode(Node node){
this.node = node;
}
}
Service class that takes start node as input and reserve it without using extra space.
package com.adnan.linkedlist;
/**
* User : Adnan
* Email : sendtoadnan#gmail.com
* Date : 9/21/13
* Time : 11:54 AM
*/
public class SinglyLinkedListReversal {
private static final SinglyLinkedListReversal service
= new SinglyLinkedListReversal();
public static SinglyLinkedListReversal getService(){
return service;
}
public Node reverse(Node start){
if (hasOnlyNodeInLinkedList(start)){
return start;
}
Node firstNode, secondNode, thirdNode;
firstNode = start;
secondNode = firstNode.getNode();
while (secondNode != null ){
thirdNode = secondNode.getNode();
secondNode.setNode(firstNode);
firstNode = secondNode;
secondNode = thirdNode;
}
start.setNode(null);
return firstNode;
}
private boolean hasOnlyNodeInLinkedList(Node start) {
return start.getNode() == null;
}
}
And The test case that covers above scenario. Please note that you require junit jars. I am using testng.jar; you can use any whatever pleases you..
package com.adnan.linkedlist;
import org.testng.annotations.Test;
import static org.testng.AssertJUnit.assertTrue;
/**
* User : Adnan
* Email : sendtoadnan#gmail.com
* Date : 9/21/13
* Time : 12:11 PM
*/
public class SinglyLinkedListReversalTest {
private SinglyLinkedListReversal reversalService =
SinglyLinkedListReversal.getService();
#Test
public void test_reverseSingleElement() throws Exception {
Node node = new Node(1, null);
reversalService.reverse(node);
assertTrue(node.getNode() == null);
assertTrue(node.getValue() == 1);
}
//original - Node1(1) -> Node2(2) -> Node3(3)
//reverse - Node3(3) -> Node2(2) -> Node1(1)
#Test
public void test_reverseThreeElement() throws Exception {
Node node3 = new Node(3, null);
Node node2 = new Node(2, node3);
Node start = new Node(1, node2);
start = reversalService.reverse(start);
Node test = start;
for (int i = 3; i >=1 ; i -- ){
assertTrue(test.getValue() == i);
test = test.getNode();
}
}
#Test
public void test_reverseFourElement() throws Exception {
Node node4 = new Node(4, null);
Node node3 = new Node(3, node4);
Node node2 = new Node(2, node3);
Node start = new Node(1, node2);
start = reversalService.reverse(start);
Node test = start;
for (int i = 4; i >=1 ; i -- ){
assertTrue(test.getValue() == i);
test = test.getNode();
}
}
#Test
public void test_reverse10Element() throws Exception {
Node node10 = new Node(10, null);
Node node9 = new Node(9, node10);
Node node8 = new Node(8, node9);
Node node7 = new Node(7, node8);
Node node6 = new Node(6, node7);
Node node5 = new Node(5, node6);
Node node4 = new Node(4, node5);
Node node3 = new Node(3, node4);
Node node2 = new Node(2, node3);
Node start = new Node(1, node2);
start = reversalService.reverse(start);
Node test = start;
for (int i = 10; i >=1 ; i -- ){
assertTrue(test.getValue() == i);
test = test.getNode();
}
}
#Test
public void test_reverseTwoElement() throws Exception {
Node node2 = new Node(2, null);
Node start = new Node(1, node2);
start = reversalService.reverse(start);
Node test = start;
for (int i = 2; i >=1 ; i -- ){
assertTrue(test.getValue() == i);
test = test.getNode();
}
}
}
A simple algorithm if you use the linked list as a stack structure:
#include <stdio.h>
#include <stdlib.h>
typedef struct list {
int key;
char value;
struct list* next;
} list;
void print(list*);
void add(list**, int, char);
void reverse(list**);
void deleteList(list*);
int main(void) {
list* head = NULL;
int i=0;
while ( i++ < 26 ) add(&head, i, i+'a');
printf("Before reverse: \n");
print(head);
printf("After reverse: \n");
reverse(&head);
print(head);
deleteList(head);
}
void deleteList(list* l) {
list* t = l;
while ( t != NULL ) {
list* tmp = t;
t = t->next;
free(tmp);
}
}
void print(list* l) {
list* t = l;
while ( t != NULL) {
printf("%d:%c\n", t->key, t->value);
t = t->next;
}
}
void reverse(list** head) {
list* tmp = *head;
list* reversed = NULL;
while ( tmp != NULL ) {
add(&reversed, tmp->key, tmp->value);
tmp = tmp->next;
}
deleteList(*head);
*head = reversed;
}
void add(list** head, int k, char v) {
list* t = calloc(1, sizeof(list));
t->key = k; t->value = v;
t->next = *head;
*head = t;
}
The performance may be affected since additional function call to the add and malloc so the algorithms of address swaps are better but that one actually creates new list so you can use additional options like sort or remove items if you add a callback function as parameter to the reverse.
Here is a slightly different, but simple approach in C++11:
#include <iostream>
struct Node{
Node(): next(NULL){}
Node *next;
std::string data;
};
void printlist(Node* l){
while(l){
std::cout<<l->data<<std::endl;
l = l->next;
}
std::cout<<"----"<<std::endl;
}
void reverse(Node*& l)
{
Node* prev = NULL;
while(l){
auto next = l->next;
l->next = prev;
prev=l;
l=next;
}
l = prev;
}
int main() {
Node s,t,u,v;
s.data = "1";
t.data = "2";
u.data = "3";
v.data = "4";
s.next = &t;
t.next = &u;
u.next = &v;
Node* ptr = &s;
printlist(ptr);
reverse(ptr);
printlist(ptr);
return 0;
}
Output here
Following is one implementation using 2 pointers (head and r)
ListNode * reverse(ListNode* head) {
ListNode *r = NULL;
if(head) {
r = head->next;
head->next = NULL;
}
while(r) {
head = reinterpret_cast<ListNode*>(size_t(head) ^ size_t(r->next));
r->next = reinterpret_cast<ListNode*>(size_t(r->next) ^ size_t(head));
head = reinterpret_cast<ListNode*>(size_t(head) ^ size_t(r->next));
head = reinterpret_cast<ListNode*>(size_t(head) ^ size_t(r));
r = reinterpret_cast<ListNode*>(size_t(r) ^ size_t(head));
head = reinterpret_cast<ListNode*>(size_t(head) ^ size_t(r));
}
return head;
}
here is a little simple solution...
void reverse()
{
node * pointer1 = head->next;
if(pointer1 != NULL)
{
node *pointer2 = pointer1->next;
pointer1->next = head;
head->next = NULL;
head = pointer1;
if(pointer2 != NULL)
{
while(pointer2 != NULL)
{
pointer1 = pointer2;
pointer2 = pointer2->next;
pointer1->next = head;
head = pointer1;
}
pointer1->next = head;
head = pointer1;
}
}
}
You can have solution of this problem with help of only one extra pointer, that has to be static for the reverse function. It's in O(n) complexity.
#include<stdio.h>
#include<stdlib.h>
typedef struct List* List;
struct List {
int val;
List next;
};
List reverse(List list) { /* with recursion and one static variable*/
static List tail;
if(!list || !list->next) {
tail = list;
return tail;
} else {
reverse1(list->next);
list->next->next = list;
list->next = NULL;
return tail;
}
}
As an alternative, you can use recursion-
struct node* reverseList(struct node *head)
{
if(head == NULL) return NULL;
if(head->next == NULL) return head;
struct node* second = head->next;
head->next = NULL;
struct node* remaining = reverseList(second);
second->next = head;
return remaining;
}
class Node {
Node next;
int data;
Node(int item) {
data = item;
next = null;
}
}
public class LinkedList {
static Node head;
//Print LinkedList
public static void printList(Node node){
while(node!=null){
System.out.print(node.data+" ");
node = node.next;
}
System.out.println();
}
//Reverse the LinkedList Utility
public static Node reverse(Node node){
Node new_node = null;
while(node!=null){
Node next = node.next;
node.next = new_node;
new_node = node;
node = next;
}
return new_node;
}
public static void main(String[] args) {
//Creating LinkedList
LinkedList.head = new Node(1);
LinkedList.head.next = new Node(2);
LinkedList.head.next.next = new Node(3);
LinkedList.head.next.next.next = new Node(4);
LinkedList.printList(LinkedList.head);
Node node = LinkedList.reverse(LinkedList.head);
LinkedList.printList(node);
}
}