Segmentation fault when deleting linked list - c

I am trying to delete all the nodes on a linked list but I am getting a segmentation fault.
I had code that was working initially but I was only deleting the first node in the list, I want to delete all the nodes and delete all the pointers redundant pointers.
Also if some of you guys could check the function I am using to create the linked list and give me some feedback on whether you think it is ok or where some improvements could be made, I would appreciate it.
Thanks.
Here is the code:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#define MEMORY_SIZE (15)
typedef struct link {
double coeff;
int pow;
struct link * next;
} poly;
poly *polyArray[MEMORY_SIZE];// array of 15 polynomials to play with
// /** The function prototypes */
void createPoly(poly **);
void deletePoly(poly *);
/**
* The main function
*/
int main(void) {
printf("\n\n\t***************************************************");
/* printf("\n\tDemonstrating Polynomial Creation");
printf("\n\t***************************************************");*/
printf("\n\t1st polynomial\t");
createPoly(&polyArray[0]);
showPoly(polyArray[0]);
srand(time(NULL));
// printf("\n\n\tCreating and storing the 2nd polynomial\n");
// createPoly(&polyArray[1]);
// showPoly(polyArray[1]);
showPoly(polyArray[0]);
printf("\n\t***************************************************");
printf("\n\tProgram has Ended, Deleting all polynomials");
printf("\n\t***************************************************");
int count;
for(count = 0; count < MEMORY_SIZE; count++)
{
deletePoly(polyArray[count]);
}
printf("\n\n");
showPoly(polyArray[0]);
return 0;
}//end main function
//////////////////////////////////////////////////////////////////////////////////////
void createPoly(poly **node) {
poly *tempnode; //To hold the temporary last address
tempnode = (poly*)malloc( sizeof(poly) ); //create the first node
*node = tempnode; //Store the head address to the reference variable
int flag = 1 + rand()%3;; // A flag to control the number of terms
int counter;
for( counter = 0; counter <= flag; counter++ )
{
tempnode->pow = ( flag-counter );
tempnode->coeff = ( (double)(rand()%20) )/( (double)(1 + rand()%20) );
if( (counter < flag) && (counter >= 0) )
{
tempnode->next = (poly*)malloc( sizeof(poly) ); //Grow the list
}
else if ( counter == flag )
{
tempnode->next = NULL;
}
tempnode = tempnode->next;
}
}
void deletePoly(poly *node) {
poly *temp;
if( node->next == NULL )
{
free( node );
node = NULL;
}
else
{
while( node->next != NULL )
{
temp = node->next;
free( node );
node = temp;
}//end while
node = NULL;
}//end 'if/else'
}//end function 'deletePoly'

As I understand it, the main function is creating only the first polynomial (poly[0]), but you are trying to delete them all (the loop in the main function goes up to MEMORY_SIZE).
You should also initialize all your pointers to NULL before beginning the program (this is an important feature in C programs) and change the deletePoly this way:
void deletePoly(poly *node) {
poly *temp;
while( node != NULL ) {
temp = node->next;
free( node );
node = temp;
}//end while
node = NULL;
}//end function 'deletePoly'

Related

Linked List Delete Node , Simple linked list

