Count distinct elements in an list in C [duplicate] - c

How can i find only the elements that appears once in the list and return the cardinal number?For example if my list consist of {3,2,1,1,2,4} i expect for return the counter to be 4 and not 6 cause we do not count the duplicate numbers.
Here is the code that i have written so far.
struct Node
{
int data;
struct Node *next;
};
int Find_cardinal(struct Node *start)
{
struct Node *ptr1, *ptr2
ptr1 = start;
int counter=0;
/* Pick elements one by one */
while (ptr1 != NULL && ptr1->next != NULL)
{
ptr2 = ptr1;
/* Compare the picked element with rest
of the elements */
while (ptr2->next != NULL)
{
/* If duplicate */
if (ptr1->data == ptr2->next->data)
{
break;
}
else
//do what?
ptr2 = ptr2->next;
}
ptr1 = ptr1->next;
}
return counter;
}

Your function implementation is wrong.
Even the condition in the first while loop
while (ptr1 != NULL && ptr1->next != NULL)
is incorrect because if the list contains only one node the loop will not be executed and the function will return 0.
And within the function the variable counter is not being changed.
Here is a demonstrative program that shows how the function Find_cardinal that is better to name like count_distinct can be implemented.
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node *next;
};
typedef struct Node Node_t;
size_t assign( Node_t **head, const int a[], size_t n )
{
while ( *head )
{
Node_t *tmp = *head;
head = &( *head )->next;
free( tmp );
}
size_t i = 0;
for ( ; i < n && ( *head = malloc( sizeof( Node_t ) ) ) != NULL; i++ )
{
( *head )->data = a[i];
( *head )->next = NULL;
head = &( *head )->next;
}
return i;
}
size_t count_distinct( const Node_t *head )
{
size_t n = 0;
for ( const Node_t *current = head; current != NULL; current = current->next )
{
const Node_t *prev = head;
while ( prev != current && prev->data != current->data )
{
prev = prev->next;
}
if ( prev == current ) ++n;
}
return n;
}
FILE * display( const Node_t *head, FILE *fp )
{
for ( ; head != NULL; head = head->next )
{
fprintf( fp, "%d -> ", head->data );
}
fputs( "null", fp );
return fp;
}
int main(void)
{
Node_t *head = NULL;
int a[] = { 1, 2, 1, 1, 3, 4 };
assign( &head, a, sizeof( a ) / sizeof( *a ) );
fputc( '\n', display( head, stdout ) );
printf( "There are %zu distinct data in the list.\n", count_distinct( head ) );
return 0;
}
The program output is
1 -> 2 -> 1 -> 1 -> 3 -> 4 -> null
There are 4 distinct data in the list.

You cannot do it using your current construct. The idea is to iterate through the list and 'remember' or check whether a particular item is duplicate, so somehow you need to store the unique values that have been passed. Below is one naive implementation. Sample output:
Input values
3
2
1
1
2
4
Unique count: 4
Code:
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node *next;
};
void printAll(struct Node *start){
struct Node *ptr1;
ptr1 = start;
while (ptr1 != NULL) {
printf("%d\n", ptr1->data);
ptr1 = ptr1->next;
}
}
int countUnique(struct Node *start) {
struct Node *uniqueNodes; //this will hold the unique value
struct Node *ptrInput;
ptrInput = start;
int counter = 0;
/* Pick elements one by one */
while (ptrInput != NULL) {
//Loop through the list which hold the unique value
struct Node *ptrUnique;
ptrUnique = uniqueNodes;
int isFound = 0;
while (ptrUnique != NULL && !isFound) {
if (ptrInput->data == ptrUnique->data) {
isFound = 1; //value is found in the unique list
} //end if
ptrUnique = ptrUnique->next;
} //end while
if (! isFound) { //when not found, then need to add the value in the unique list and increment the counter afterwards
struct Node *newNode = (struct Node *) malloc (sizeof(struct Node));
newNode->data = ptrInput->data;
newNode->next = NULL;
//If uniqueNodes is still empty, then just change the pointer of the uniqueNodes to the newly created item.
//Otherwise, just put the newly created item on the head of the list
if (uniqueNodes == NULL) {
uniqueNodes = newNode;
} else {
newNode->next = uniqueNodes;
uniqueNodes = newNode;
} //end else
counter++;
} //end if
ptrInput = ptrInput->next;
} //end while
return counter;
}
int main(void) {
struct Node *node1 = (struct Node *) malloc (sizeof(struct Node));
struct Node *node2 = (struct Node *) malloc (sizeof(struct Node));
struct Node *node3 = (struct Node *) malloc (sizeof(struct Node));
struct Node *node4 = (struct Node *) malloc (sizeof(struct Node));
struct Node *node5 = (struct Node *) malloc (sizeof(struct Node));
struct Node *node6 = (struct Node *) malloc (sizeof(struct Node));
node1->data = 3;
node2->data = 2;
node3->data = 1;
node4->data = 1;
node5->data = 2;
node6->data = 4;
node1->next = node2;
node2->next = node3;
node3->next = node4;
node4->next = node5;
node5->next = node6;
node6->next = NULL;
printf("Input values\n", NULL);
printAll(node1);
int uniq = countUnique(node1);
printf("\nUnique count: %d\n", uniq);
return 0;
}

