C program to partitition a simply linked list - c

so i've been working on a small function(part of a bigger program) that basically does the following:
define a list and the number of elements N, then input N elements. after this, input a value X;
I have to 'split' / re-order the list in a way so that its elements with value < X are in the beginning, in their relative order and the ones with higher value than X come after; eg.:
Input:
list 6
2 5 6 4 3 1
X 3
Output:
2 3 1 5 6 4
my code and list structure are down below:
(the partition function is at the bottom, just above the main function)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_STRING_SIZE 64
typedef struct ll_node_t
{
void* data;
struct ll_node_t* next;
} ll_node_t;
typedef struct linked_list_t
{
ll_node_t* head;
unsigned int data_size;
unsigned int size;
} linked_list_t;
linked_list_t*
ll_create(unsigned int data_size)
{
linked_list_t* list = malloc(sizeof(list));
// err handle
list->head = NULL;
list->data_size = data_size;
list->size = 0;
return list;
}
void
ll_add_nth_node(linked_list_t* list, unsigned int n, const void* new_data)
{
if(n < 0) exit(0);
ll_node_t* new_node = malloc(sizeof(ll_node_t*));
new_node->data = malloc(list->data_size);
// err handle
memcpy(new_node->data, new_data, list->data_size);
if(n == 0 || list->size == 0) {
new_node->next = list->head;
list->head = new_node;
list->size++;
return;
}
if(n < list->size)
{
ll_node_t* current = list->head;
for(int i = 0; i < n - 1; i++)
{
current = current->next;
}
new_node->next = current->next;
current->next = new_node;
list->size++;
return;
}
if(n >= list->size)
{
ll_node_t* current = list->head;
for(unsigned int i = 0; i < list->size - 1; i++)
{
current = current->next;
}
new_node->next = current->next;
current->next = new_node;
list->size++;
return;
}
}
ll_node_t*
ll_remove_nth_node(linked_list_t* list, unsigned int n)
{
if(n < 0) exit(0);
ll_node_t* removedNode = NULL;
if(n == 0)
{
removedNode = list->head;
list->head = list->head->next;
list->size--;
return removedNode;
}
if(n < list->size)
{
ll_node_t* current = list->head;
// err handle
for(int i = 0; i < n - 1; i++)
{
current = current->next;
}
removedNode = current->next;
current->next = current->next->next;
list->size--;
return removedNode;
}
if(n >= list->size)
{
ll_node_t* current = list->head;
// err handle
for(int i = 0; i < n - 1; i++)
{
current = current->next;
}
removedNode = current->next;
current->next = NULL;
list->size--;
return removedNode;
}
}
unsigned int
ll_get_size(linked_list_t* list)
{
return list->size;
}
void
ll_free(linked_list_t** pp_list)
{
ll_node_t* current = (*pp_list)->head;
for(int i = 0; i < (*pp_list)->size; i++)
{
(*pp_list)->head = current->next;
free(current->data);
free(current);
current = (*pp_list)->head;
}
free(*pp_list);
}
void
ll_print_int(linked_list_t* list)
{
if(!list->size) exit(0);
ll_node_t* current = list->head;
for(int i = 0; i < list->size; i++)
{
printf("%d ", *(int*)current->data);
current = current->next;
}
printf("\n");
}
void
ll_print_string(linked_list_t* list)
{
if(!list->size) exit(0);
ll_node_t* current = list->head;
for(int i = 0; i < list->size; i++)
{
printf("%s ", (char*)current->data);
current = current->next;
}
printf("\n");
}
void partition(linked_list_t* list, int x)
{
ll_node_t* current = list->head;
ll_node_t* tail = list->head;
for(int i = 0; i < list->size; i++)
{
tail = tail->next;
}
//special case for the first element of the list
if(*(int*)current->data > x)
{
tail->next = current;
list->head = current->next;
tail = current;
}
// loop that finds elements > X
for(int i = 0; i < list->size - 1; i++)
{
if(*(int*)current->data > x)
{
// assigning the element to the end
tail->next = current->next;
// linking the previous element to the one after the element
current->next = current->next->next;
tail = tail->next;
tail->next = NULL;
// moving on to next element
current = current->next;
}
else current = current->next;
// moving on to next element
}
}
int main()
{
linked_list_t* linkedList;
while (1) {
char command[16];
long size, num;
scanf("%s", command);
if (strcmp(command, "list") == 0) {
linkedList = ll_create(sizeof(int));
scanf("%ld", &size);
long int curr_nr;
for (int i = 0; i < size; ++i) {
scanf("%ld", &curr_nr);
ll_add_nth_node(linkedList, size, &curr_nr);
}
}
if (strcmp(command, "X") == 0) {
scanf("%ld", &num);
partition(linkedList, num);
ll_print_int(linkedList);
break;
}
}
ll_free(&linkedList);
return 0;
}
so since i have list size as well, which is the number of elements in the list i thought the following:
before looping through the list, check if the head(first element) needs to be shifted at the end (if > X) and then have a loop that loops list->size - 1 times and when the condition inside is met, do the following:
it'd basically loop through elements and look at their next's, so when an element's next is > X, it would be shifted:
assign the tail's next element to be the element > X(current->next), then link current elements next to the one after the element. after that the new tail would be the element that was added at the end.
currently I get a Segmentation fault at the first line inside the condition in the for loop, on this line:
tail->next = current->next;
disclaimer: the main program, as i've tested it, works just fine for adding elements, and so on.

