L-33 MCS 360 Monday 7 April 2003
In this lecture we discussed merge and radix sort.
Below are simple implementations.
1. merge sort
/* L-33 MCS 360 Monday 7 April 2003
* simple implementation of merge sort */
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include"digits.h"
#include"priority_queue.h"
void random_vector ( int n, int m, int a[n] );
/* returns n random integers modulo m in a */
void print_vector ( int n, int a[n] );
/* writes the vector to screen */
void sort ( int a[], int lb, int ub );
/* sorts the numbers in a with index between lb and ub */
void sort_random_data ( void );
void sort_given_data ( void );
int main ( void )
{
int answer;
printf("Menu to test merge sort : \n");
printf(" 1. test randomly generated data.\n");
printf(" 2. test user given data.\n");
printf("Type 1 or 2 to choose : ");
scanf("%d", &answer);
if (answer == 1)
sort_random_data();
else if (answer == 2)
sort_given_data();
else
printf("invalid choice\n");
return 0;
}
void random_vector ( int n, int m, int a[n] )
{
int i;
for(i=0; i<n; i++) a[i] = rand() % m;
}
void print_vector ( int n, int a[n] )
{
int i;
for(i=0; i<n; i++) printf(" %d", a[i]);
printf("\n");
}
void sort ( int a[], int lb, int ub )
{
if (lb >= ub)
return;
else if (lb == ub-1)
{
if (a[lb] > a[ub])
{
int tmp = a[ub];
a[ub] = a[lb];
a[lb] = tmp;
}
}
else
{
int m = (lb+ub)/2; /* split array in two */
sort(a,lb,m) ; /* sort first half */
sort(a,m+1,ub); /* sort second half */
{ /* merge sorted halves */
int i,j,k,aux[ub-lb+1];
for(i=lb,j=m+1,k=0; ((i<=m) && (j<=ub)); k++)
aux[k] = ( a[i] < a[j] ? a[i++] : a[j++] );
while (i<=m) aux[k++] = a[i++];
while (j<=ub) aux[k++] = a[j++];
for(i=lb,k=0; i<=ub; i++,k++) a[i] = aux[k];
}
}
}
void sort_random_data ( void )
{
int s,m;
srand(time(NULL));
printf("Give number of elements to sort : ");
scanf("%d", &s);
printf("Give size of numbers : ");
scanf("%d", &m);
{
int i,a[s];
random_vector(s,m,a);
print_vector(s,a);
sort(a,0,s-1);
print_vector(s,a);
}
}
void sort_given_data ( void )
{
int n;
printf("Give number of elements to sort : ");
scanf("%d", &n);
{
int i,a[n];
for(i=0; i<n; i++)
{
printf("Give a number : ");
scanf("%d", &a[i]);
}
print_vector(n,a);
sort(a,0,n-1);
print_vector(n,a);
}
}
This simple sort forms the basis for understanding shell sort.
2. radix sort
The radix sort needs the following:
- extract most significant digit from a number; and
- a priority queue of integers.
2.1 counting and extracting digits
We group the prototypes in digits.h:
/* L-33 MCS 360 Monday 7 April 2003
* Some prototypes of utilities to implement radix sort */
int number_of_digits ( int n, int r );
/* returns the number of digits of a positive number n
* in the number system with radix r */
int digit ( int n, int r, int d, int k );
/* returns the k-th digit (set k=1 for most significant digit)
* of the positive number n in the number system with radix r,
* and where d = number_of_digits(n,r) */
and the definitions are in digits.c:
/* L-33 MCS 360 Monday 7 April 2003
* Some definitions of utilities to implement radix sort */
int number_of_digits ( int n, int r )
{
if (n < r)
return 1;
else
return 1 + number_of_digits(n/r,r);
}
int digit ( int n, int r, int d, int k )
{
int i,m;
for(i=0,m=n; i<d-k; i++,m=m/r);
return m%r;
}
A simple test program:
/* L-33 MCS 360 Monday 7 April 2003
* tests the operations in digits.h */
#include
#include"digits.h"
int main ( void )
{
int n,r,d,i,m;
printf("Give a positive number : ");
scanf("%d", &n);
printf("Give the radix of the number system : ");
scanf("%d", &r);
d = number_of_digits(n,r);
printf("Number of digits in %d is %d.\n", n, d);
printf("The digits in %d are", n);
for (m=0,i=1; i<=d; m=m*r+digit(n,r,d,i),i++)
printf(" %d", digit(n,r,d,i));
printf(".\n");
printf("The number rebuilt : %d\n", m);
return 0;
}
2.2 the priority queue
First comes the header file priority_queue.h:
/* L-33 MCS 360 Monday 7 April 2003
* declaration of a priority queue of integers */
typedef struct list priority_queue;
/* a priority queue is a list of integers */
struct list
{
int item; /* first item in list */
priority_queue *next; /* points to next item */
};
int length ( priority_queue *q );
/* postcondition: returns number of elements in q */
priority_queue *delete_element ( priority_queue *q, int *i, int *flag );
/* precondition: length(q) > 0;
* postcondition: smallest int is removed from priority queue q,
* if empty(q), *flag == -1, otherwise *flag == 0; */
priority_queue *insert_element ( priority_queue *q, int i );
/* postcondition: integer i is inserted to the priority queue q; */
void write_elements ( priority_queue *q );
/* postcondition: writes all elements in the queue to the screen; */
and next the definitions in priority_queue.c:
/* L-33 MCS 360 Monday 7 April 2003
* implementation of the operations in the priority queue */
#include
#include "priority_queue.h"
int length ( priority_queue *q )
{
if (q == NULL)
return 0;
else
return 1 + length(q->next);
}
priority_queue *delete_element ( priority_queue *q, int *i, int *flag )
{
if (q == NULL)
{
*flag = -1;
return q;
}
else
{
priority_queue *nq;
*flag = 0;
*i = q->item;
nq = q->next;
free(q);
return nq;
}
}
priority_queue *insert_element ( priority_queue *q, int i )
{
priority_queue *nq;
nq = (priority_queue*) calloc(1,sizeof(priority_queue));
nq->item = i;
if (q == NULL)
{
nq->next = NULL;
return nq;
}
else if (i < q->item)
{
nq->next = q;
return nq;
}
else
{
priority_queue *previous = q;
priority_queue *current = q->next;
while (current != NULL)
{
if (i < current->item) break;
previous = current;
current = current->next;
}
previous->next = nq;
nq->next = current;
return q;
}
}
void write_elements ( priority_queue *q )
{
if (q != NULL)
{
printf(" %d", q->item);
write_elements(q->next);
}
}
2.3 radix sort
/* L-33 MCS 360 Monday 7 April 2003
* implementation of radix sort */
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include"digits.h"
#include"priority_queue.h"
void random_vector ( int n, int m, int a[n] );
/* returns n random integers modulo m in a */
void print_vector ( int n, int a[n] );
/* writes the vector to screen */
void sort ( int n, int a[n], int r );
/* sorts the numbers using radix r */
void sort_random_data ( void );
void sort_given_data ( void );
int main ( void )
{
int answer;
printf("Menu to test radix sort : \n");
printf(" 1. test randomly generated data.\n");
printf(" 2. test user given data.\n");
printf("Type 1 or 2 to choose : ");
scanf("%d", &answer);
if (answer == 1)
sort_random_data();
else if (answer == 2)
sort_given_data();
else
printf("invalid choice\n");
return 0;
}
void random_vector ( int n, int m, int a[n] )
{
int i;
for(i=0; i<n; i++) a[i] = rand() % m;
}
void print_vector ( int n, int a[n] )
{
int i;
for(i=0; i<n; i++) printf(" %d", a[i]);
printf("\n");
}
void sort ( int n, int a[n], int r )
{
priority_queue *q[r];
int i,nd0,nd,kd,ind,flag;
for(i=0; i<r; i++) /* initialize queues */
q[i] = NULL;
nd0 = number_of_digits(a[0],r);
for(i=0; i<n; i++) /* insert to the queues */
{
nd = number_of_digits(a[i],r);
if (nd < nd0)
q[0] = insert_element(q[0],a[i]);
else
{
kd = digit(a[i],r,nd,1);
q[kd] = insert_element(q[kd],a[i]);
}
}
ind=0;
for(i=0; i<r; i++) /* delete from the queues */
while (q[i] != NULL)
q[i] = delete_element(q[i],&a[ind++],&flag);
}
void sort_random_data ( void )
{
int s,m,r;
srand(time(NULL));
printf("Give number of elements to sort : ");
scanf("%d", &s);
printf("Give size of numbers : ");
scanf("%d", &m);
printf("Give the radix of the number system : ");
scanf("%d", &r);
{
int i,a[s];
random_vector(s,m,a);
print_vector(s,a);
sort(s,a,r);
print_vector(s,a);
}
}
void sort_given_data ( void )
{
int n,r;
printf("Give number of elements to sort : ");
scanf("%d", &n);
printf("Give the radix of the number system : ");
scanf("%d", &r);
{
int i,a[n];
for(i=0; i<n; i++)
{
printf("Give a number : ");
scanf("%d", &a[i]);
}
print_vector(n,a);
sort(n,a,r);
print_vector(n,a);
}
}