Related

Getting the nth from last of the linked list

What I'm doing is that first I reversed the linked list and then actually I'm trying to get the nth value of a node. The problem is that the function isn't doing anything after it reverses the linked list and doesn't give an error for some reason.
Here's my code:
#include<stdlib.h>
#include<assert.h>
// 1. Create a linked list first
struct Node {
int data;
struct Node* next;
};
// 2. Create traversal function for linked list
void linkedListTraversal(struct Node* ptr) {
while (ptr != NULL) {
printf("%d\n", ptr->data);
ptr = ptr->next;
}
}
// 3. Write a function to get the node value from the tail of the linked list
int getNode(struct Node* head, int positionFromTail) {
int value;
struct Node* prevNode = NULL;
struct Node* currNode = head;
struct Node* nextNode;
while (currNode != NULL) {
nextNode = currNode->next;
currNode->next = prevNode;
prevNode = currNode;
currNode = nextNode;
}
head = prevNode;
struct Node* ptr = head;
int count = 0;
while (ptr != NULL) {
if (count == positionFromTail) {
return (ptr->data);
count = count + 1;
ptr = ptr->next;
}
}
assert(0);
}
int main() {
struct Node* head;
struct Node* second;
struct Node* third;
struct Node* fourth;
head = (struct Node*)malloc(sizeof(struct Node));
second = (struct Node*)malloc(sizeof(struct Node));
third = (struct Node*)malloc(sizeof(struct Node));
fourth = (struct Node*)malloc(sizeof(struct Node));
head->data = 3;
head->next = second;
second->data = 2;
second->next = third;
third->data = 1;
third->next = fourth;
fourth->data = 0;
fourth->next = NULL;
linkedListTraversal(head);
printf("The value of the node is %d", getNode(head, 2));
}
Here's my output and any help will be appreciated.
3
2
1
0
You can have an infinite loop because the pointer ptr is changed only when the condition of the if statement within the loop evaluates to true
while (ptr!=NULL)
{
if (count == positionFromTail)
{
return (ptr->data);
count = count + 1;
ptr = ptr->next;
}
}
Rewrite the for loop at least for example like
while ( ptr != NULL && positionFromTail-- )
{
ptr = ptr->next;
}
if ( ptr != NULL )
{
return ptr->data;
}
else
{
// return some value
return -1;
}
Also the parameter positionFromTail shall have an unsigned integer type. Otherwise you need to check in the beginning of the function whether it has a negative value.
Pay attention to that after exiting the function your list will be broken. The pointer head in main will not be changed after calling the function but the value of the data member next of the node pointed to by the pointer and of other nodes will be changed. So in general your approach is incorrect.
There is no need to reverse the list to find an element at the given position counted from the end of the list.
For starters I would declare the function the following way
int getNode( const struct Node *head, int pos, int *data );
That is the function returns either 1 if there exists a node with the specified position or 0 otherwise. If there is a node with the specified position then the stored value is written in the dereferenced parameter data.
If the value of the parameter pos is not negative then counting of nodes starts from the head otherwise from the end of the list.
Here is a demonstration program.
#include <stdlib.h>
#include <stdio.h>
struct Node
{
int data;
struct Node *next;
};
void clear( struct Node **head )
{
while (*head)
{
struct Node *current = *head;
*head = ( *head )->next;
free( current );
}
}
size_t create( struct Node **head, const int a[], size_t n )
{
clear( head );
size_t i = 0;
while (n-- && ( *head = malloc( sizeof( struct Node ) ) ) != NULL )
{
( *head )->data = *a++;
( *head )->next = NULL;
++i;
head = &( *head )->next;
}
return i;
}
FILE * display( const struct Node *head, FILE *fp )
{
for (; head != NULL; head = head->next)
{
fprintf( fp, "%d -> ", head->data );
}
fputs( "null", fp );
return fp;
}
int getNode( const struct Node *head, int pos, int *data )
{
int success = 0;
if (!( pos < 0 ))
{
while (head != NULL && pos--)
{
head = head->next;
}
if (( success = head != NULL )) *data = head->data;
}
else
{
const struct Node *current = head;
for ( ;current != NULL && pos; ++pos )
{
current = current->next;
}
while (current != NULL )
{
head = head->next;
current = current->next;
}
if (( success = pos == 0 )) *data = head->data;
}
return success;
}
int main( void )
{
struct Node *head = NULL;
const int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
create( &head, a, sizeof( a ) / sizeof( *a ) );
fputc( '\n', display(head, stdout ) );
for (int i = 0, data; getNode( head, i, &data ); i++)
{
printf( "%d: %d; ", i, data );
}
putchar( '\n' );
for (int i = -1, data; getNode( head, i, &data ); i--)
{
printf( "%d: %d; ", i, data );
}
putchar( '\n' );
clear( &head );
}
The program output is
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
0: 0; 1: 1; 2: 2; 3: 3; 4: 4; 5: 5; 6: 6; 7: 7; 8: 8; 9: 9;
-1: 9; -2: 8; -3: 7; -4: 6; -5: 5; -6: 4; -7: 3; -8: 2; -9: 1; -10: 0;