I'm trying to implement a function that deletes nodes from a linked list. So far, I can delete just the first node of the list(3).
I tried to go to the for loop from delete, I thought that the memory is not well allocated, I have been struggling for a few days and I don't understand, please help me a little, it's the topic I received from college.
#include <stdio.h>
#include <stdlib.h>
typedef struct nod
{
int key;
struct nod *urm;
} NOD;
NOD *first=0,*last=0;
void add(int x)
{
NOD *p=(NOD*)malloc(sizeof(NOD));
p->key=x;
p->urm=0;
if(0==first)
{
first=p;
last=p;
}
else{
last->urm=p;
last=p;
}
}
void delete(int x)
{
NOD *q,*p;
if(first->key==x)
{
p=first;
first=first->urm;
free(p);
}
else{
for(p=q=first;p=0;q=p,p=p->urm)
{
if(p->key==x)
{
q->urm=p->urm;
if(p==last)
{
last=q;
}
free(p);
}
}
}
}
void show()
{
for(NOD *p=first;p!=0;p=p->urm)
{
printf("%d ",p->key);
}
printf("\n");
}
int main()
{
add(3);
add(1);
add(2);
add(5);
show();
delete(2);
show();
return 0;
}
For starters the code you showed is not a C++ code. It is a C code.
It is a bad idea to define global variables like first and last and when functions depend on global variables. In this case you can not create more than one list in a program.
As for the function delete then in general it has undefined behavior. It can be called for an empty list.
Moreover in this ;loop
for(p=q=first;p=0;q=p,p=p->urm)
there is a typo in the condition expression. You are using the assignment operator instead of the comparison operator.
And you function ignore the case when the list contains only one node because in this case it does not update the last node.
Nevertheless using your approach the function delete can look the following way.
void delete(int x)
{
if ( first )
{
if ( first->key == x )
{
NOD *tmp = first;
first = first->urm;
free( tmp );
if ( first == NULL ) last = NULL;
}
else
{
NOD *p = first;
while ( p->urm != NULL && p->urm->key != x )
{
p = p->urm;
}
if ( p->urm != NULL )
{
NOD *tmp = p->urm;
p->urm = p->urm->urm;
free( tmp );
if ( p->urm == NULL ) last = p;
}
}
}
}
Here is a demonstrative program.
#include <stdio.h>
#include <stdlib.h>
typedef struct nod
{
int key;
struct nod *urm;
} NOD;
NOD *first=0,*last=0;
void add(int x)
{
NOD *p=(NOD*)malloc(sizeof(NOD));
p->key=x;
p->urm=0;
if(0==first)
{
first=p;
last=p;
}
else{
last->urm=p;
last=p;
}
}
void delete(int x)
{
if ( first )
{
if ( first->key == x )
{
NOD *tmp = first;
first = first->urm;
free( tmp );
if ( first == NULL ) last = NULL;
}
else
{
NOD *p = first;
while ( p->urm != NULL && p->urm->key != x )
{
p = p->urm;
}
if ( p->urm != NULL )
{
NOD *tmp = p->urm;
p->urm = p->urm->urm;
free( tmp );
if ( p->urm == NULL ) last = p;
}
}
}
}
void show()
{
for(NOD *p=first;p!=0;p=p->urm)
{
printf("%d ",p->key);
}
printf("\n");
}
int main()
{
add(10);
add(20);
add(30);
add(40);
show();
delete(30);
show();
add( 50 );
add( 60 );
add( 70 );
add( 80 );
show();
delete(80);
show();
return 0;
}
Its output is
10 20 30 40
10 20 40
10 20 40 50 60 70 80
10 20 40 50 60 70
You can greatly simplify deleting a node from your list by using both a pointer-to-pointer to NOD and a pointer-to NOD to iterate over the list. This allows you to set the node at the current address to the node->urm eliminating the need to keep track of the previous node in the list, e.g.
/** delete node with key v from list (for loop) */
void delete (int v)
{
NOD **ppn = &first; /* pointer to pointer to first*/
NOD *pn = first; /* pointer to first */
for (; pn; ppn = &pn->urm, pn = pn->urm) {
if (pn->key == v) {
*ppn = pn->urm; /* set node at address to next node */
free (pn); /* free deleted node */
break;
}
}
}
See Linus on Understanding Pointers for further discussion on the advantages of using the address of a node in addition to a pointer to node.
I think your for loop condition is incorrect inside delete functions:
for(q=first, p=first->urm; p!=0; q=p, p=p->urm)
just change the condition, then it should work.

How would checking if a value in a data structure equals NULL return a segmentation fault?