I going to offer an answer that is not exactly a solution to your existing code, but instead presents a different way of thinking about organizing your data as you work through it.
What if, instead of trying to reorder the list in place (managing head, current, and tail) while iterating through it, we deconstruct the list and construct two new lists? Our result becomes the concatenation of these two lists.
Visualized in pseudocode this would work like:
Q is [2 5 6 4 3 1]
part Q <= 3
L is []
R is []
Q eql [2 5 6 4 3 1]
^ -> L eql [2]
Q eql [5 6 4 3 1]
^ -> R eql [5]
Q eql [6 4 3 1]
^ -> R eql [5 6]
Q eql [4 3 1]
^ -> R eql [5 6 4]
Q eql [3 1]
^ -> L eql [2 3]
Q eql [1]
^ -> L eql [2 3 1]
Q eql []
Q is L concat R
Q eql [2 3 1 5 6 4]
By doing this, our partitioning function gets utilize the same logic we used to build our list in the first place.
Here is an example of what this might look like in C, using a very simple linked list:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
struct node *next;
int value;
} node;
typedef struct {
node *head;
} list;
void list_append_node(list *l, node *n) {
node *root = l->head;
if (root) {
while (root->next)
root = root->next;
root->next = n;
} else
l->head = n;
}
void list_append_value(list *l, int v) {
node *n = calloc(1, sizeof *n);
n->value = v;
list_append_node(l, n);
}
void list_part(list *l, int v) {
list lower = { 0 };
list upper = { 0 };
for (node *curr = l->head, *temp; curr; curr = temp) {
temp = curr->next;
curr->next = NULL;
list_append_node(curr->value <= v ? &lower : &upper, curr);
}
list_append_node(&lower, upper.head);
l->head = lower.head;
}
int main(void) {
int inputs[] = { 2, 5, 6, 4, 3, 1 };
size_t len = sizeof inputs / sizeof *inputs;
list l = { 0 };
for (size_t i = 0; i < len; i++)
list_append_value(&l, inputs[i]);
list_part(&l, 3);
for (node *n = l.head, *t; n; n = t) {
t = n->next;
printf("%d ", n->value);
free(n);
}
putchar('\n');
}
stdout:
2 3 1 5 6 4
Note, the use of a node *tail member for each list could be implemented to improve the performance of list_append_node from O(N) to O(1).

Related

How to count Duplicates of an array in singly linked list?