Why isn't my reverse(); function working?

I'm writing a program in C for reversing a circular singly linked list. I keep getting segmentation fault for some reason. I'm sure the problem is with the reverse function as I tried commenting the function call, the program works fine.
For my reverse() function, I have used 3 pointers: prev, next and curr. The logic is that I'll run a loop till curr takes the address of head, which will be stored in the link part of the last node since it is a circular linked list. I'll keep updating curr->link using prev pointer which will change its link from the next to its previous node.
When the loop breaks, head->link = prev; and head = prev; will update the respective addresses such that they point to the first node of the reversed list.
//reversing CLL
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *link;
} *head;
void reverse() {
struct node *prev = NULL, *curr = head, *next;
while (curr != head) {
next = curr->link;
curr->link = prev;
prev = curr;
curr = next;
}
head->link = prev;
head = prev;
}
void createList(int n) {
int i, data;
head = (struct node *)malloc(sizeof(struct node));
struct node *ptr = head, *temp;
printf("Enter data of node 1\t");
scanf("%d", &data);
head->data = data;
head->link = NULL;
for (i = 2; i <= n; i++) {
temp = (struct node *)malloc(sizeof(struct node));
printf("Enter data of node %d\t", i);
scanf("%d", &data);
temp->data = data;
temp->link = NULL;
ptr->link = temp;
ptr = ptr->link;
}
ptr->link = head;
}
void disp() {
struct node *ptr = head;
do {
printf("%d\t", ptr->data); //gdb debugger shows problem is in this line
ptr = ptr->link;
} while (ptr != head);
}
int main() {
int n;
printf("Enter no of nodes to be created\t");
scanf("%d", &n);
createList(n);
printf("\n\nList is displayed below!\n");
disp();
printf("\n\nReversing list ...\n");
reverse(); // on commenting this call, disp() function
// works accurately showing node data non-reversed
disp();
printf("\n\nList successfully reversed!\n");
}
The loop in the reverse() function exits immediately because curr is initialized to the value of head so the test while (curr != head) is false at the first iteration.
reverse() then sets head->link to NULL and finally head is also set to NULL (the initial value of prev), which explains the segmentation fault in the subsequent disp() function where you use a do { } while (pre != head) that cannot handle an empty list.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *link;
};
struct node *reverse(struct node *head) {
struct node *prev = NULL, *curr = head;
if (head) {
do {
struct node *next = curr->link;
curr->link = prev;
prev = curr;
curr = next;
} while (curr != head);
curr->link = prev;
head = prev;
}
return head;
}
struct node *createList(int n) {
struct node *head = NULL, *tail = NULL, *temp;
int i;
for (i = 1; i <= n; i++) {
temp = (struct node *)malloc(sizeof(struct node));
temp->data = 0;
temp->link = NULL;
printf("Enter data of node %d\t", i);
scanf("%d", &temp->data);
if (head == NULL) {
head = temp;
} else {
tail->link = temp;
}
tail = temp;
temp->link = head;
}
return head;
}
void disp(struct node *head) {
if (head) {
struct node *ptr = head;
do {
printf("%d\t", ptr->data);
ptr = ptr->link;
} while (ptr != head);
}
}
int main() {
struct node *head;
int n = 0;
printf("Enter no of nodes to be created\t");
scanf("%d", &n);
head = createList(n);
printf("\n\nList is displayed below!\n");
disp(head);
printf("\n\nReversing list ...\n");
head = reverse(head);
disp(head);
printf("\n\nList successfully reversed!\n");
// should free the list
return 0;
}
For starters it is a bad idea to use the global variable head
struct node {
int data;
struct node *link;
} *head;
In this case the functions depend on the global variable and you can not use more than one list in a program.
Due to this initialization
struct node *prev = NULL, *curr = head, *next;
^^^^^^^^^^^^
the condition of the while loop
while (curr != head) {
is never evaluates to true because initially the pointer curr is equal to the pointer head.
Moreover if the list is empty then this statement
head->link = prev;
invokes undefined behavior.
Here is a demonstrative program that shows how the list can be declared in main and then reversed.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *link;
};
size_t assign( struct node **head, const int a[], size_t n )
{
while ( *head )
{
struct node *tmp = *head;
*head = ( *head )->link;
free( tmp );
}
size_t total = 0;
struct node *first = NULL;
while ( total < n && ( *head = malloc( sizeof( struct node ) ) ) != NULL )
{
( *head )->data = a[total];
( *head )->link = NULL;
++total;
if ( first == NULL ) first = *head;
head = &( *head )->link;
}
if ( first != NULL ) *head = first;
return total;
}
void display( const struct node *head )
{
if ( head != NULL )
{
const struct node *current = head;
do
{
printf( "%d -> ", current->data );
} while ( ( current = current->link ) != head );
}
puts( "null" );
}
struct node * reverse( struct node **head )
{
if ( *head )
{
struct node *last = *head;
struct node *prev = NULL;
while ( ( *head )->link != last )
{
struct node *current = *head;
*head = ( *head )->link;
current->link = prev;
prev = current;
}
( *head )->link = prev;
last->link = *head;
}
return *head;
}
int main(void)
{
struct node *head = NULL;
int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
assign( &head, a, sizeof( a ) / sizeof( *a ) );
display( head );
display( reverse( &head ) );
display( reverse( &head ) );
return 0;
}
The program output is
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
9 -> 8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> 0 -> null
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null

