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:
  1. extract most significant digit from a number; and
  2. 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);
   }
}