I am trying to load a hash table of node*(s)-
typedef struct node{
char word[LENGTH+1];
struct node* next;
}node;
(don't worry about length, it is defined in the file that calls this)
-into memory, but this:
// make hash table
node* hashtable[729];
node* new_node = malloc(sizeof(node));
node* cursor = NULL;
int bucket;
while(sscanf(dictionary,"%s",new_node->word) != 0)
{
bucket = hash(new_node->word);
cursor = hashtable[bucket];
while(cursor->next != NULL)
{
cursor = cursor->next;
}
cursor->next = new_node;
}
return true;
keeps turning up to be a segmentation fault (specifically the condition of the while loop). I am baffled, what is going on? Thank you in advance to any who helps! I really appreciate your help!
You need to allocate memory for each node that is going into your hash table. How's about something like the following:
/* make hash table */
node* hashtable[729];
/* initialise all buckets to NULL */
memset(hashtable, 0, sizeof(node*)*729);
node new_node; /* Use a stack node for the temporary */
new_node.next = NULL;
node** cursor = NULL;
int bucket;
while(sscanf(dictionary,"%s",new_node.word) != 0)
{
bucket = hash(new_node.word);
cursor = &hashtable[bucket];
while(*cursor != NULL)
{
cursor = &(*cursor)->next;
}
if ((*cursor = malloc(sizeof(node))) != NULL)
/* Copy from temporary to hashed node. Assumes structure is 'flat' */
**cursor = new_node;
else {
/* panic! */
}
}
return true;
Edit:
I've refactored some code and produced a standalone example that compiles and runs, For simplicity, I've employed a totally bogus hash function and reduced the number of buckets to fit its output of 0-25. I've tried to split out the hashtable 'object' and started the effort to be a little more disciplined to avoid buffer overruns, etc.
For the traversal of the linked list of nodes in a bucket of the hashtable, I've included two versions--one that uses the node** (pointer to a pointer) and another that doesn't--in an attempt to demonstrate the use of the double star. Change the #if 1 to #if 0 to use the "single star" version.
I hope that, collectively, these changes help clarify (more than they obscure) the original purpose, although I apologise for the verboseness of the code that follows:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define LENGTH 64
typedef struct node {
char word[LENGTH+1];
struct node * next;
} node;
typedef struct hashtable {
node * table[26];
} hashtable;
/* The cleverest 'hashing' function in the world ever! */
int hash(const char * str) {
if (str && str[0]) return tolower(str[0]) - 'a';
return 0;
}
/* Allocate a new node and initialise it with the given word */
node * node_create(const char * word) {
node * nd = NULL;
if (word && (nd = malloc(sizeof(node)))) {
strncpy(nd->word, word, sizeof(nd->word)-1);
nd->word[sizeof(nd->word) - 1] = '\0';
nd->next = NULL;
}
return nd;
}
/* Set all the buckets' pointers to NULL */
void hashtable_init(hashtable * ht) {
if (ht) memset(ht, 0, sizeof(hashtable));
}
/* Place the given node into the hashtable, taking responsibility for it */
void hashtable_insert_node(hashtable * ht, node * nd) {
if (ht && nd) {
#if 1 /* More succint version using node** */
/* Identify the bucket this node should go into */
node ** cursor = ht->table + hash(nd->word);
/* Append this node to this bucket's list of nodes */
while (*cursor != NULL) cursor = &(*cursor)->next;
*cursor = nd;
#else /* Version that avoids use of node** */
int bucket = hash(nd->word);
/* Identify the bucket this node should go into */
if (ht->table[bucket]) {
node * cursor = ht->table[bucket];
while (cursor->next) cursor = cursor->next;
cursor->next = nd;
} else {
ht->table[bucket] = nd;
}
#endif
nd->next = NULL; // Ensure the new node is the last in the list
}
}
/* Free the contents of the given hashtable */
void hashtable_free_contents(hashtable * ht) {
if (ht) {
int i;
for (i=0; i < sizeof(ht->table)/sizeof(ht->table[0]); ++i) {
node * cursor = ht->table[i];
while (cursor != NULL) {
node * next = cursor->next;
free(cursor);
cursor = next;
}
}
}
}
/* Dump the contents of the given hashtable to stdout */
void hashtable_dump(const hashtable * ht) {
if (ht) {
int i;
for (i=0; i < sizeof(ht->table)/sizeof(ht->table[0]); ++i) {
printf("Bucket %d:", i);
node * cursor = ht->table[i];
while (cursor != NULL) {
printf(" %s", cursor->word);
cursor = cursor->next;
}
printf("\n");
}
}
}
int main(int argc, char * argv[]) {
char dictionary[] = {
"apples "
"apricots "
"oranges "
"lemons "
"bananas "
"raspberries "
"carrots "
"tomatoes "
"aubergines "
"limes "
"blueberries "
"plums "
"pears "
"peaches "
"pineapples "
"tangerines "
"kiwis "
"passion_fruit "
"strawberries "
};
hashtable ht;
hashtable_init(&ht);
char * p = dictionary; /* Pointer for traversing the dictionary */
node new_node; /* Temporary node for storing word read from dictionary */
new_node.next = NULL;
int n; /* Number of bytes read from dictionary in sscanf call */
char format[16];
/* If a huge word is in the dictionary, guard against buffer overflow */
snprintf(format, sizeof(format), "%%%ds%%n", sizeof(new_node.word));
while(sscanf(p, format, new_node.word, &n) == 1) {
/* Insert (a copy of the) new node into hashtable */
hashtable_insert_node(&ht, node_create(new_node.word));
/* Move forwards through the dictionary */
p += n;
}
hashtable_dump(&ht);
hashtable_free_contents(&ht);
return 0;
}
Just allocate memory for each node of the hashtable and then dereference them.
i.e.
int i ;
for(i = 0; i < 729; ++i) {
hashtable[i] = malloc(sizeof(node));
hashtable[i]->next = NULL ;
}

printing tree results , segmentation error , insertion into tree

Here's the code , i run it with one example it works , but when it comes
to comparing i do not understand what's wrong ? , thanks in advance for
any help .I need to print dictionary texts properly (inserting , printing) , can not still come up with a solution , i mean using dictionary data structure like .
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
typedef struct Node_s {
char *element;
struct Node_s *left, *right;
} Node;
typedef struct {
Node *head;
} Table;
//Table *initialize();
//Node *createNode(const char *element);
Table *initialize() {
Table *tb = malloc(sizeof(Table)*1000);
tb->head = NULL;
return tb;
}
Node *createNode( char * element ) {
Node *temp = malloc(sizeof(temp));
temp->element = element ;
temp->left = temp->right = NULL;
return temp;
}
void insert(Table *temp, char *element) {
Node *nd = createNode(element);
Table * place = NULL;
Node *new = NULL;
int cmp = 0;
if(temp->head == NULL) {
temp->head= nd;
printf("empty ! \n");
return;
}
else {
Table *current = temp;
while (current!=NULL) {
cmp = strcmp(current->head->element,element);
if(cmp < 0) {
current->head= current->head->left;
}
else if(cmp > 0) {
current->head = current->head->right;
}
} //while
place = current;
new = nd;
if(cmp > 0 ) {
place->head->right = new ;
}
else if(cmp <0 ) {
place->head->left = new;
}
}
}
void print_table(Table *temp) {
if(temp!=NULL || !temp->head) return;
print_table(temp->head->left);
printf("%s \n",temp->head->element);
print_table(temp->head->right);
}
int main () {
Node * nd = NULL;
//nd->element = "key";
// nd = createNode("key");
Table *tb = initialize();
//tb->head = createNode("key");
//tb->head = createNode("key");
insert(tb, "table element1");
insert(tb, "table element2");
insert(tb, "table element2");
//nd = createNode("key1");
// print_table(t);
//printf("%s \n",nd->element);
print_table(tb);
// printf("%s \n",tb->head->element);
free(nd);
return 0;
}
There are a lot of potential bugs here, but your primary issue is in the following line of createNode:
Node *temp = malloc(sizeof(temp));
Here you're doing a sizeof(temp) and temp is a pointer. This means that you are only allocating enough memory for a pointer (usually 8 bytes). You are hence writing outside of allocating memory when using the left/right members of the heap allocated structure. The fix:
Node *temp = malloc(sizeof(Node));
// EXTRA: I also recommend that you verify that the allocation was successful
if (temp) {
temp->element = element ;
temp->left = temp->right = NULL;
}
return temp;
In printTable, you should also verify that temp itself isn't NULL as you are passing the function parameters that might be NULL:
if(!temp || !temp->head) return;
Also, remove the free(nd); at the end of main, as calling free() on unallocated heap memory corrupts the heap and typically leads to a segfault.
Your printing method crashes when reaching the last node on the left because it will call print_table(NULL) since there's nothing more on the left. After that when it executes the line
if(!temp->head) return;
You get a memory access violation because temp is NULL, you should also check if temp itself is NULL.
if( !temp || !temp->head ) return;
That should fix your problem.
One issue right away is on your second call to insert:
while (current != NULL) {
cmp = strcmp(current->head->element, element); // this line
You didn't check if current->head is NULL itself. According to what you've implemented, you use head as a sentinel, thus it can be NULL. However, your search loop totally forgot about this condition and assumes that head is never NULL.
Your loop doesn't seem fundamentally correct. You traverse the left, so what is supposed to happen if the left branch "runs out" (as it does now when you call insert the second time)?
In addition, your insert function has a memory leak. You potentially allocate 2 new nodes here:
Node *nd = createNode(element);
and here:
new = createNode(element);
Only one is stored while the other is leaked.
Another issue is that your tree does nothing in the while loop if the two items are equal. Two equal items results in an infinite loop:
while (current!=NULL)
{
cmp = strcmp(current->head->element,element);
if(cmp < 0)
current->head= current->head->left;
else if(cmp > 0)
current->head = current->head->right;
else
printf("these are equal ! \n"); // but we don't do anything with current!
}
If the goal is to not have duplicates, then you should exit this function if a duplicate is found. If the goal is to store duplicates, only test for < 0, anything else, goes on the right branch.
This might be what you are looking for.
It handles a doubly linked list
error checking is added
removed undesirable/unnecessary typedef's from struct definitions
corrected the logic to link in new nodes
avoided recursion in the printing of the linked list
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
struct Node
{
char *element;
struct Node *left;
struct Node *right;
};
// define the head pointer for the linked list
struct Node *head = NULL;
// struct Node *createNode(const char *element);
struct Node *createNode( char * element )
{
struct Node *pNewNode = NULL;
if( NULL == (pNewNode = malloc(sizeof(struct Node)) ) )
{ // then, malloc failed
perror( "malloc for new node failed" );
exit( EXIT_FAILURE );
}
// implied else, malloc successful
pNewNode->element = element ; // copies a char pointer
pNewNode->left = NULL;
pNewNode->right = NULL;
return pNewNode;
} // end function: createNode
void insert(char *element)
{
int cmp = 0;
// get ptr to first node in list
struct Node *pCurrentNode = head;
// create the node to be inserted into linked list
struct Node *pNewNode = createNode(element);
if (pCurrentNode == NULL)
{ // then list empty
head = pNewNode;
printf("added first node\n");
return;
}
// implied else, not first node
while (pCurrentNode->right)
{
cmp = strcmp(pCurrentNode->element,element);
if(cmp < 0)
{
// insert new node before current node
pNewNode->right = pCurrentNode;
pNewNode->left = pCurrentNode->left;
pCurrentNode->left = pNewNode;
(pNewNode->left)->right = pNewNode;
}
else if(cmp > 0)
{
// step to next node
pCurrentNode = pCurrentNode->right;
} // end if
// note: if data same, don't insert new node
} //while
if( pCurrentNode->right == NULL )
{ // then, reached end of list
// append new node to end of list
pNewNode->left = pCurrentNode;
pNewNode->right = NULL;
pCurrentNode->right = pNewNode;
} // end if
} // end function: insert
void print_table()
{
struct Node *pCurrentNode = head;
if( pCurrentNode == NULL ) return;
// implied else, list not empty
while( pCurrentNode )
{
printf("%s \n",pCurrentNode->element);
pCurrentNode = pCurrentNode->right;
} // end while
} // end function: print_table
void cleanup()
{
struct Node *pCurrentNode = head;
while( pCurrentNode )
{
pCurrentNode = pCurrentNode->right;
free( pCurrentNode->left );
}
} // end function: cleanup
int main ()
{
// exercise the insert function
insert("table element1"); // append first element
insert("table element2"); // append second element
insert("table element4"); // append third element
insert("table element3"); // insert forth element
insert("table element3"); // duplicate within list
insert("table element4"); // duplicate at end of list
print_table();
cleanup();
return 0;
} // end function: main
I tried a different implementation, it compiles and works, it does not allow duplicates.
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#define ELEMENT_SIZE 1024
typedef struct Node_s
{
char element[ELEMENT_SIZE];
struct Node_s *left, *right;
} Node;
Node * createNode(char *element)
{
Node *node = malloc(sizeof(Node));
node->left = NULL;
node->right = NULL;
memcpy(node->element, element, ELEMENT_SIZE);
return node;
}
void free_node(Node *node)
{
if(!node)
return;
free_node(node->left);
free_node(node->right);
free(node);
}
Node * insert(Node **head_ptr, char *element)
{
Node *head = *head_ptr;
if(head == NULL){
Node *node = createNode(element);
head = node;
*head_ptr = node;
return node;
}else{
int comp = strcmp(head->element, element);
if(comp < 0){
// go left
if(head->left == NULL){
// set element to be temp left
Node *node = createNode(element);
head->left = node;
return node;
}else{
return insert(&head->left, element);
}
}else if(comp > 0){
// go right
if(head->right == NULL){
// set element to be temp left
Node *node = createNode(element);
head->right = node;
return node;
}else{
return insert(&head->right, element);
}
}else{
// element exists
printf("Element \"%s\" already exists\n", element);
return NULL;
}
}
}
void print_table(Node *temp)
{
if(!temp)
return;
printf("%s \n",temp->element);
print_table(temp->left);
print_table(temp->right);
}
int main ()
{
Node *nd = NULL;
printf("Address of nd is %p\n", &nd);
Node *n1 = insert(&nd, "table element 1");
n1 = insert(&nd, "table element 2");
n1 = insert(&nd, "table element 3");
n1 = insert(&nd, "element 1");
n1 = insert(&nd, "element 2");
n1 = insert(&nd, "element 3");
n1 = insert(&nd, "alternative 1");
n1 = insert(&nd, "alternative 2");
n1 = insert(&nd, "alternative 3");
n1 = insert(&nd, "alternative 1");
n1 = insert(&nd, "alternative 2");
n1 = insert(&nd, "alternative 3");
print_table(nd);
free_node(nd);
return 0;
}

Write a function that rearranges a linked list to put the nodes in even positions after the nodes in odd positions in the list

Write a function that rearranges a linked list to put the nodes in even positions after the nodes in odd positions in the list, preserving the relative order of both the evens and the odds.
I found this problem in the book Algorithm in c writtern by Sedgewick. I have tried but failed. I trid to put all nodes in even positions on another linked list. It's grateful for you to help me. A good idea is enough. Thanks :).
This is my Code in C.
/*
* File: rearranges.c <Exercise 3.36>
* Note: Write a function that rearranges a linked list to put the nodes in even
* positions after the nodes in odd positions in the list, preserving the
* relative order of both the evens and the odds.
* NOTICE: I think it's necessary to use linked list with a dummy head.
* Time: 2013-10-26 10:58
*/
#include <stdio.h>
#include <stdlib.h>
#define LEN 11
typedef struct node *link;
struct node {
int item;
link next;
};
/* Traverse a linked list with a dummy head. */
void traverse(link t) {
link x = t->next;
while (x != NULL) {
printf("%d ", x->item);
x = x->next;
}
putchar('\n');
}
/* Detach even positon nodes from a linked list. */
link detach(link t) {
link u = malloc(sizeof(*u));
link x = t, y = u;
/* x is odd position node. We should ensure that there's still one even
* position node after x. */
while (x != NULL && x->next != NULL) {
y->next = x->next;
x->next = x->next->next;
x = x->next;
y = y->next;
y->next = NULL;
}
return u;
}
/* Combine two linked list */
link combine(link u, link t) {
link x = u;
link y = t->next;
while (y != NULL) {
link n = y->next;
y->next = x->next;
x->next = y;
x = x->next->next;
y = n;
}
return u;
}
/* The function exchanges the position of the nodes in the list. */
link rearranges(link t) {
link u = detach(t);
link v = combine(u, t);
return v;
}
int main(int argc, char *argv[]) {
int i;
link t = malloc(sizeof(*t));
link x = t;
for (i = 0; i < LEN; i++) {
x->next = malloc(sizeof(*x));
x = x->next;
x->item = i;
x->next = NULL;
}
traverse(t);
traverse(rearranges(t));
return 0;
}
curr=head;
end=lastOfList;//last node if size of list is odd or last-1 node
for(int i=1;i<=listSize()/2;i++)
{
end->next=curr->next;
end=end->next;
end->next=null;
if(curr->next!=null)
if((curr->next)->next!=null)
curr->next=(curr->next)->next;
curr=curr->next;
}
You can implement a recursive solution where each call returns an updated node that will serve as the new next reference for the upper caller. We just have to go down the list until we find the last element, and then move every even node to the end of the list, and update the reference to the last element. Here's my solution (please try to do it yourself before looking at my and other solutions):
struct node {
int val;
struct node *next;
};
struct node *reorder_aux(struct node *l, int count, struct node **last);
struct node *reorder(struct node *l) {
struct node *x;
if (l == NULL)
return NULL;
return reorder_aux(l, 1, &x);
}
struct node *reorder_aux(struct node *l, int count, struct node **last) {
struct node *n;
if (l->next == NULL) {
*last = l;
return l;
}
n = reorder_aux(l->next, count+1, last);
if (count & 1) {
l->next = n;
return l;
}
else {
(*last)->next = l;
l->next = NULL;
*last = l;
return n;
}
}
At each step, if the current node l is an even node (as determined by count), then we append this node to the end, and tell the upper caller that its next pointer shall be updated to our next (because our next will be an odd node). In case we're an odd node, we just have to update our next pointer to whatever the recursive call returned (which will be a pointer to an odd node), and return the current node, since we will not move ourselves to the end of the list.
It's a nice exercise!
#include <stdio.h>
struct list {
struct list *next;
int ch;
};
void swap_odd_even (struct list **pp)
{
struct list *one, *two ;
for( ; (one = *pp) ; pp = &one->next) {
two = one->next;
if (!two) break;
*pp = two;
one->next = two->next;
two->next = one;
}
}
struct list arr[] =
{ {arr+1, 'A'} , {arr+2, 'B'} , {arr+3, 'C'} , {arr+4, 'D'}
, {arr+5, 'E'} , {arr+6, 'F'} , {arr+7, 'G'} , {arr+8, 'H'}
, {arr+9, 'I'} , {arr+10, 'J'} , {arr+11, 'K'} , {arr+12, 'L'}
, {arr+13, 'M'} , {arr+14, 'N'}, {arr+15, 'O'} , {arr+16, 'P'}
, {arr+17, 'Q'} , {arr+18, 'R'} , {arr+19, 'S'} , {arr+20, 'T'}
, {arr+21, 'U'} , {arr+22, 'V'}, {arr+23, 'W'} , {arr+24, 'X'}
, {arr+25, 'Y'} , {NULL, 'Z'} };
int main (void) {
struct list *root , *ptr;
root = arr;
for (ptr=root ; ptr; ptr = ptr->next ) {
printf( "-> %c" , ptr->ch );
}
printf( "\n" );
printf( "Swap\n" );
swap_odd_even ( &root);
for (ptr=root ; ptr; ptr = ptr->next ) {
printf( "-> %c" , ptr->ch );
}
printf( "\n" );
return 0;
}
In the following, every time swap_nodes is called another odd sinks to the last sunk odd. The evens are grouped together on each iteration and they bubble up to the end of the list. Here is an example:
/*
[0]-1-2-3-4-5
1-[0-2]-3-4-5
1-3-[0-2-4]-5
1-3-5-[0-2-4]
*/
#include <stdio.h>
#include <stdlib.h>
#define LIST_LENGTH 10
struct node{
int id;
struct node *next;
};
void print_list(struct node *current)
{
while(NULL != current){
printf("node id = %d\n",current->id);
current = current->next;
}
printf("Done\n");
}
struct node *swap_nodes(struct node *head_even, struct node *tail_even, struct node *next_odd)
{
tail_even->next = next_odd->next;
next_odd->next = head_even;
return next_odd;
}
struct node *reorder_list(struct node *head)
{
struct node *head_even;
struct node *tail_even;
struct node *next_odd;
struct node *last_odd;
if(NULL == head->next){
return head;
}
head_even = head;
tail_even = head;
next_odd = head->next;
last_odd = head->next;
head = swap_nodes(head_even, tail_even, next_odd);
if(NULL != tail_even->next){
tail_even = tail_even->next;
}
while (NULL != tail_even->next) {
next_odd = tail_even->next;
last_odd->next = swap_nodes(head_even, tail_even, next_odd);
last_odd = last_odd->next;
if(NULL != tail_even->next){
tail_even = tail_even->next;
}
}
return head;
}
int main(void)
{
int i;
struct node *head = (struct node *) malloc(LIST_LENGTH*sizeof(struct node));
struct node *mem = head;
if(NULL == head){
return -1;
}
struct node *current = head;
for(i=0;i<LIST_LENGTH-1;i++){
current->next = current + 1;
current->id = i;
current = current->next;
}
current->next = NULL;
current->id = i;
head = reorder_list(head);
print_list(head);
free(mem);
return 0;
}

Error in trying to count the nodes in circular doubly linked list recursively

Here is my implementation of count:
int count(node *start)
{
static int l ;
node *current; /* Node for travelling the linked list*/
current=start;
if(current->next!=start)
{
l = 1 + count ( current->next ) ;
return ( l ) ;
}
else
{
return(1);
}
}
Here is a fragment of main function where I am calling it:
void main()
{
node *head;
printf ( "Length of linked list = %d", count ( head ) ) ;
}
Here is the structure:
struct cirdoublelinklist
{
struct cirdoublelinklist *prev; /** Stores address of previous node **/
int value; /** stores value **/
struct cirdoublelinklist *next; /** stores address of next node **/
};
/** Redefining list as node **/
typedef struct cirdoublelinklist node;
On running and trying to see the length of a list, it crashes with out of bound memory. Please help me with this, I have been working on this for a long time now.
Method to add the first node:
void initialize(node *start)
{
start->prev=start;
printf("\nEnter Value\n");
scanf("%d",&start->value);
start->next=start;
}
Method to add subsequent nodes after the location specified:
void insert_after(node *start)
{
int num; /* value for inserting a node */
int flag=0;
node *newnode; /* New inputed node*/
node *current; /* Node for travelling the linked list*/
newnode=(node*)malloc(sizeof(node));
printf("\nEnter the value after which you want to insert a node\n");
scanf("%d",&num);
init(newnode);
current=start;
while(current->next!=start)
{
if(current->value==num)
{
newnode->next=current->next;
current->next->prev=newnode;
current->next=newnode;
newnode->prev=current;
flag=1;
}
current=current->next;
}
if(flag==0 && current->next==start && current->value==num)
{
/*** Insertion checking for last node ***/
newnode->next=current->next; /* Start is being copied */
current->next->prev=newnode;
current->next=newnode;
newnode->prev=current;
flag=1;
}
if(flag==0 && current->next==NULL)
printf("\nNo match found\n");
}
Every time you call count, it has a new start, so current->next!=start is always comparing a node to its successor, which will only ever end if the list has length 1. What you most likely want to do is have two functions:
int count(node *start)
{
if(start == NULL)
return 0;
return count_helper(start, start);
}
int count_helper(node *start, node *current)
{
static int l;
if(current->next!=start)
{
l = 1 + count (start, current->next);
return ( l ) ;
}
else
{
return(1);
}
}
As others have mentioned, the static variable is not necessary. A better way of writing what I have called count_helper would be:
int count_helper(node *start, node *current)
{
if(current->next!=start)
{
return 1 + count (start, current->next);
}
else
{
return 1;
}
}
Finally, a more efficient implementation would be non-recursive:
int count(node *start)
{
if(start == NULL)
return 0;
node *current = start->next;
int c = 1;
while(current != start)
{
c++;
current = current->next;
}
return c;
}
Well, the problem is that you call the function in the main on a NULL pointer. Infact node *head; is declared but never assigned to something. So when you execute this line:
if(current->next!=start)
the program crashes because it will check for NULL->next that, obviously, doesn't exist.
You need to pass a pointer to start pointer in insert_after function
void insert_after(node **start)
instead of
void insert_after(node *start)
Otherwise you'll be just updating the local copy of *start.
Similarly for initialize
void initialize(node **start)
Put simply, the recursive calls don't know the original start node. You will need to add a second node* argument and pass the start node via it.
Here's a recursive solution that doesn't use static or helper variables:
int count(Node* head) {
// Base cases:
// 0 nodes
if (!head)
return 0;
// 1 node
if (head->next == next)
return 1;
// Keep a pointer to the node to be removed
Node* rest = head->next;
// Remove the node
head->next = head->next->next;
// Get the length of the new list
int result = 1 + count(head->next);
// Reconnect the node
head->next = rest;
return result;
}

Resources