I am preparing for a technical interview and I am stuck at writing this program to reverse every k nodes of a linked list.
For example
1->2->3->4->5->6 //Linked List
2->1->4->3->6->5 //Output for k=2
EDIT:
Here is my code. I get only 6->5 as output.
struct node* recrev(struct node* noode,int c)
{
struct node* root=noode,*temp,*final,*prev=NULL;
int count=0;
while(root!=NULL && count<c)
{
count++;
temp=root->link;
root->link=prev;
prev=root;
root=temp;
}
if(temp!=NULL)
noode->link=recrev(temp,c);
else
return prev;
}
Any help is appreciated. Thanks.
EDIT: I tried to implement Eran Zimmerman's Algorithm as below.
struct node* rev(struct node* root,int c)
{
struct node* first=root,*prev,*remaining=NULL;
int count=0;
while(first!=NULL && count<c)
{
count++;
prev=first->link;
first->link=remaining;
remaining=first;
first=prev;
}
return remaining;
}
struct node* recc(struct node* root,int c)
{
struct node* final,*temp,*n=root,*t;
int count=0;
while(n!=NULL)
{
count=0;
temp=rev(n,c);
final=temp;
while(n!=NULL && count<c)
{
printf("inside while: %c\n",n->data); // This gets printed only once
if(n->link==NULL) printf("NULL"); //During first iteration itself NULL gets printed
n=n->link;
final=final->link;
count++;
}
}
final->link=NULL;
return final;
}
Yeah, I have never been a fan of recursion, so here is my shot at it using iteration:
public Node reverse(Node head, int k) {
Node st = head;
if(head == null) {
return null;
}
Node newHead = reverseList(st, k);
st = st.next;
while(st != null) {
reverseList(st, k);
st = st.next;
}
return newHead
}
private Node reverseList(Node head, int k) {
Node prev = null;
Node curr = head;
Node next = head.next;
while(next != null && k != 1){
curr.next = prev;
prev = curr;
curr = next;
next = next.next;
--k;
}
curr.next = prev;
// head is the new tail now.
head.next = next;
// tail is the new head now.
return curr;
}
Here is a pseudo code.
temp = main_head = node.alloc ();
while ( !linked_list.is_empty () )
{
push k nodes on stack
head = stack.pop ();
temp->next = head;
temp = head;
while ( !stack.empty () )
{
temp->next = stack.pop ();
temp = temp->next;
}
}
I have made a demo implementation of this code. Pardon for the messy implementation. This will work for any value of k. Each k sized segment is reversed separately in the inner loop and the different segments are linked with each other in the outer loop before entering the inner one. temp traces the last node of the k sized sublist and head holds the next value of the next sublist, and we link them. An explicit stack is used to do the reversal.
#include <stdio.h>
#include <stdlib.h>
typedef struct _node {
int a;
struct _node *next;
} node_t;
typedef struct _stack {
node_t *arr[128];
int top;
} stack_t;
void stk_init (stack_t *stk)
{
stk->top = -1;
}
void push (stack_t *stk, node_t *val)
{
stk->arr[++(stk->top)] = val;
}
node_t *pop (stack_t *stk)
{
if (stk->top == -1)
return NULL;
return stk->arr[(stk->top)--];
}
int empty (stack_t *stk)
{
return (stk->top == -1);
}
int main (void)
{
stack_t *stk = malloc (sizeof (stack_t));
node_t *head, *main_head, *temp1, *temp;
int i, k, n;
printf ("\nEnter number of list elements: ");
scanf ("%d", &n);
printf ("\nEnter value of k: ");
scanf ("%d", &k);
/* Using dummy head 'main_head' */
main_head = malloc (sizeof (node_t));
main_head->next = NULL;
/* Populate list */
for (i=n; i>0; i--)
{
temp = malloc (sizeof (node_t));
temp->a = i;
temp->next = main_head->next;
main_head->next = temp;
}
/* Show initial list */
printf ("\n");
for (temp = main_head->next; temp != NULL; temp = temp->next)
{
printf ("%d->", temp->a);
}
stk_init (stk);
/* temp1 is used for traversing the list
* temp is used for tracing the revrsed list
* head is used for tracing the sublist of size 'k' local head
* this head value is used to link with the previous
* sublist's tail value, which we get from temp pointer
*/
temp1 = main_head->next;
temp = main_head;
/* reverse process */
while (temp1)
{
for (i=0; (temp1 != NULL) && (i<k); i++)
{
push (stk, temp1);
temp1 = temp1->next;
}
head = pop (stk);
temp->next = head;
temp = head;
while (!empty (stk))
{
temp->next = pop (stk);
if (temp->next == NULL)
break;
temp = temp->next;
}
}
/* Terminate list with NULL . This is necessary as
* for even no of nodes the last temp->next points
* to its previous node after above process
*/
temp->next = NULL;
printf ("\n");
for (temp = main_head->next; temp != NULL; temp = temp->next)
{
printf ("%d->", temp->a);
}
/* free linked list here */
return 0;
}
I like you recursion, although it may be not the best solution. I can see from your code that you think it deep when you design it. You're just one step away from the answer.
Cause: You forget to return the new root node in your recursion case.
if(temp!=NULL)
noode->link=recrev(temp,c);
// You need return the new root node here
// which in this case is prev:
// return prev;
else
return prev;
I would do something like this:
init curr (node pointer) to point to the beginning of the list.
while end of list is not reached (by curr):
- reverse(curr, k)
- advance curr k times
and reverse is a function that reverses the first k elements starting from curr.
this might not be the most elegant or the most efficient implementation, but it works and is quite simple.
to answer regarding the code you added:
you returned prev, which is constantly being advanced. you should return the beginning of the list.
(I'm assuming this is a singly linked list.) You can keep a temporary pointer (lets call it nodek) and advance it k times in a while loop. This will take O(k). Now you have a pointer to the start of the list and to the last element of the sublist. To reverse here, you remove from head which is O(1) and add to nodek which is O(1). Do this for all elements, so this is O(k) again. Now update root to nodek, and run the while loop on nodek again (to get the new position of nodek) and repeat this whole process again. Remember to do any error checking along the way.
This solution will run at O(n) with only O(1) extra space.
The following solution uses extra space for storing pointers,and reverses each chunk of list separately. Finally,the new list is built. When I tested, this seemed to cover the boundary conditions.
template <typename T>
struct Node {
T data;
struct Node<T>* next;
Node() { next=NULL; }
};
template <class T>
void advancePointerToNextChunk(struct Node<T> * & ptr,int & k) {
int count =0;
while(ptr && count <k ) {
ptr=ptr->next;
count ++;
}
k=count;}
/*K-Reverse Linked List */
template <class T>
void kReverseList( struct Node<T> * & head, int k){
int storeK=k,numchunk=0,hcount=0;
queue < struct Node<T> *> headPointerQueue;
queue <struct Node<T> *> tailPointerQueue;
struct Node<T> * tptr,*hptr;
struct Node<T> * ptr=head,*curHead=head,*kReversedHead,*kReversedTail;
while (ptr) {
advancePointerToNextChunk(ptr,storeK);
reverseN(curHead,storeK,kReversedHead,kReversedTail);
numchunk++;
storeK=k;
curHead=ptr;
tailPointerQueue.push(kReversedTail),headPointerQueue.push(kReversedHead);
}
while( !headPointerQueue.empty() || !tailPointerQueue.empty() ) {
if(!headPointerQueue.empty()) {
hcount++;
if(hcount == 1) {
head=headPointerQueue.front();
headPointerQueue.pop();
}
if(!headPointerQueue.empty()) {
hptr=headPointerQueue.front();
headPointerQueue.pop();
}
}
if( !tailPointerQueue.empty() ) {
tptr=tailPointerQueue.front();
tailPointerQueue.pop();
}
tptr->next=hptr;
}
tptr->next=NULL;}
template <class T> void reverseN(struct Node<T> * & head, int k, struct Node<T> * & kReversedHead, structNode<T> * & kReversedTail ) {
struct Node<T> * ptr=head,*tmp;
int count=0;
struct Node<T> *curr=head,*nextNode,*result=NULL;
while(curr && count <k) {
count++;
cout <<"Curr data="<<curr->data<<"\t"<<"count="<<count<<"\n";
nextNode=curr->next;
curr->next=kReversedHead;
kReversedHead=curr;
if(count ==1 ) kReversedTail=kReversedHead;
curr=nextNode;
}}
public class ReverseEveryKNodes<K>
{
private static class Node<K>
{
private K k;
private Node<K> next;
private Node(K k)
{
this.k = k;
}
}
private Node<K> head;
private Node<K> tail;
private int size;
public void insert(K kk)
{
if(head==null)
{
head = new Node<K>(kk);
tail = head;
}
else
{
tail.next = new Node<K>(kk);
tail = tail.next;
}
size++;
}
public void print()
{
Node<K> temp = head;
while(temp!=null)
{
System.out.print(temp.k+"--->");
temp = temp.next;
}
System.out.println("");
}
public void reverse(int k)
{
head = reverseK(head, k);
}
Node<K> reverseK(Node<K> n, int k)
{
if(n==null)return null;
Node<K> next=n, c=n, previous=null;
int count = 0;
while(c!=null && count<k)
{
next=c.next;
c.next=previous;
previous=c;
c=next;
count++;
}
n.next=reverseK(c, k);
return previous;
}
public static void main(String[] args)
{
ReverseEveryKNodes<Integer> r = new ReverseEveryKNodes<Integer>();
r.insert(10);
r.insert(12);
r.insert(13);
r.insert(14);
r.insert(15);
r.insert(16);
r.insert(17);
r.insert(18);
r.print();
r.reverse(3);
r.print();
}
}
Related
void
LInsert (LIST * l, int x, int pos)
{
struct Node *new, *p; // p: previous node
// create a new node
new = (struct Node *) malloc (sizeof (struct Node));
new->val = x;
if (pos == 0)
{ // insert to start
new->next = l->head;
l->head = new;
}
else
{
// insert after p
p = l->head;
while (p != NULL && pos > 1)
{
p = p->next;
--pos;
}
if (p == NULL)
{
printf ("LInsert: Position not possible\n");
return;
}
new->next = p->next;
p->next = new;
}
l->size++;
}
This is a function of inserting a node to a linked list. I don't understand a few lines in this program.
In the first if condition there is a line new->next=l->head; From my thinking it means that in the "next" part of the new node it will store the what's in the head node(an address probably), but why?. It makes the linked list a circular linked list but this is just a simple linked list.
Also near the end new->next=p->next what does this mean.It makes the linked list circular again.
Hope the indentation is correct I always get people yelling at me for wrong indentation
Here is the complete code which includes struc declaration and stuff
#include <stdio.h>
#include <stdlib.h>
struct Node {
int val;
struct Node *next;
};
struct List {
struct Node *head;
int size;
};
// LIST is new name for "struct List"
typedef struct List LIST;
void LInit(LIST *l){ // Initialize list to empty
l->head = NULL; // pointer to first node
l->size = 0; // number of nodes
}
int LGetPos(LIST *l, int x) {
struct Node *p;
int i=0;
// go through all nodes
for (p=l->head; p!=NULL; p=p->next)
if (p->val == x) return i; // found
else i++; // next
return -1; // not found in the list
}
int LGetAt(LIST *l, int pos) {
struct Node *p=l->head;
int i;
// go to position
for(i=0; p!=NULL && i<pos; i++) p = p->next;
if(p) return p->val; // if exists, return it
else { printf("LDelete: Position not exist\n"); return -99; }
}
void LInsert(LIST *l, int x, int pos) {
struct Node *new, *p; // p: previous node
// create a new node
new = (struct Node *) malloc(sizeof(struct Node));
new->val = x;
if(pos==0) { // insert to start
new->next = l->head;
l->head = new;
}
else { // insert after p
p = l->head;
while(p!=NULL && pos>1) { p = p->next; --pos; }
if(p==NULL) { printf("LInsert: Position not possible\n"); return; }
new->next = p->next;
p->next = new;
}
l->size++;
}
void LDelete(LIST *l, int pos) {
struct Node *p, *d; // p: previous
if(l->head == NULL) return;
if(pos==0) { // delete first node
d = l->head;
l->head = d->next;
}
else { // delete after p
p = l->head;
while(pos>1 && p) { p = p->next; --pos; }
if(p==NULL) { printf("LDelete: Position not exist\n"); return; }
d = p->next;
p->next = p->next->next;
}
l->size--;
free(d);
}
int LIsEmpty(LIST * l){
return (l->size == 0);
}
int LSize(LIST * l){
return (l->size);
}
void LDisplay(LIST *l) {
struct Node *p;
printf("List: ");
for(p=l->head; p!=NULL; p=p->next)
printf("--> %d ", p->val);
printf("\n");
}
int LHeadOf(LIST *l) {
if (!LIsEmpty(l)) return l->head->val;
else {
printf("LHeadOf: Linked list empty\n");
return -99;
}
}
int main() {
LIST list;
LInit(&list);
LDisplay(&list);
LInsert(&list, 3, 0);
LInsert(&list, 4, 0);
LInsert(&list, 5, 2);
LDisplay(&list);
printf("Value at 1: %d\n", LGetAt(&list, 1));
printf("Location of 4: %d\n", LGetPos(&list, 4));
LDelete(&list, 1);
LDisplay(&list);
return 0;
}
I don't understand a few lines in this program
Okay - let's take a look of those lines...
here is a line new->next=l->head; From my thinking it means that in the "next" part of the new node it will store the what's in the head node(an address probably), but why?
That line is used to insert the new element in front of the current head element. So
new->next=l->head; // Make the new element point to current head
l->head = new; // Change head to point to the new element as it is now the front element
Also near the end new->next=p->next what does this mean.It makes the linked list circular again.
Well, it doesn't make the list circular. It simply insert the new element somewhere in the middle of the list.
new->next = p->next; // Make new point to the element after p
p->next = new; // Make p point to new
// In this way new has between inserted after p and
// before the element that folloed p
I am studying for my Algorithms exam and I have an exercise where I need to swap two items of a doubly linked list if a condition is true. (Language: C)
More specifically, I have a list of this kind:
H <-> |prev|Frequency1|VALUE1|next| <-> |prev|Frequency2|VALUE2|next| <-> ... <-> NULL
The frequency field increases every time I search for the relative value. The list must be ordered according to the frequency (in decreasing order, so at the very top there is the most searched item)
The problem is, I am not very good in exchanging pointers, I tried many times to do it but I have no clue. I guess that the problem I am facing is that I don't know how to use a temp item to keep track of what I am doing without loosing data.
I think that the case I have to consider are:
First item of the list
Last item of the list
Item is in the middle of the list.
My attempt, certainly wrong is:
int Search(int x, list* head) {
int contapos = 0;
list* i;
list* aus;
for (i=head; i!=NULL; i = i->next, contapos++)
{
if (i->key == x)
{
i->freq++; // Increase frequency
aus = i->prev;
while ((i->freq > aus->freq))
{ // Keep ordered the frequencies
if (i->next != NULL)
{
i->next->prev = aus;
}
if (aus->prev != NULL)
{
aus->prev->next = i;
}
aus->next = i->next;
i->prev = aus->prev;
aus->prev = i;
i->next = aus;
}
/* Return counter */
return contapos;
}
}
return -1; // In case the item i am searching is not there
}
Thank you in advance for everything!
Edit:
as requested, I am adding the main (and the whole code just to be sure) of the program at the moment
typedef struct _list {
int key;
int freq;
struct _list *next;
struct _list *prev;
} list;
list* head;
list* tail;
void swap(list *lhs, list *rhs) {
list *temp;
temp = lhs->prev;
lhs->prev = rhs->prev;
rhs->prev = temp;
temp = lhs->next;
lhs->next = rhs->next;
rhs->next = temp;
}
void InsertAtTail(int value) {
list *newNode;
newNode = (list*)malloc(sizeof(list));
newNode->key = value;
if(head == NULL)
{
head = newNode;
}
else
{
tail->next = newNode;
newNode->prev = tail;
}
tail = newNode;
tail->next = NULL;
}
int SearchAndIncrement(int x, list** head) {
int contapos = 0;
list* i;
// Let's find the element with the matching key
for (i = *head; i != NULL; i = i->next, contapos++)
if (i->key == x)
break;
// If we did not find the node, return -1 to denote failure.
if (i == NULL)
return -1;
// Increase frequency
i->freq++;
// Move this node forward while the frequency is not in the correct position.
while (i->next && i->prev && (i->freq > i->prev->freq))
swap(i, i->prev);
// The head might have been moved.
while ((*head)->prev != NULL)
(*head) = (*head)->prev;
// Return the original position
return contapos;
}
int main () {
int N;
scanf("%d", &N);
head = NULL;
tail = NULL;
int i, value;
for (i=0; i<N; i++) {
scanf("%d", &value);
InsertAtTail(value);
}
/* Initializing frequencies */
list* aus;
for (aus=head; aus; aus = aus ->next) {
aus->freq = 0;
}
int x, pos;
do {
scanf("%d", &x);
pos = SearchAndIncrement(x, &head);
printf("%d ", pos);
printf("[");
aus = head;
while (aus!=NULL) {
printf("%d ", aus->key);
aus = aus->next;
}
printf("]\n");
} while (pos != -1);
return 0;
}
Let's simplify the problem. The complicated pointer portion is when we are trying to move a node forward in the list. So let's create some functions just for that.
void RemoveNode(list *node) {
if (node->prev)
node->prev->next = node->next;
if (node->next)
node->next->prev = node->prev;
}
void InsertNodeBetween(list *lhs, list *node, list *rhs) {
if (lhs) assert(lhs->next == rhs);
if (rhs) assert(rhs->prev == lhs);
if (lhs) lhs->next = node;
if (rhs) rhs->prev = node;
node->prev = lhs;
node->next = rhs;
}
Once we've done that, then we can more easily talk about the operation that you want to do.
int SearchAndIncrement(int x, list** head) {
int contapos = 0;
list* i;
// Let's find the element with the matching key
for (i = *head; i != NULL; i = i->next, contapos++)
if (i->key == x)
break;
// If we did not find the node, return -1 to denote failure.
if (i == NULL)
return -1;
// Increase frequency
i->freq++;
// Move this node forward while the frequency is not in the correct position.
while (i->next && (i->freq > i->next->freq)) {
list *prev = i->next;
list *next = i->next->next;
RemoveNode(i);
InsertNodeBetween(prev, i, next);
}
// The head might have been moved.
while ((*head)->prev != NULL)
(*head) = (*head)->prev;
// Return the original position
return contapos;
}
Some commentary:
The important thing to note here is that we have the ability to create multiple functions. And we can use those functions to make the amount of the problem that we need to keep in our head at any one time smaller.
I am currently solving sum problems of list and function and i came across this question i.e rotate a linked list by k anti clockwise.
Here is the code for same
void rotate_k(struct list *node,int k)
{
int count=0;
struct list *knode,*ptr=node;
while(ptr!=NULL && count < k)
{
ptr=ptr->next;
count++;
}
knode=ptr;
while(ptr->next!=NULL)
{
ptr=ptr->next;
}
ptr->next =node;
node=knode->next;
knode->next=NULL;
}
Lets say if input is 1->2->3->4->5->6 and k=4.
The output should be 5->6->1->2->3->4 but the code gives the output 1->2->3->4->5 .
Help needed :)
You are not modifying the original list (node parameter)
struct list *rotate_k(struct list *node,int k)
{
int count=0;
struct list *knode,*ptr=node;
while(ptr!=NULL && count < k)
{
ptr=ptr->next;
count++;
}
knode=ptr;
while(ptr->next!=NULL)
{
ptr=ptr->next;
}
ptr->next =node;
node=knode->next;
knode->next=NULL;
return knode; //<-- THIS IS THE NEW LIST
}
Also, knode->next=NULL is strange; you should do at the node that is (was) previous to knode (this is what is deleting the 6 from your results).
SJuan's method is correct but if you want to do it your way without using a return value, then you need to use a double pointer for node. Remember, C makes copies of variables you pass into a function. If the original root node was a pointer (which I'm assuming it was) than you need to make a pointer to a pointer otherwise you are just making changes to a copy of the root node pointer, not the actual root node pointer.
void rotate_k(struct list **node, int k)
{
int count = 0;
struct list *knode, *ptr = *node;
while(ptr != NULL && count < k)
{
ptr = ptr->next;
count++;
}
knode = ptr;
while(ptr->next != NULL)
{
ptr = ptr->next;
}
ptr->next = *node;
*node = knode->next;
knode->next = NULL;
}
void rotate_list_right(listnode** head, int k)
{
if( !head || !*head )
{
printf( "\nrotate_list_right: empty list = so return \n" );
return;
}
if( k < 1 )
{
printf( "\nrotate_list_right:invalid input: k must be >= 1 \n" );
return;
}
listnode* post = *head;
listnode* curr = *head;
/* move post by k nodes */
while(k--)
{
post = post->next;
if( !post ) /* k is bigger than length of the list */
{
printf( "\nrotate_list_right:invalid input: k must be smaller than list size \n" );
return;
}
}
/* move curr to kth-last node */
while(post->next)
{
curr = curr->next;
post = post->next;
}
/* currs' next is new header */
listnode* tmp = *head;
*head = curr->next;
curr->next = 0;
//join post
post->next = tmp;
}
I'm trying to sort a linked list by finding the largest value, deleting it from its position, and then inserting it at the top of the list.
The difficulty I'm running into is the actual deleting and inserting at the top. The issue seems to be in the if condition in the while loop contained within the sortList function, but I'm not sure how to fix it.
Any help would be appreciated.
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int num;
struct node *next;
} Node, *NodePtr;
void printList(NodePtr np);
NodePtr makeList(void);
NodePtr makeNode(int n);
NodePtr sortList(NodePtr list);
int main(void) {
NodePtr list;
printf("Enter numbers for the list (0 to end)\n");
list = makeList();
printList(list);
list = sortList(list);
printList(list);
return 0;
}
NodePtr makeList(void) {
NodePtr makeNode(int), np, top, last;
int n;
top = NULL;
if(scanf("%d", &n) != 1)n = 0;
while(n != 0) {
np = makeNode(n);
if(top == NULL)top = np;
else last->next = np;
last = np;
if(scanf("%d", &n)!=1)n=0;
}
return top;
}
void printList(NodePtr np) {
while(np != NULL) {
printf("%d\n", np->num);
np = np->next;
}
}
NodePtr makeNode(int n) {
NodePtr np = (NodePtr)malloc(sizeof(Node));
np->num = n;
np->next = NULL;
return np;
}
NodePtr sortList(NodePtr list) {
NodePtr top = list;
NodePtr curr = NULL;
NodePtr largest;
NodePtr prev;
prev = NULL;
curr = top;
largest = top;
while(curr != NULL) {
prev = curr;
if(curr->num > largest->num) {
largest = curr;
prev->next = curr->next;
largest->next = top;
}
curr = curr->next;
}
if(prev == NULL) {
largest->next = top;
return largest;
}
return largest;
}
There is issues in the sortList function.
This function only put some large nodes in the beginning of the list. It is not soting all the list. you can you a sort algorithm to sort the file : quicksort/ bubblesort/...
i put a code doing a sort in the end of this answer.
here is a code doing the sort of the list :
//it is replacing largest node with first one then doing the same operation with sublist (list-first element)
NodePtr sortList(NodePtr list)
{
//
if(list == null || list->next == null)
return list; // the list is sorted.
//replace largest node with the first :
//1- find largest node :
NodePtr curr, largest,largestPrev;
curr = list;
largest = list;
prev = list;
largestPrev = list;
while(curr != NULL) {
if(curr->num > largest->num) {
largestPrev = prev;
largest = curr;
}
prev = curr;
curr = curr->next;
}
//largest node is in largest.
//2- switching firt node and largest node :
NodePtr tmp;
if(largest != list)
{
largestPrev->next = list;
tmp = list->next;
list->next = largest->next;
largest->next = tmp;
}
// now largest is the first node of the list.
// calling the function again with the sub list :
// list minus its first node :
largest->next = sortList(largest->next);
return largest;
}
Here is my attempt to sort a singly linked list using QuickSort algorithm. If you know n then run time will be O(n log n). Check if this helps.
#include "malloc.h"
typedef struct node {
struct node *next;
int val;
} node;
bool insert_node(struct node **head, int val)
{
struct node *elem;
elem = (struct node *)malloc(sizeof(struct node));
if (!elem)
return false;
elem->val = val;
elem->next = *head;
*head = elem;
return true;
}
int get_lval(struct node *head, int l)
{
while(head && l) {
head = head->next;
l--;
}
if (head != NULL)
return head->val;
else
return -1;
}
void swap(struct node *head, int i, int j)
{
struct node *tmp = head;
int tmpival;
int tmpjval;
int ti = i;
while(tmp && i) {
i--;
tmp = tmp->next;
}
tmpival = tmp->val;
tmp = head;
while(tmp && j) {
j--;
tmp = tmp->next;
}
tmpjval = tmp->val;
tmp->val = tmpival;
tmp = head;
i = ti;
while(tmp && i) {
i--;
tmp = tmp->next;
}
tmp->val = tmpjval;
}
struct node *Quick_Sort_List(struct node *head, int l, int r)
{
int i, j;
int jval;
int pivot;
i = l + 1;
if (l + 1 < r) {
pivot = get_lval(head, l);
printf("Pivot = %d\n", pivot);
for (j = l + 1; j <= r; j++) {
jval = get_lval(head, j);
if (jval < pivot && jval != -1) {
swap(head, i, j);
i++;
}
}
swap(head, i - 1, l);
Quick_Sort_List(head, l, i);
Quick_Sort_List(head, i, r);
}
return head;
}
struct node *Sort_linkedlist(struct node *head)
{
struct node *tmp = head;
// Using Quick sort.
int n = 0;
while (tmp) {
n++;
tmp = tmp->next;
}
printf("n = %d\n", n);
head = Quick_Sort_List(head, 0, n);
return head;
}
void print_list(struct node *head)
{
while(head) {
printf("%d->", head->val);
head = head->next;
}
printf("\n");
}
int _tmain(int argc, _TCHAR* argv[])
{
struct node *head = NULL;
struct node *shead = NULL;
insert_node(&head, 10);
insert_node(&head, 12);
insert_node(&head, 9);
insert_node(&head, 11);
insert_node(&head, 7);
insert_node(&head, 1);
insert_node(&head, 3);
insert_node(&head, 8);
insert_node(&head, 5);
insert_node(&head, 2);
insert_node(&head, 4);
insert_node(&head, 6);
print_list(head);
shead = Sort_linkedlist(head);
print_list(shead);
return 0;
}
By writing to largest->next you overwrote curr->next. So you end up restarting from the top all the time.
Make sure that:
the list remains consistent
your list iterator remains consistent
But overall, your code seems to be heavily broken, I believe there might be a couple other errors in your sorting logic.
The following are some of the problems which exist in your sorting logic:
You are setting the prev pointer to curr in the beginning of the loop itself which is incorrect. By doing this, you are making the current pointer and the previous node pointer as same which makes it impossible to delete the node.
You should assign the largest pointer also to top whereby it facilitates the possibility of setting the largest->next to real top node.
The code can modified like below (Just a pointer, you need to check for other issues yourself):
while(curr != NULL)
{
if(curr->num > largest->num)
{
largest = curr;
prev->next = curr->next;
largest->next = top;
top = largest;
}
prev = curr;
curr = curr->next;
}
// Program to sort a single linked list in ascending order
// (without exchanging data in the nodes)
/**************************************************************************
There are two methods of sorting presented here(At a time,we can use any of
these two functions to sort our single linked list.) -
1. Function 'void Sort()' - This function uses selection sort method(I
think).
In this function,a node whose data is the smallest in the list is made
as 'head' node(i.e. starting node of the list) by scanning the whole list
once.Then from the remaining list,again a node with the smallest data is
found out whose address is kept in the 'next' field of previous node(head
node).This process continues to sort the whole list.
2. Function 'void Sort_method2()' - This function uses insertion sort
method(I think).
In this function,starting from second node in the list, all previous node
data(starting from 'head' node) are compared with current reference node
(which is initially second node in the list).If 'data' field of current
reference node is smaller than that of any of its previous nodes,then
suitable changes in the 'next' field of corresponding nodes are made.If
data in the current reference node is smaller than that in the 'head' node,
then the current reference node is made as 'head' node.
*********************************************************************/
#include<stdio.h>
#include<conio.h>
#include<alloc.h>
#include<stdlib.h>
struct node
{
int data;
struct node *next;
};
struct node *head,*head1;
void Create_node(int data);
void display();
void Sort();
void Sort_method2();
void main()
{
int choice,d;
clrscr();
while(1)
{
printf("\n 1.Create new node");
printf("\n 2.Sort in ascending order");
printf("\n 3.Exit");
printf("\nEnter your choice : ");
scanf("%d",&choice);
switch(choice)
{
case 1: printf("\nEnter data :");
scanf("%d",&d);
Create_node(d);
break;
case 2: Sort(); // At a time,we can use any of these two
//Sort_method2(); // functions to sort our single linked list.
break;
case 3: exit(0);
default:exit(0);
}
} // end of while(1)
} // end of main()
//--------------------------------------------
void Create_node(int d)
{
struct node *newnode,*temp;
newnode = (struct node *)malloc(sizeof(struct node));
newnode -> data = d;
newnode -> next = NULL;
if(head == NULL)
head = newnode;
else
{
temp = head;
while(temp -> next != NULL)
temp = temp -> next;
temp -> next = newnode;
} // end of 'else'
} // end of 'Create_node(int d)'
//---------------------------------------------
void display() // Print linked list contents
{
struct node *temp;
printf("\nList contents are :\n");
temp = head;
while(temp != NULL)
{
printf(" Data = %d Address = %u\n",temp->data,temp);
temp = temp->next;
}
printf("\n");
}
//--------------------------------------------
void Sort()
{
struct node *t,*t1,*t2,*t3;
t1 = head;
head1 = head;
if(head == NULL)
printf("\nThe linked list is empty!");
else
{
while( (t2 = t1 -> next) != NULL)
{
while(t2 != NULL)
{
t3 = t2 -> next;
if( t1 -> data > t2 -> data)
{
t2 -> next = t1;
for(t = t1; t -> next != t2;t = t -> next);
t -> next = t3;
t1 = t2; // t1 = Node with smaller data
t2 = t3; // t2 = Node to be compared with t1
} // end of 'if'
else
{
// t1 = t1; // That is,no change in t1.
t2 = t3;
}
} // end of ' while(t2 != NULL)'
if(head == head1) // We want this action only for first pass of
{ // outer while() loop.Only initially, head = head1.
head = t1;
head1 = t1 -> next;
} // end of 'if(head == head1)'
else
{
for(t = head;t -> next != head1; t = t -> next);
t -> next = t1;
head1 = t1 -> next;
} // end of 'else'
t1 = t1 -> next;
} // end of 'while( (t2 = t1 -> next) != NULL)'
display(); // Display the list.
} // end of 'else' of 'if(head == NULL)'
} // end of 'Sort()'
//--------------------------------------------
void Sort_method2()
{
struct node *t,*t1,*t2,*tt;
if(head == NULL)
printf("\nThe linked list is empty!");
else
{
t1 = head -> next;
while(t1 != NULL) // This is i-loop(outer loop).
{
t2 = t1 -> next;
for(t = head; t != t1; t = t -> next) // This is j-loop(inner loop).
{
if(t1->data < t->data)
{
t1 -> next = t;
for(tt=head; tt->next != t1; tt=tt->next); //end of for loop in 'if'
tt -> next = t2;
if(t == head)
head = t1; // There is only one statement in this 'if'.
else // i.e.,'if(t != head)'
{
for(tt=head; tt->next != t; tt=tt->next);
tt -> next = t1;
}
break;
} // end of 'if'
} // end of outer 'for' loop
t1 = t2;
} // end of 'while'
display(); // Display the list.
} // end of 'else' of 'if(head == NULL)'
} // end of 'Sort_method2()'
We have a problem with our LinkedList in C.
When I count how many nodes should be in the list, I always get 1
LL count: 1
This is the Add, count and get last element of the list code:
void addLL(LL * head)
{
LL *newNode;
LL *tail = getLastNode(head);
newNode = malloc(sizeof(LL));
if(newNode != DEF_NULL)
{
newNode->ID=-1;
newNode->TCB=-1;
newNode->next = DEF_NULL;
if(!head) head = newNode;
else tail->next = newNode;
}
}
LL * getLastNode(LL * head)
{
LL *temp = head;
while(temp->next != DEF_NULL)
{
temp = temp->next;
}
return temp;
}
CPU_INT32U countLL(LL * head)
{
CPU_INT32U elements = 0;
LL * temp = head;
while(temp->next != DEF_NULL)
{
temp = temp->next;
elements++;
}
return elements;
}
It's called in this way:
addLL(list);
temp = countLL(list);
Debug_LOG("LL count: %i", temp);
where LL * list; is a global variable, and temp is in local scope.
I hope anyone can see where I went wrong
Greetings,
Sjaak and Gerrit
I see several issues in your code :
you should always protect your linked list operations by testing if the list pointer is valid (i.e. not null)
you cannot allocate a first item to an empty list due to the way you allocate the first new item : you change head but the modification won't be propagated outside of the function. You should pass a "pointer to a list pointer" (i.e. a LL**) that is equivalent to "the address of a LL*"; See how I call addLL() and how I have modified its prototype and the head assignment
if your list is only one block long, it won't be counted as you count only if there is a successor, see how I have modifed the order of the do / while condition
I propose the modified code that works for 1, 2 or any list length (I have just changed the CPU_INT32U to int to compile quickly with MinGW, I could have typedef'ined):
#include <stdio.h>
#define DEF_NULL 0
typedef struct tagL {
int ID;
int TCB;
struct tagL *next;
} LL;
void addLL(LL ** head);
LL * getLastNode(LL * head);
int countLL(LL * head);
void addLL(LL ** head)
{
LL *newNode;
LL *tail = getLastNode(*head);
newNode = malloc(sizeof(LL));
if(newNode != DEF_NULL)
{
newNode->ID=-1;
newNode->TCB=-1;
newNode->next = DEF_NULL;
if(!*head)
*head = newNode;
else
tail->next = newNode;
}
}
LL * getLastNode(LL * head)
{
LL *temp = head;
if (head){
while(temp->next != DEF_NULL)
{
temp = temp->next;
}
}
return temp;
}
int countLL(LL * head)
{
int elements = 0;
LL * temp = head;
if (head){
do {
temp = temp->next;
elements++;
} while(temp != DEF_NULL);
}
return elements;
}
int main(int argc, char *argv[]){
LL *list = 0;
printf("LL test\n");
addLL(&list);
printf("length = %d\n", countLL(list));
addLL(&list);
printf("length = %d\n", countLL(list));
addLL(&list);
printf("length = %d\n", countLL(list));
}
Output :
LL test
length = 1
length = 2
length = 3
On Windows nothing's wrong whit this function - strange ...
ideone also shows good output.
#include <stdio.h>
#include <stdlib.h>
typedef struct LL{
struct LL *next;
}LL;
LL * getLastNode(LL * head)
{
LL *temp = head;
while(temp->next != NULL)
{
temp = temp->next;
}
return temp;
}
void addLL(LL * head)
{
LL *newNode;
LL *tail = getLastNode(head);
newNode = malloc(sizeof(LL));
if(newNode != NULL)
{
newNode->next = NULL;
if(!head) head = newNode;
else tail->next = newNode;
}
}
int countLL(LL * head)
{
int elements = 0;
LL * temp = head;
while(temp->next != NULL)
{
temp = temp->next;
elements++;
}
return elements;
}
int main() {
LL *h = malloc(sizeof(*h));
addLL(h);
addLL(h);
addLL(h);
printf("%d\n", countLL(h)); // prints 3 as expected
}
CPU_INT32U countLL(LL * head){CPU_INT32U elements = 0;LL * temp = head;while(temp->next != DEF_NULL){temp = temp->next;elements++;}return elements;}
in this function you are declaring elements variable as auto
so its storage gets deallocated as soon as function exits , as memory now free to allocate to different variable, so may be overwritten hence previous cvalue gets lost
so to avoid this please use static in declaring variable.....
as static variables memory gets deallocated only after execution of whole program
please try....
void addLL(LL * head)
{
LL *newNode;
LL *tail = getLastNode(head);
There is a problem here, if (the global) head happens to be NULL, it will be dereferenced by the getLastNode() function:
LL * getLastNode(LL * head)
{
LL *temp = head;
while(temp->next != DEF_NULL)
Here temp->next != ... will cause temp to be dereferenced. That would cause NULL pointer dereferences if temp happens to be NULL. (as in the call by the insert function. You could add an extra test (or use pointers to pointers which is cleaner):
while(temp && temp->next != DEF_NULL)
Update (to show that the pointer to pointer version is cleaner)
#include <stdlib.h>
#include <stdio.h>
#define DEF_NULL NULL
#define CPU_INT32U unsigned
typedef struct link {
struct link *next;
} LL;
LL *globhead=NULL;
LL **getTailPP(LL **ppHead);
CPU_INT32U countLL(LL * ptr);
void addLL(LL **ppHead);
void addLL(LL **ppHead)
{
ppHead = getTailPP(ppHead);
*ppHead = malloc(sizeof **ppHead);
if(*ppHead != DEF_NULL)
{
// newNode->ID=-1;
// newNode->TCB=-1;
(*ppHead)->next = DEF_NULL;
}
}
LL **getTailPP(LL **ppHead)
{
for( ; *ppHead; ppHead = &(*ppHead)->next ) {;}
return ppHead;
}
CPU_INT32U countLL(LL * ptr)
{
CPU_INT32U elements = 0;
for(; ptr != DEF_NULL; ptr=ptr->next) { elements++; }
return elements;
}
int main()
{
unsigned count;
addLL( &globhead);
count = countLL (globhead);
printf("count = %u\n", count);
addLL( &globhead);
count = countLL (globhead);
printf("count = %u\n", count);
return 0;
}