Hi i am writing a program that manage a list of student, i am using a list, each element is described like this:
struct student
{
char lastname[50];
char name[50];
char date_of_birth[50];
char height[50];
struct student *next;
};
struct student *root=0; //this is the root node
This is how i add element to the list:
void add_element(struct student **root, char lastname[50], char name[50], char date_of_birth[50], char height[50])
{
if(*root == 0)
{
*root = malloc(sizeof(struct student));
strcpy((*root)->lastname,lastname);
strcpy( (*root)->name,name);
strcpy( (*root)->date_of_birth,date_of_birth);
strcpy( (*root)->height,height);
(*root)->next = 0;
}
else
{
add_element(&(*root)->next,lastname,name,date_of_birth,height);
}
}
I also wrote 2 function, one is for reading from a file, the other is to write the file, the file contains all the students, everything works but i need a function to sort all the element in alphabetical order by lastname, i tried to write one, but it doesn't work, it keeps crashing.
I tried a lot of things and they didn't work, this is one attempt, and it doesn't work :-(
please help me
void sort(struct student *head)
{
struct student **current;
struct student *tmp;
for(current = &head ; *current !=NULL ; current = (*current)->next)
{
if((*current)->next == NULL)
{
break;
}
switch(strcmp((*current)->lastname,(*current)->next->lastname))
{
case 0:
{
printf("user not valid");
break;
}
case 1:
{
tmp = *current;
*current = (*current)->next;
(*current)->next = tmp;
break;
}
}
}
}
After including remarks from comments to correct the proposed source code, the algorithm to sort the linked-list is missing some steps. At least, to sort a linked-list, it is necessary to have two loops. The choice used of a struct student **current
access will be complex for a two nested loops.
Here is another powerful sorting function using the optimized qsort()
function.
Step 1 - before showing the function, to sort a list, the root
pointer shall be modified.
First method, used for the
add_element()
by sending the address of the pointer.
void sort(struct student **root)
{
...
}
Second method, to return the modified
root
.
struct student *sort(struct student *root)
{
...
return (root);
}
Step 2 - the function sort()
using qsort()
quicksort function.
The method allocates a temporary array of pointers in order to have a fixed-size element to be sorted.
struct student *
, fill the array by using a loop to each item of the linked-list;qsort()
function by using the customized comparison function node_compare()
(see next step);struct student *next
(the first is *root
and the last is pointing to NULL).struct student *
;That's all.
//
void sort(struct student **root)
{
struct student *tmp;
struct student **array;
int i,icount;
// number of nodes to be sorted
for(tmp = *root,icount = 0;tmp!=NULL;tmp = tmp->next,icount++);
if (icount<2) {
// no sort needed
return;
}
// allocate an array of pointers
array = (struct student **)malloc(icount*sizeof(struct student *));
// push linked-list into array of pointers
for(tmp = *root,icount = 0;tmp!=NULL;tmp = tmp->next,icount++) {
array[icount]=tmp;
}
// quicksort using node_compare() customized function
qsort(array, icount, sizeof(struct student *), node_compare);
// pop linked-list from array of pointers
*root = array[0];
(*root)->next = NULL;
for(tmp = *root,i = 1;i<icount;i++) {
tmp->next = array[i];
array[i]->next = NULL;
tmp = tmp->next;
}
// free the allocated array of pointer
free(array);
}
//
Step 3 - the comparison function node_compare()
needed to qsort()
.
The function shall return a signed comparison as
strcmp()
does.
int node_compare(const void * a, const void * b)
{
// restore node pointers
struct student *node_a = *((struct student **)a);
struct student *node_b = *((struct student **)b);
if (node_b==NULL) return (-1); // force 'node_a'
if (node_a==NULL) return (+1); // force 'node_b'
// use the strcmp() function
return (strcmp(node_a->lastname,node_b->lastname));
}
Enhancement - because the add_element()
is using a recursive call not compliant with a long linked-list, here is a quite simple non-recursive algorithm.
If the recursive algorithm limits the size to few-centuries of elements, the proposed one has been tested with 100,000 elements (40Mb linked-list), generated randomly and sorted.
void add_element(struct student **root, char lastname[50], char name[50], char date_of_birth[50], char height[50])
{
struct student **current;
for(current = root; *current !=NULL ; current = &((*current)->next));
*current = (struct student *)malloc(sizeof(struct student));
strcpy((*current)->lastname,lastname);
strcpy( (*current)->name,name);
strcpy( (*current)->date_of_birth,date_of_birth);
strcpy( (*current)->height,height);
(*current)->next = NULL;
}