each person have a Rank[4]
struct node
{
int value;
int Rank[4];
struct node *next;
};
i want to know how many people choose the same Rank ?
for example :
person 1 : Rank[4] = {1, 2, 3, 4}; &
person 2 : Rank[4] = {1, 2, 3, 4};
that should count as duplicate
The following code does the job, in this case, I used a 'this_rank' to count how many matches this in the list, but you can use any rank that already exists in the list.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int value;
int Rank[4];
struct node *next;
};
int rank_test(int *rank_1, int *rank_2, int rank_counts)
{
int r = 1;
for(int n = 0; n < rank_counts; n++)
{
if(rank_1[n] != rank_2[n])
{
return 0;
}
}
return r;
}
int rank_count(struct node *my_node, int *rank, int rank_length)
{
int rank_counter = 0;
while(my_node != NULL)
{
rank_counter += rank_test(my_node->Rank, rank, rank_length);
my_node = my_node->next;
}
return rank_counter;
}
int main(void)
{
struct node *n1;
struct node *n2;
struct node *n3;
int r;
int this_rank[] = {1, 2, 3, 4};
n1 = (struct node *) malloc(sizeof(struct node));
n2 = (struct node *) malloc(sizeof(struct node));
n3 = (struct node *) malloc(sizeof(struct node));
n1->next = n2;
n2->next = n3;
n3->next = NULL;
n1->Rank[0] = 1;
n1->Rank[1] = 2;
n1->Rank[2] = 3;
n1->Rank[3] = 4;
n2->Rank[0] = 1;
n2->Rank[1] = 2;
n2->Rank[2] = 3;
n2->Rank[3] = 4;
n3->Rank[0] = 1;
n3->Rank[1] = 2;
n3->Rank[2] = 3;
n3->Rank[3] = 5;
r = rank_count(n1, this_rank, 4);
printf(" r = %d", r);
return 0;
}
Here is a bit lengthy proof of principle program that sets up some test data with duplicates that you might use for determining people that are duplicates.
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int val;
int Rank[4];
struct node *next;
} node_t;
node_t * push(node_t *nd, int val)
{
node_t *new_node; // New pointer to a node
new_node = (node_t *)malloc(sizeof(node_t));
new_node->val = val;
new_node->Rank[0] = val *5 + 1;
new_node->Rank[1] = val *5 + 4;
new_node->Rank[2] = val *5 + 8;
new_node->Rank[3] = val *5 + 9;
new_node->next = NULL;
/* Create some duplicates */
if ((val % 17) == 0)
{
new_node->Rank[0] = 4;
new_node->Rank[1] = 5;
new_node->Rank[2] = 6;
new_node->Rank[3] = 7;
}
return new_node;
}
void find_dupe(node_t *person, node_t *list)
{
node_t *comp;
comp = list;
while (comp->next != NULL)
{
if (person->Rank[0] == comp->Rank[0] && person->Rank[1] == comp->Rank[1] && person->Rank[2] == comp->Rank[2] &&person->Rank[3] == comp->Rank[3] && person != comp)
{
printf("Person %d matches with Person %d\n", person->val, comp->val);
}
comp = comp->next;
}
return;
}
int main()
{
node_t *work; // Pointer work variable for building a linked list of nodes
node_t *head;
head = (node_t *)malloc(sizeof(node_t));
head->val = 2;
head->Rank[0] = 1;
head->Rank[1] = 2;
head->Rank[2] = 3;
head->Rank[3] = 4;
head->next = NULL;
// Create a set of fifty nodes.
work = head;
for (int i = 0; i < 50; i++)
{
work->next = push(work, (2 * i + i + 12));
work = work->next;
}
// Now travel down the chain and print out the pertinent statistics of the nodes.
work = head;
while (work->next != NULL)
{
find_dupe(work, head);
work = work->next;
}
return 0;
}
This was the output from the test run.
#Una:~/C_Programs/Console/Ranked/bin/Release$ ./Ranked
Person 51 matches with Person 102
Person 51 matches with Person 153
Person 102 matches with Person 51
Person 102 matches with Person 153
Person 153 matches with Person 51
Person 153 matches with Person 102
Give that a try if you want.

Merging two sorted linked list algorithm not working when using for loop