how can i swap two nodes without exchanging data

#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
struct node *head;
void createnodeatbeg(int key) {
struct node *new = (struct node*)malloc(sizeof(struct node));
new->data = key;
new->next = head;
head = new;
}
void printlist() {
struct node *temp = head;
printf("list is:");
while (temp != NULL) {
printf("%d ", temp->data);
temp = temp->next;
}
printf("\n");
}
void swapnodes(int x, int y) {
struct node *prevX = NULL;
struct node *prevY = NULL;
struct node *currX = head;
struct node *currY = head;
while (currX->data != x && currX != NULL) {
prevX = currX;
currX = currX->next;
}
printf("not found\n");
while (currY->data != y && currY != NULL) {
prevY = currY;
currY = currY->next;
}
if (currX == NULL || currY == NULL) {
printf("elements not found\n");
return;
}
struct node *swap = currY->next;
prevX->next = currY;
currY->next = prevY;
prevY->next = currX;
currX->next = swap;
}
int main() {
head = NULL;
int nodes, key;
printf("enter number of nodes\n");
scanf("%d", &nodes);
for (int i = 0; i < nodes; i++) {
int data;
printf("enter number\n");
scanf("%d", &data);
createnodeatbeg(data);
}
printlist();
int x, y;
printf("enter the values from the list to be swapped\n");
scanf("%d %d", &x, &y);
swapnodes(x, y);
printf("swapped list is:\n");
printlist();
}
My code works when elements (x and y) are present in the list but if it is not present in the list then error is ./a.out terminated by signal SIGSEGV (Address boundary error).
The problem is that the control doesn't comes out of the first while loop in swapNodes() function.
The code takes a user input and creates a node at the beginning.
The order of operands in the conditions of the while statements is wrong.
while(currX->data!=x && currX!=NULL)
{
prevX=currX;
currX=currX->next;
}
//...
while(currY->data!=y && currY!=NULL)
{
prevY=currY;
currY=currY->next;
}
Here must be
while(currX != NULL && currX->data!=x)
{
prevX=currX;
currX=currX->next;
}
//...
while(currY != NULL && currY->data!=y)
{
prevY=currY;
currY=currY->next;
}
So if for example currX is equal to NULL then the expression currX->data!=x will not be eva;luated.
This code snippet
struct node *swap = currY->next;
prevX->next = currY;
currY->next = prevY;
prevY->next = currX;
currX->next = swap;
is also wrong because for example prevX or prevY can be equal to NULL.
And you have to deal with the head in the function by reference. Otherwise the head node will not be changed.
You should split the function into two functions. The first one founds the node with the given value and the second one will swap found nodes if they are not equal to NULL.
Also it is a bad idea when functions depend on global variables. In fact your program can not deal with two lists simultaneously.
Here is a demonstrative program that shows how the function swap can be implemented.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
};
struct node ** find( struct node **head, int data )
{
while ( *head && ( *head )->data != data ) head = &( *head )->next;
return head;
}
void swap( struct node **head, int data1, int data2 )
{
struct node **left, **right;
if ( *( left = find( head, data1 ) ) && *( right = find( head, data2 ) ) )
{
struct node *tmp = *left;
*left = *right;
*right = tmp;
tmp = ( *left )->next;
( *left )->next = ( *right )->next;
( *right )->next = tmp;
}
}
int push_front( struct node **head, int data )
{
struct node *tmp = malloc( sizeof( struct node ) );
int success = tmp != NULL;
if ( success )
{
tmp->data = data;
tmp->next = *head;
*head = tmp;
}
return success;
}
void display( struct node **head )
{
for ( struct node *current = *head; current; current = current->next )
{
printf( "%d ", current->data );
}
}
int main(void)
{
const int N = 10;
struct node *head = NULL;
for ( int i = 0; i < N; i++ ) push_front( &head, i );
display( &head );
putchar( '\n' );
for ( int i = 0; i < N; i+=2 )
{
swap( &head, i, i + 1 );
}
display( &head );
putchar( '\n' );
return 0;
}
Its output is
9 8 7 6 5 4 3 2 1 0
8 9 6 7 4 5 2 3 0 1
The problem is in following identical lines:
while(currX->data!=x && currX!=NULL)
while(currY->data!=y && currY!=NULL)
This is because instead of fist checking for NULL and then use it, you are checking for NULL latter. So when x or y is not present then you are trying to access NULL->data, which is giving Segmentation Fault Error (SIGSEGV)
Change it to following respectively:
while(currX!=NULL && currX->data!=x)
while(currY!=NULL && currY->data!=y)

