How to sort linked list - c

I am trying to sort a linear linked list by last name, however it is crashing, also i don't know if my algorithm is working correctly.
Can someone help me to stop it from crashing, and see if my algorithm for sorting the list is working?
void sort(NODEPTR *employees, int maxEmployees)
{
int i = 0, j = 0, k = 0;
NODEPTR p, q, pTrail = NULL, qTrail, temp;
temp = (NODEPTR) calloc(1, sizeof(node));
qTrail = *employees;
q = (*employees)->next;
for (i = 0; i < maxEmployees; i++)
{
p = *employees;
while (p != q)
{
if (strcmp(p->lastName, q->lastName))
{
temp = q;
qTrail = q->next;
q = pTrail->next;
temp = pTrail->next;
pTrail = temp;
p = q;
}
else
{
pTrail = p;
p = p->next;
}
}
qTrail = q;
q = q->next;
pTrail = NULL;
}
printf("%10s %10ss\n", "First", "Last");
printf("%10s %10s\n", "-----", "----");
for (i = 0; i < maxEmployees; i++)
{
printf("%10s %10ss\n", (*employees)->firstName, (*employees)->lastName);
}
}
Linked List:
typedef struct node
{
char firstName[11];
char lastName[16];
char gender;
int tenure;
char rate;
float salary;
struct node *next;
} node, *NODEPTR;

Your logic seems to be wrong:
strcmp() will return three values.
1 if first argument's value is >
-1 if second argument's value is >
0 if both arguments's value are same.
So based on strcmp(p->lastName,q->lastName) you can not sort.
You should change the position only when strcmp() return 1. for -1 and 0 it should go in else part.

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.

How do implement Count sort using linked list?

What I am trying to do is to create a counting sort using a linked list so I can link two similar elements in the same index and then copy from left to right to the original array. But my Buckets[i] are always NULL even after insertion. So my resulting array does not change. I don't know what I am doing wrong.
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node *next;
} **Buckets;
void printArray(int arr[], int size) {
for (int i = 0; i < size; i++)
printf("%d ", arr[i]);
printf("\n");
}
int findMax(int A[], int n) {
int i, max = A[0];
for (i = 0; i < n; i++) {
if (A[i] > max)
max = A[i];
}
return max;
}
void Insert(struct Node *p, int x) {
while (p != NULL) {
p = p->next;
}
Node *t = t = (struct Node *)malloc(sizeof(struct Node));
t->data = x;
t->next = NULL;
p = t;
}
int Delete(struct Node *Buckets) {
while (Buckets->next != NULL) {
Buckets = Buckets->next;
}
int temp = Buckets->data;
free(Buckets);
return temp;
}
void BucketSort(int A[], int size) {
int max, i, j;
max = findMax(A, size);
Buckets = new Node * [max + 1];
for (i = 0; i < max + 1; i++) {
Buckets[i] = NULL;
}
for (i = 0; i < size; i++) {
Insert(Buckets[A[i]], A[i]); //insertion
}
i = j = 0;
while (i < max + 1) {
while (Buckets[i] != NULL) {
A[j++] = Delete(Buckets[i]); // copy back in array
}
i++;
}
}
int main() {
int arr[] = { 3, 8, 5, 1, 10 };
int size = sizeof(arr) / sizeof(arr[0]); //5
printf("\nBefore : ");
printArray(arr, size);
BucketSort(arr, size);
printf("\nAfter : ");
printArray(arr, size);
return 0;
}
Your Insert function doesn't really modify the list – you just assign the new node to a local variable, which goes out of scope immediately.
You can solve this by passing a pointer to a node pointer to the function. That pointer points at the head pointer at first and at the next member of the preceding node when you advance:
void Insert(struct Node **p, int x)
{
while (*p) p = &(*p)->next;
*p = new Node(x); // assume a c'tor here
}
Call the function like so:
for (i = 0; i < size; i++) {
Insert(&Buckets[A[i]] ,A[i]);
}
The same goes for deletion: You must modify the links or the list head when you delete:
int Delete(struct Node **p)
{
int temp = (*p)->data;
struct Node *del = *p;
*p = (*p)->next;
delete del;
return temp;
}
(This code extracts the head node, which is probably what you want: You insert at the end, then retrieve from the beginning. That should preserve the original order. Not that it matters miuch in your case, where you have no data beside the int.)
Call Delete like so:
i = j = 0;
while (i < max + 1) {
while (Buckets[i]) {
A[j++] = Delete(&Buckets[i]);
}
i++;
}

How to get length of the longest prefix in Trie in C