So in my following code, I have two lists. Each of them should be sorted in increasing order and then merged together into one list with SortedMerge().
The code works just fine when in the main I insert the numbers separately:
int main()
{
struct Node *final = NULL;
struct Node *a = NULL;
struct Node *b = NULL;
insert(&a, 15);
insert(&a, 10);
insert(&a, 5);
insert(&b, 20);
insert(&b, 3);
insert(&b, 2);
final = SortedMerge(a, b);
printList(final);
return 0;
}
But in my case I don't want to insert numbers separately but rather have two arrays and insert them to the list using for loop. The code again merges them together, but does not sort them in increasing order:
int main()
{
int list1[] = { 15, 10, 5 };
int list2[] = { 20, 3, 2 };
struct Node *final = NULL;
struct Node *a = NULL;
struct Node *b = NULL;
int n1 = sizeof(list1) / sizeof(list1[0]);
int n2 = sizeof(list2) / sizeof(list2[0]);
for (int i = n1 - 1; i >= 0; i--) insert(&a, list1[i]);
for (int i = n2 - 1; i >= 0; i--) insert(&b, list2[i]);
final = SortedMerge(a, b);
printList(final);
return 0;
}
The following code has both insert separately and with for loop.
If for clarity anybody will need the overall code:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
struct Node
{
int data;
struct Node *next;
};
void MoveNode(struct Node **destRef, struct Node **source);
struct Node *SortedMerge(struct Node *a, struct Node *b)
{
struct Node *result = NULL;
struct Node **lastPointer = &result;
while (1) {
if (a == NULL) {
*lastPointer = b;
break;
}
else if (b == NULL) {
*lastPointer = a;
break;
}
if (a->data <= b->data)
MoveNode(lastPointer, &a);
else
MoveNode(lastPointer, &b);
lastPointer = &((*lastPointer)->next);
}
return (result);
}
void MoveNode(struct Node **destRef, struct Node **source)
{
struct Node *newNode = *source;
assert(newNode != NULL);
*source = newNode->next;
newNode->next = *destRef;
*destRef = newNode;
}
void insert(struct Node **head, int data)
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
if (newNode == NULL)
printf(" Memory can not be allocated.");
else {
newNode->data = data;
newNode->next = *head;
*head = newNode;
}
}
void printList(struct Node *node)
{
while (node)
{
printf("%d ", node->data);
node = node->next;
}
}
int main()
{
int list1[] = { 15, 10, 5 };
int list2[] = { 20, 3, 2 };
struct Node *final = NULL;
struct Node *a = NULL;
struct Node *b = NULL;
int n1 = sizeof(list1) / sizeof(list1[0]);
int n2 = sizeof(list2) / sizeof(list2[0]);
for (int i = n1 - 1; i >= 0; i--) insert(&a, list1[i]);
for (int i = n2 - 1; i >= 0; i--) insert(&b, list2[i]);
insert(&a, 15);
insert(&a, 10);
insert(&a, 5);
insert(&b, 20);
insert(&b, 3);
insert(&b, 2);
final = SortedMerge(a, b);
printList(final);
return 0;
}
Your SortedMerge function expects two lists sorted in ascending order and merges them into a single list in ascending order.
For the first example:
insert(&a, 15);
insert(&a, 10);
insert(&a, 5);
insert(&b, 20);
insert(&b, 3);
insert(&b, 2);
(Note: insert inserts at the front of the list.)
List a: 5, 10, 15.
List b: 2, 3, 20
Lists a and b are in ascending order so are valid for SortedMerge.
For the second example:
int list1[] = { 15, 10, 5 };
int list2[] = { 20, 3, 2 };
int n1 = sizeof(list1) / sizeof(list1[0]);
int n2 = sizeof(list2) / sizeof(list2[0]);
for (int i = n1 - 1; i >= 0; i--) insert(&a, list1[i]);
for (int i = n2 - 1; i >= 0; i--) insert(&b, list2[i]);
(Note: insert inserts at the front of the list.)
List a: 15, 10, 5
List b: 20, 3, 2
Lists a and b are in descending order so are not valid for SortedMerge.
For the third (combined example):
List a: 5, 10, 15, 15, 10, 5
List b: 2, 3, 20, 20, 3, 2
Lists a and b are not sorted so are not valid for SortedMerge.
The problem is SortedMerge assumes the lists are sorted in ascending order and you break this assumption: you prepend the elements from the last to the first in the arrays (the function is called insert, a confusing choice), but the contents of the arrays in already in decreasing order so you effectively get the list sorted in decreasing order. Then you prepend more elements, so these lists are unsorted.
change the insertion loop to for (int i = 0; i < n1; i++) insert(&a, list1[i]); and do not insert more elements or
change the array contents so the arrays are in increasing order and do not insert more elements or
change the insert function to insert the new node in the proper place.
Here is a modified version using the latter:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node *next;
};
void MoveNode(struct Node **destRef, struct Node **source)
{
struct Node *newNode = *source;
assert(newNode != NULL);
*source = newNode->next;
newNode->next = *destRef;
*destRef = newNode;
}
struct Node *SortedMerge(struct Node *a, struct Node *b)
{
struct Node *result = NULL;
struct Node **lastPointer = &result;
for (;;) {
if (a == NULL) {
*lastPointer = b;
break;
}
if (b == NULL) {
*lastPointer = a;
break;
}
if (a->data <= b->data)
MoveNode(lastPointer, &a);
else
MoveNode(lastPointer, &b);
lastPointer = &(*lastPointer)->next;
}
return result;
}
void insert(struct Node **head, int data)
{
struct Node *newNode = malloc(sizeof(*newNode));
if (newNode == NULL) {
fprintf(stderr, "Memory cannot be allocated.\n");
return;
}
while (*head != NULL && (*head)->data < data) {
head = &(*head)->next;
}
newNode->data = data;
newNode->next = *head;
*head = newNode;
}
void printList(const struct Node *node)
{
while (node) {
printf("%d ", node->data);
node = node->next;
}
printf("\n");
}
int main()
{
int list1[] = { 5, 10, 15 };
int list2[] = { 2, 3, 20 };
struct Node *a = NULL;
struct Node *b = NULL;
int n1 = sizeof(list1) / sizeof(list1[0]);
int n2 = sizeof(list2) / sizeof(list2[0]);
for (int i = 0; i < n1; i++)
insert(&a, list1[i]);
for (int i = 0; i < n2; i++)
insert(&b, list2[i]);
insert(&a, 15);
insert(&a, 10);
insert(&a, 5);
insert(&b, 20);
insert(&b, 3);
insert(&b, 2);
struct Node *final = SortedMerge(a, b);
printList(final);
return 0;
}