What is wrong with my code for Pairwise swapping of linked list in C?

This is my code for pairswapping:
#include<stdio.h>
#include<stdlib.h>
struct Node{
int data;
struct Node *next;
};
int main(){
struct Node *list, *head;
head = (struct Node *)malloc(sizeof(struct Node));
list = head;
int i;
for(i=0;i<6;i++){
list->data=i;
list->next = (struct Node *)malloc(sizeof(struct Node));
list = list->next;
}
list->next = NULL;
list = head;
while(list->next->next!=NULL){
int temp = list->data;
list->data = list->next->data;
list->next->data = temp;
list = list->next->next;
}
printf("Pair swapped list: ");
while(head->next!=NULL){
printf("%d\n",head->data);
head=head->next;
}
return 0;
}
I have two problems. The main is that this code is giving a runtime error, I don't see why. and second thing is that if I use list = NULL instead of list->next = null and then while(list!=NULL) then it is causing infinite loop. and if the code is kept same, a garbage element is created at end. please help me.
The line causing problem is:
while(list->next->next!=NULL) {
You do not handle when list->next is NULL
So, just replace it with:
while(list->next != NULL && list->next->next != NULL) {
And for the second problem, as pointed by DevSolar, you must control better the list creation:
struct Node *list, *head, *last;
head = list = last = NULL;
for (i=0; i<6; i++)
{
/* create a node */
list = malloc(sizeof *list);
/* if head is not set, set it */
if (NULL == head)
head = list;
/* fill new element */
list->data = i;
list->next = NULL;
/* this new node is the child of the previous */
if (NULL != last)
last->next = list;
/* remember last created node */
last = list;
}
You have 7 nodes -- the head, and the 6 you create in the loop.
Your while checks for list->next->next!=NULL, and at the end of the loop you move list like this: list = list->next->next;
This means your loop runs for:
1st node, swapped with 2nd
3rd node, swapped with 4th
5th node, swapped with 6th.
Then list is set to the 7th node (with list->next being NULL). And your while checks for list->next->next. As stated, list->next is NULL, list->next->next is an illegal memory access (dereferencing NULL).
(Deferring to purplepsycho for what you should do -- I don't copy from other people's answers. ;-) )
For starters according to the C Standard the function main without parameters shall be declared like
int main( void )
In this loop
for(i=0;i<6;i++){
list->data=i;
list->next = (struct Node *)malloc(sizeof(struct Node));
list = list->next;
}
list->next = NULL;
there is allocated a redundant node with an inderterminate value of the data member data.
The condition in this while loop
while(list->next->next!=NULL){
int temp = list->data;
list->data = list->next->data;
list->next->data = temp;
list = list->next->next;
}
is wrong and leads to undefined behavior due to this statement at the end of the loop
list = list->next->next;
The condition should be written like
while ( list && list->next )
Using your approach the program can look the following way
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node *next;
};
int main(void)
{
struct Node *list, *head;
const int N = 6;
head = ( struct Node * )malloc( sizeof( struct Node ) );
list = head;
int i = 0;
do
{
list->data = i;
} while ( ++i < N && ( list = list->next = ( struct Node *)malloc( sizeof( struct Node ) ) ) );
list->next = NULL;
printf("Original list: ");
for ( list = head; list; list = list->next )
{
printf( "%d ", list->data );
}
putchar( '\n' );
list = head;
while ( list && list->next )
{
int temp = list->data;
list->data = list->next->data;
list->next->data = temp;
list = list->next->next;
}
printf("Pair swapped list: ");
for ( list = head; list; list = list->next )
{
printf( "%d ", list->data );
}
putchar( '\n' );
return 0;
}
Its output is
Original list: 0 1 2 3 4 5
Pair swapped list: 1 0 3 2 5 4
You can add yourself checks that malloc(s) were successfull.
A more safe program can be written using the variable list of the type struct Node **.
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node *next;
};
int main(void)
{
const int N = 6;
struct Node *head;
struct Node **list;
list = &head;
for ( int i = 0; ( i < N ) && ( *list = ( struct Node *)malloc( sizeof( struct Node ) ) ); i++ )
{
if ( *list )
{
( *list )->data = i;
list = &( *list )->next;
}
}
*list = NULL;
printf("Original list: ");
for ( list = &head; *list; list = &( *list )->next )
{
printf( "%d ", ( *list )->data );
}
putchar( '\n' );
list = &head;
while ( *list && ( *list )->next )
{
int temp = ( *list )->data;
( *list )->data = ( *list )->next->data;
( *list )->next->data = temp;
list = &( *list )->next->next;
}
printf("Pair swapped list: ");
for ( list = &head; *list; list = &( *list )->next )
{
printf( "%d ", ( *list )->data );
}
putchar( '\n' );
return 0;
}
Take into account that you should free all allocated memory for the list.
And one more remark. The program does not swap nodes. It swaps values of the data member data of adjacent nodes.:)