I'm trying to figure out how to find the length of the longest prefix of two words in Trie. I was trying to find a solution, but I found nothing.
I already have an implementation of Trie, where the nodes are represent by structure:
struct node
{
int end; // 1 if node is end of word or 0 if not
int count; // The number of words that contain current node
struct node *letter[26]; // Array of nodes, which represent the alphabet
};
int length_of_longest_prefix(struct node *root)
{
//??????????
}
I tried to make a recursive function for this problem, but I could not do it.
Let´s think about this filled trie:
Filled trie
What is the best way to solve this problem?
Pseudocode will be very usefull.
My function:
//Global variable
int total_max;
//root = start
int length_of_longest_prefix(struct node *root, struct node *start)
{
int max = 0;
int depth = 0;
for (int i = 0; i < 26; i++)
{
if(root->letter[i] != NULL && root->letter[i]->count >= 2)
{
depth = length_of_longest_prefix(root->letter[i], start);
depth++;
if(root->letter[i] == start->letter[i])
{
depth = 0;
}
}
if(depth > total_max)
total_max = depth;
}
return depth;
}
int main(void)
{
total_max = 0;
struct node *root = (struct node*)malloc(sizeof(struct node));
for (int i = 0; i < 26; i++)
{
root->letter[i] = NULL;
}
root->end = 0;
root->count = 0;
/*Inserting strings to Trie*/
length_of_longest_prefix(root, root);
printf("%d\n", total_max);
return 0;
}

When I add an element to a linked list contained in an array of linked lists why every other element of the list gets deleted?

UPDATED
The problem of this code is that after the matrix has been transformed into an array of linked lists, it looks like no value is contained in the array of linked lists.
I think the problem is in the function that add a node to a specific list of the array of linked lists.
// node
struct node {
int n;
struct node* next_ptr;
};
// prototypes
void fill_mat(int mat[][SIZE]);
void mat_to_list(int mat[][SIZE]);
void insertSortedLinkedList(struct node *l, int value);
void print_mat(int mat[][SIZE]);
void print_vet();
// array of pointers
struct node* vet[SIZE];
int visitato[SIZE];
// main function
int main(int argc, const char *argv[]) {
int mat[SIZE][SIZE];
int i, j;
// reset the matrix
for(i = 0; i < SIZE; ++i) {
for(j = 0; j < SIZE; ++j) {
mat[i][j] = 0;
}
}
// generate graph with weights
srand(time(NULL));
fill_mat(mat);
// transform matrix in an array of linked lists
mat_to_list(mat);
print_mat(mat);
printf("\n");
print_vet();
return 0;
}
// generate graph
void fill_mat(int mat[][SIZE]) {
int x, y, z;
for(x = 0; x < (SIZE * SIZE) / 2;) {
y = rand() % SIZE;
z = rand() % SIZE;
if(mat[y][z] == 0) {
mat[y][z] = rand() % 10 + 1;
++x;
}
}
}
// insert in list
void addNode(struct node **st, int d) {
struct node *temp = *st;
if(temp == NULL) {
temp = malloc(sizeof(struct node));
} else {
while((temp)->next_ptr != NULL) {
temp = temp->next_ptr;
}
temp->next_ptr = malloc(sizeof(struct node));
temp = temp->next_ptr;
}
temp->n = d; // this must done using strncpy
temp->next_ptr = NULL;
}
// transform matrix to array of linked lists
void mat_to_list(int mat[][SIZE]) {
int i, j;
// reset array
for(i = 0; i < SIZE; ++i) {
vet[i] = NULL;
}
for(i = 0; i < SIZE; ++i) {
for(j = 0; j < SIZE; ++j) {
if(mat[i][j] != 0) {
addNode(&(vet[i]), mat[i][j]);
}
}
}
}
// print matrix
void print_mat(int mat[][SIZE]) {
int i, j
;
for(i = 0; i < SIZE; ++i) {
for(j = 0; j < SIZE; ++j) {
printf("%-2d ", mat[i][j]);
}
printf("\n");
}
}
// print array of linked lists
void print_vet() {
int i;
struct node* temp;
for(i = 0; i < SIZE; ++i) {
printf("ARRAY CELL: %d\n", i);
temp = vet[i];
while(temp != NULL) {
printf("NODE VALUE --> ");
printf("%d\n", temp->n);
temp = temp->next_ptr;
}
printf("\n");
}
}
I have not understood where there is an array of lists and how long you are going to show your editions of the function. But in any case a correct function can look the following way
void addNode( struct node **st, int d )
{
while ( *st ) st = &( *st )->next_ptr;
*st = malloc( sizeof( struct node ) );
( *st )->n = d;
( *st )->next_ptr = NULL;
}
Or the following way
int addNode( struct node **st, int d )
{
while ( *st ) st = &( *st )->next_ptr;
*st = malloc( sizeof( struct node ) );
int success = *st != NULL;
if ( success )
{
( *st )->n = d;
( *st )->next_ptr = NULL;
}
return success;
}
It looks like you are modifying the original pointer.
An iterator can be used to find the last node.
In your calling function, you can create an iterator.
first = (node *) malloc(sizeof(node));
iterator = first;
In your function, you can pass the iterator
void addNode(node *iterator, int d) {
/*Create a new node*/
newNode = (node *) malloc(sizeof(node));
newNode->n = d;
newNode->next_ptr = NULL;
/*Iterate through your list to find end*/
if (iterator != 0) {
while (iterator->next != 0) {
iterator = iterator->next;
}
}
/*Add item to last link in list*/
iterator->next = newNode;
}

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