Connected Components in an undirected graph - Algorithm fhor StackOverflow users (Segmentation fault)

In response to my first question on the subject, I found (pg 89)/ built an algorithm that prints the connected components. However, for an input of the type
6 edges
4 vertices
2 3
2 3
4 5
0 1
the program returns a segmentation error. Why?
#include<stdlib.h>
#define MAXVERTICES 100
void enqueue(int);
int deque();
int isConnected(char **graph,int noOfVertices);
void BFS(char **graph,int vertex,int noOfVertices);
int count = 0;
struct node{
int v;
struct node *next;
};
typedef struct node Node;
typedef struct node *Nodeptr;
Nodeptr Qfront = NULL;
Nodeptr Qrear = NULL;
char *visited;//array that keeps track of visited vertices.
void enqueue(int vertex){
if(Qfront == NULL){
Qfront = malloc(sizeof(Node));
Qfront->v = vertex;
Qfront->next = NULL;
Qrear = Qfront;
}
else{
Nodeptr newNode = malloc(sizeof(Node));
newNode->v = vertex;
newNode->next = NULL;
Qrear->next = newNode;
Qrear = newNode;
}
}
int deque(){
if(Qfront == NULL){
printf("Q is empty , returning -1\n");
return -1;
}
else{
int v = Qfront->v;
Nodeptr temp= Qfront;
if(Qfront == Qrear){
Qfront = Qfront->next;
Qrear = NULL;
}
else
Qfront = Qfront->next;
free(temp);
return v;
}
}
int isConnected(char **graph,int noOfVertices){
int i;
BFS(graph,0,noOfVertices);
for(i = 0;i < noOfVertices;++i)
if(visited[i] == 'N')
return 0;
return 1;
}
void BFS(char **graph,int v,int noOfVertices){
int i,vertex;
visited[v] = 'Y';
enqueue(v);
while((vertex = deque()) != -1){
//printf("\nConnected component %d\n",++count);
//printf("%d ",vertex+1);
for(i = 0;i < noOfVertices;++i)
if(graph[vertex][i] == 1 && visited[i] == 'N'){
enqueue(i);
visited[i] = 'Y';
}
}
}
void listConnectedComponents(char **graph,int noOfVertices){
int i;
for(i = 0;i < noOfVertices;++i){
if(visited[i] == 'N')
BFS(graph,i,noOfVertices);
}
}
int main(){
int n,e;//n is number of vertices, e is number of edges.
int i,j;
char **graph;//adjacency matrix
printf("Enter number of vertices:");
scanf("%d",&n);
if(n < 0 || n > MAXVERTICES){
fprintf(stderr, "Please enter a valid positive integer from 1 to %d",MAXVERTICES);
return -1;
}
graph = malloc(n * sizeof(char *));
visited = malloc(n*sizeof(char));
for(i = 0;i < n;++i){
graph[i] = malloc(n*sizeof(int));
visited[i] = 'N';//initially all vertices are not visited.
for(j = 0;j < n;++j)
graph[i][j] = 0;
}
printf("enter number of edges and then enter them in pairs:");
scanf("%d",&e);
for(i = 0;i < e;++i){
int u,v;
scanf("%d%d",&u,&v);
graph[u-1][v-1] = 1;
graph[v-1][u-1] = 1;
}
if(isConnected(graph,n))
printf("The graph is connected");
else printf("The graph is NOT connected\n");
}
I believe it is due to the positions allocated in the adjacency matrix.