Doubly Linked List Insertion With Recursion in C

I'm more or less just learning C, I was given an simple assignment that deals with doubly linked lists, dynamic data allocation, and recursion. I created an array of just 10 integers and I am trying to put these integers into a sorted doubly linked list using recursion. I am having some trouble with inserting nodes into the linked list; I think I have the first node down, but I'm not sure if the rest makes any sense. Right now I'm also getting a segmentation fault... Thank you for any help!
#include <stdio.h>
#include <stdlib.h>
#define N 10
typedef struct node_ {
int value;
struct node_ *next;
struct node_ *prev;
} node;
void insert(node **head, node *cur, node *p);
void print_list(node *cur);
void print_list(node *cur)
{
if (!cur) {
printf("\n");
return;
} else {
printf("%d ", cur->value);
print_list(cur->next);
}
}
int main(int argc, char *argv[])
{
int i;
int data[N] = {2, 7, 3, 9, 4, 4, 0, 8, 7, 100};
node *p, *head;
head = NULL;
for (i = 0; i < N; i++) {
p = (node *)malloc(sizeof(node));
p->value = data[i];
insert(&head, head, p);
}
print_list(head);
}
void insert(node **head, node *cur, node *p)
{
if(*head == NULL)
{
p->next = (*head);
//(*head)->prev = p;
(*head) = p;
}
if(p->value < cur->value)
{
cur->prev->next = p;
p->prev = cur->prev;
cur->prev = p;
p->next = cur;
}
insert(head, cur, p);
//p->next = *head;
//*head = p;
}
There are a few mistakes in your recursive insert function. It will be clear in the comments of my code:
void insert(node **head, node *cur, node *p)
{
if(*head == NULL) // the list will contain a single element
{
p->next = p->prev = NULL;
*head = p;
return; // we're done for this case!
}
if(p->value < cur->value)
{
p->prev = cur->prev;
p->next = cur;
cur->prev = p;
if(cur->prev != NULL) // what if cur is the head? there is no cur->prev!
cur->prev->next = p;
else
*head = p; // p becomes the new head
return; // we're done!
}
if(cur->next == NULL) // if cur is the last in the list, we just insert p after it
{
cur->next = p;
p->next = NULL;
p->prev = cur;
}
else // now we can proceed recursively and check the next element
insert(head, cur->next, p);
}
I think that it is the function insert itself that has to allocate new node.
It should have two parameters: pointer to head and a value that to be added.
Here is a demonstrative program that shows how the function can be writtem
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct node
{
int value;
struct node *next;
struct node *prev;
} node;
void insert( node **current, int value )
{
if ( *current == NULL || value < ( *current )->value )
{
node *tmp = malloc( sizeof( node ) );
tmp->value = value;
tmp->next = *current;
if ( *current != NULL )
{
tmp->prev = ( *current )->prev;
( *current )->prev = tmp;
}
else
{
tmp->prev = NULL;
}
*current = tmp;
}
else if ( ( *current )->next == NULL )
{
node *tmp = malloc( sizeof( node ) );
tmp->value = value;
tmp->next = ( *current )->next;
tmp->prev = *current;
( *current )->next = tmp;
}
else
{
insert( &( *current )->next, value );
}
}
void print_list( node *current )
{
if ( current == NULL )
{
printf( "\n" ) ;
}
else
{
printf( "%d ", current->value );
print_list( current->next );
}
}
#define N 10
int main( void )
{
node *head = NULL;
srand( ( unsigned int )time( NULL ) );
for ( int i = 0; i < N; i++ )
{
int value = rand() % N;
printf( "%d ", value );
insert( &head, value );
}
printf( "\n" );
print_list( head );
return 0;
}
The program output might look like
4 9 0 0 6 7 2 7 3 3
0 0 2 3 3 4 6 7 7 9
Of course you need to write also a recursive function that will free all allocated mempry for nodes.

Resources