Swap kth position from start and end in a single traverse linked list

I have come across the following implementation for swapping the kth position from start and end in a linked list in single traverse.
node *list;
node *p, *q, *r;
p = q = r = list;
i = 1;
while(p != NULL)
{
if(i != k)
{
q = q->next;
i++;
}//q will eventually point to kth node from starting
if(i == k)
{
r = r->next
}//r will eventually point to kth node from end
p = p->next;
}
Swap q & r elements
But I feel it's not the right implementation, could anyone look at it and verify if it's correct?
If it's wrong, what changes would I have to make?
This question is majorly associated with finding right nodes and respective previous node.
Then essentially there are 2 cases when nodes are starting and ending node or they are intermediate nodes.
First adjust previous pointer to point swap targets and then swap next pointers of targets. That is all ... following is complete java code for reference ->
JAVA Code
public class SwapKthNodeTest {
public static void main(String[] args) {
Test10Node();
System.out.println();
Test2Node();
}
private static void Test2Node() {
Node head = Node.getNodeListHead(2);
Node.ToString(head);
int k = 1;
head = Node.SwapKthNodeFromStartNEnd(head, k);
Node.ToString(head);
k = 2;
head = Node.SwapKthNodeFromStartNEnd(head, k);
Node.ToString(head);
}
public static void Test10Node(){
Node head = Node.getNodeListHead(10);
Node.ToString(head);
int k = 2;
head = Node.SwapKthNodeFromStartNEnd(head, k);
Node.ToString(head);
k=1;
head = Node.SwapKthNodeFromStartNEnd(head, k);
Node.ToString(head);
k=3;
head = Node.SwapKthNodeFromStartNEnd(head, k);
Node.ToString(head);
k=4;
head = Node.SwapKthNodeFromStartNEnd(head, k);
Node.ToString(head);
k=5;
head = Node.SwapKthNodeFromStartNEnd(head, k);
Node.ToString(head);
}
}
class Node {
int val;
Node next;
Node(int val, Node next) {
this.val = val;
this.next= next;
}
public static int length(Node head){
Node trav = head;
int count = 0;
while(trav != null){
count++;
trav = trav.next;
}
return count;
}
public static void ToString(Node head) {
// just print the list which we created
Node trav = head;
while(trav != null){
System.out.print(trav.val+" ");
trav = trav.next;
}
}
public static Node SwapKthNodeFromStartNEnd(Node head, int k) {
System.out.println();
int len = Node.length(head);
if( k > len) return head;
// would be the same thing just making it reverse
// to make process more cleaner
if( k == len) k = 1;
Node x = head, y = head, t = head;
Node xp = null, yp = null;
int i = 1;
while (i++ < k) {
xp = x;
x = x.next;
t = t.next;
}
while(t.next != null){
yp = y;
y = y.next;
t = t.next;
}
// System.out.println("x= "+x.val+" y= "+ y.val);
// if(xp != null) System.out.println("xp= "+xp.val);
// if(yp != null) System.out.println("yp= "+yp.val);
// first adjust previous pointer of two nodes
// later swap the next pointers of both nodes
// CASE-1: case nodes have previous pointer
// and they are not start and end node
if(xp != null && yp != null ){
xp.next = y;
yp.next = x;
}
// CASE-2: x and y nodes are first and last
// this case xp is null
else if (xp == null && yp != null){
head = y;
yp.next = x;
}
t = y.next;
y.next = x.next;
x.next = t;
return head;
}
public static Node getNodeListHead(int nodes){
int idx = nodes-1;
Node head = new Node(nodes, null);
while(idx >= 1){
head = new Node(idx, head);
idx--;
}
return head;
}
}
Refer to geeks4geeks for all boundary cases:
http://www.geeksforgeeks.org/swap-kth-node-from-beginning-with-kth-node-from-end-in-a-linked-list/
For singly linked list of size N, find the Kth element and then N-K+1 th element and exchange their values
And as Jonathan said, you have to take care of special cases and keep track of additional pointers to do the swap. But the crux is you have to swap the Kth element with the N-K+1th element

Applying bubble sort on linked list gives wrong output in c

I am trying to sort a linked list using bubble sort.But it gives segmentation problem
My logic to do so is below:
Note: Please note that i have to use only pass by reference every where (no return and global declaration for nodes)
void bubble_sort(node * * List, int size)
{
int i, j, temp;
node * first;
node * second;
node * final;
final=*List
for (i = 0; i < size - 1; i++)
{
first =final;
second = first -> link;
for (j = 0; j < size; j++)
{
if (first -> data < second -> data)
{
temp = first -> data;
first -> data = second -> data;
second -> data = temp;
}
first = first -> link;
}
} * List = first;
}
It's function call is :
bubble_sort(&start,val);
Could any one please help me in correcting the logic ?
EDIT: My full code:
#include <stdio.h>
//#include <conio.h>
#include <malloc.h>
/* structure containing a data part and link part */
struct node
{
int data;
struct node * link;
};
typedef struct node node;
node * start, * visit, * newnode;
//start=NULL
///////////////////////////////// Function declaration ///////////////////
void append(node * * q, int num);
void displaylist(node * start);
void bubble_sort(node * * List, int val);
//////////////////////////////////////////////////////////////////////////////////////////
void append(node * * q, int num)
{
node * temp, * temp2;
temp = * q;
//temp= (node* )malloc(sizeof (node));
if (temp == NULL) /* if the list is empty, create first node */
{
temp = (node * ) malloc(sizeof(struct node)); * q = temp;
} else
{
temp2 = * q;
while (temp2 -> link != NULL)
{
temp2 = temp2 -> link;
}
temp = (node * ) malloc(sizeof(struct node));
temp2 -> link = temp;
}
temp -> data = num;
temp -> link = NULL;
}
///////////////////////////////////////////////////////////////////////
void displaylist(node * start)
{
visit = start;
/* traverse the entire linked list */
while (visit != NULL)
{
printf("%d ", visit -> data);
visit = visit -> link;
}
}
/////////////////////////////////////////////////////////////////////////////////
/*
void bubble_sort(node **List,int size)
{
int i,j,temp;
node*first;
node*second;
node*final;
final=*List;
for(i=0;i<size-1;i++)
{
first=final;
second=first->link;
for(j=1;j<size;j++)
{
if( first->data<second->data)
{
temp=first->data;
first->data=second->data;
second->data=temp;
}
first=first->link;
}
}
*List=first;
} */
//////////////////////////////////////////////////////////////////////////////////////
void bubble_sort(node * * List, int size)
{
int i, j, temp;
node * first;
node * second;
node * final;
for (i = 0; i < size; i++)
{
first = * List;
for (j = 0; j < size - 1; j++)
{
if (first -> data < first -> link -> data)
{
temp = first -> data;
first -> data = first -> link -> data;
first -> link -> data = temp;
}
first = first -> link;
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////
main()
{
start = NULL;
int val, n, size;
char ch;
struct node * new;
new = NULL;
printf("\nEnter the size desired size of Linked list: \n");
scanf("%d", & size);
for (ch = 0; ch < size; ch++)
{
printf("\nEnter a value: ");
scanf("%d", & val);
append( & new, val);
}
start = new;
displaylist(start);
printf("\nApplying Bubble sort on Linked list: \n");
bubble_sort( & start, val);
displaylist(start);
printf("\n");
}
Assumed Val is number of nodes in list, you are actually not sorting a linked list but instead swapping the values from one node to another in order to sort it.
bubble_sort( &start, size); change this as well should fix it(pass size not val)
try this.
void bubble_sort(node **List, int val)
{
int i,j,temp;
node *first;
node *second;
node *final;
for(i = 0; i < val; i++)
{
first = *list
for(j = 0; j < val-1; j++)
{
if(first->data < first->link->data)
{
temp = first->data;
first->data = first->link->data;
first->link->data = temp;
}
first = first->link;
}
}
}
I believe you are getting a segmentation fault because you're trying to access a Null pointer as a node, in the inner for-loop.
for (j = 0; j < val; j++)
this should be:
for (j = 0; j < val - 1; j++)
Because in your solution, when j = val-1, it will still try and access first->link->data, however, first->link is Null.

Resources