/* Output from p2c, the Pascal-to-C translator */
/* From input file "sorts2.pas" */


/* #include <p2c/p2c.h> */
#include "p2c.h"


/* This is the code from the 2nd Edition of Dale and Lilly */

/*********************************************************/
/*           A COLLECTION OF SORTING ROUTINES            */
/*********************************************************/
/* NOTE: It is assumed that in the following sorting     */
/*       routines, ArrayType has been declared as type   */
/*       ARRAY[1..MaxElements OF ElementType, where      */
/*       ElementType is some type whose values can be    */
/*       compared using < and >. The Swap procedure      */
/*       below is used by nearly all of the sorts.       */
/*********************************************************/

#define MaxElements     1000


typedef long ElementType;

typedef ElementType ArrayType[MaxElements];


Static ArrayType List;
Static long index_;


/*********************************************************/
/*                          SWAP                         */
/*********************************************************/

Static Void Swap(This, That)
long *This, *That;
{

  /* This gets That, and vice versa */
  ElementType Temp;


  Temp = *This;
  *This = *That;
  *That = Temp;

}  /* Swap */


/*********************************************************/
/*                      INSERTSORT                       */
/*********************************************************/

Static Void InsertSort(DataList, NumElements)
long *DataList;
long NumElements;
{

  /* Sort DataList[1]..DataList[NumElements] in increasing */
  /* order, using the insert sort algorithm.               */
  long Inner, Outer;   /* loop controls */
  boolean PlaceFound;


  Outer = 2;

  /* Loop Invariant: Outer may range from 2 to NumElements */
  /*    AND DataList[1]..DataList[Outer-1] is sorted.      */
  while (Outer <= NumElements) {   /* outer loop */
    /* Put DataList[Outer] in its proper place,        */
    /* relative to DataList[1]..DataList[Outer - 1].   */
    Inner = Outer;
    PlaceFound = false;

    /* Loop invariant: DataList[1]..DataList[Outer] */
    /* is sorted, with the (possible) exception of  */
    /* DataList[Inner].                             */
    while (Inner > 1 && !PlaceFound) {   /* inner loop */
      if (DataList[Inner - 1] < DataList[Inner - 2]) {
	/* Swap the elements and decrement Inner. */
	Swap(&DataList[Inner - 1], &DataList[Inner - 2]);
	Inner--;
      }  /* IF out of place */
      else  /* in place -- stop the inner loop now */
	PlaceFound = true;

    }  /* WHILE inner loop */

    /* Set up for next iteration of outer loop. */
    Outer++;

  }  /* outer loop */

}  /* InsertSort */


/*********************************************************/
/*                       SELECTSORT                      */
/*********************************************************/

Static Void SelectSort(Data, N)
long *Data;
long N;
{  /* InsertSort */

  /* Sorts array Data from index 1 through N in increasing */
  /* order, using the selection sort algorithm.            */
  long I, J;   /* loop controls */
  long Mindex;   /* index of minimum value */


  I = 1;

  /* Loop through the whole array. */
  while (I <= N) {   /* outer loop */
    /* Initialize. */
    Mindex = I;
    J = I + 1;

    /* Find the index of the minimum unsorted element. */
    while (J <= N) {  /* inner loop */
      if (Data[J - 1] < Data[Mindex - 1])
	Mindex = J;
      J++;
    }  /* inner loop */

    /* Swap the first unsorted element with the minimum */
    /* unsorted element in the array.                   */
    Swap(&Data[Mindex - 1], &Data[I - 1]);
    I++;

  }  /* outer loop */


}  /* SelectSort */


/*********************************************************/
/*                        BUBBLE1                        */
/*********************************************************/


Static Void Bubble1(Data, N)
long *Data;
long N;
{

  /* Sorts array Data from index 1 through N in increasing */
  /* order, using the bubble sort algorithm.               */
  long I, J;   /* loop controls */


  I = 1;

  /* Loop through the whole array. */
  while (I < N) {   /* outer loop */
    /* Bubble up smallest unsorted value. */
    J = N;

    while (J > I) {  /* inner loop */
      /* If the bottom value is smaller than its */
      /* predecessor, swap them.                 */
      if (Data[J - 1] < Data[J - 2])
	Swap(&Data[J - 1], &Data[J - 2]);
      J--;
    }  /* inner loop */

    I++;

  }  /* outer loop */


}  /* Bubble1 */


/*********************************************************/
/*                        BUBBLE2                        */
/*********************************************************/

Static Void Bubble2(Data, N)
long *Data;
long N;
{

  /* Sorts array Data from index 1 through N in increasing */
  /* order, using the bubble sort algorithm. Stops sorting */
  /* when the array is sorted.                             */
  long I, J;
  boolean Swapped;


  /* Initialize. */
  I = 1;
  Swapped = true;

  /* Loop through the whole array; stop when sorted (i.e., */
  /* when there are no values swapped in the inner loop).  */
  while (I < N && Swapped) {  /* outer loop */
    J = N;
    Swapped = false;

    /* Bubble up smallest unsorted value. */
    while (J > I) {  /* inner loop */
      /* If the bottom value is smaller than its */
      /* predecessor, swap them. Note that the   */
      /* swap took place by setting Swapped.     */
      if (Data[J - 1] < Data[J - 2]) {
	Swap(&Data[J - 1], &Data[J - 2]);
	Swapped = true;
      }  /* IF */

      J--;

    }  /* inner loop */


    I++;

  }  /* outer loop */


}  /* Bubble2 */


/************** Internal Procedure Merge ***************/

Local Void Merge(Data, LeftFirst, LeftLast, RightFirst, RightLast)
long *Data;
long LeftFirst, LeftLast, RightFirst, RightLast;
{

  /* Merge the two sorted subarrays Data[LeftFirst] ..    */
  /* Data[LeftLast] and Data[RightFirst]..Data[RightLast] */
  /* into a single sorted subarray Data[LeftFirst] ..     */
  /* Data[RightLast].                                     */
  ArrayType Temp;   /* auxiliary array */
  long Index;   /* index into Temp */
  long CurrentLeft, CurrentRight;


  /* Initialize indexes before loop. */
  CurrentLeft = LeftFirst;
  CurrentRight = RightFirst;
  Index = LeftFirst;

  /* Process while more elements in both subarrays. */
  while (CurrentLeft <= LeftLast && CurrentRight <= RightLast) {
    if (Data[CurrentLeft - 1] < Data[CurrentRight - 1]) {
      Temp[Index - 1] = Data[CurrentLeft - 1];
      CurrentLeft++;
    }  /* left element smaller */
    else {
      Temp[Index - 1] = Data[CurrentRight - 1];
      CurrentRight++;
    }  /* right element smaller or equal */


    Index++;

  }  /* WHILE loop */

  /* Copy any remaining elements from left half to Temp.  */
  while (CurrentLeft <= LeftLast) {
    Temp[Index - 1] = Data[CurrentLeft - 1];
    CurrentLeft++;
    Index++;
  }  /* WHILE more elements in left half */

  /* Copy any remaining elements from right half to Temp. */
  while (CurrentRight <= RightLast) {
    Temp[Index - 1] = Data[CurrentRight - 1];
    CurrentRight++;
    Index++;
  }  /* WHILE more elements in right half */

  /* Copy the sorted elements from Temp back into Data. */
  for (Index = LeftFirst - 1; Index < RightLast; Index++) {
    Data[Index] = Temp[Index];

  }
}  /* Merge */


/**********************************************************/
/*                       MERGESORT                        */
/**********************************************************/

Static Void MergeSort(Data, First, Last)
long *Data;
long First, Last;
{

  /* Sort Data[First]..Data[Last] in increasing order. */
  /* This is a recursive solution.                     */
  long Middle;   /* middle index in range to sort */

  /********************* Main procedure **********************/


  /* Base Case: Check for empty or single element. */
  if (First >= Last) {  /* General case */
    return;
  }  /* general case */


  /* ELSE - do nothing in base case */

  /* Cut the array into two halves. */
  Middle = (First + Last) / 2;

  /* Sort the left subarray. */
  MergeSort(Data, First, Middle);

  /* Sort the right subarray. */
  MergeSort(Data, Middle + 1, Last);   /* first index in left  half */

  /* Merge the two sorted halves together. */
  /* last  index in left  half */
  /* first index in right half */
  /* last  index in right half */

  Merge(Data, First, Middle, Middle + 1, Last);
}  /* MergeSort */


/* * * * * * * Internal Procedure Split * * * * * * * * */

Local Void Split(Data, First, Last, SplitPoint)
long *Data;
long First, Last, *SplitPoint;
{


  /* Chooses a splitting value, V, and rearranges */
  /* the values in the array Data such that:      */
  /*   Data[First]..Data[SplitPoint - 1] <= V     */
  /*   Data[SplitPoint] = V                       */
  /*   Data[SplitPoint + 1]..Data[Last] > V       */
  long Right, Left;
  ElementType V;   /* the splitting value */


  V = Data[First - 1];
  Right = First + 1;
  Left = Last;

  do {

    /* Move Right to the right until element > V. */
    while (Right < Left && Data[Right - 1] <= V)
      Right++;

    /* Check end condition. */
    if (Right == Left && Data[Right - 1] <= V)
      Right++;

    /* Move Left to the left until element <= V. */
    while (Right <= Left && Data[Left - 1] > V)
      Left--;

    if (Right < Left) {
      Swap(&Data[Right - 1], &Data[Left - 1]);
      Right++;
      Left--;
    }  /* IF */

  } while (Right <= Left);

  /* Swap first element with SplitPoint element. */
  Swap(&Data[First - 1], &Data[Left - 1]);
  *SplitPoint = Left;

}  /* Split */


/*********************************************************/
/*                      QUICKSORT                        */
/*********************************************************/

Static Void QuickSort(Data, First, Last)
long *Data;
long First, Last;
{

  /* Sorts array Data from index 1 through N in increasing */
  /* order, using the quick sort algorithm.                */
  long SplitPoint;

  /* * * * * * * * Main QuickSort Procedure * * * * * * * */


  if (First >= Last) {
    return;
  }  /* IF First < Last */


  /* Procedure Split chooses the splitting value */
  /* (V) and rearranges the array such that      */
  /*   Data[First]..Data[SplitPoint - 1] <= V    */
  /*   Data[SplitPoint] = V                      */
  /*   Data[SplitPoint + 1]..Data[Last] > V      */
  Split(Data, First, Last, &SplitPoint);

  /* Sort the two "halves." */
  QuickSort(Data, First, SplitPoint - 1);

  QuickSort(Data, SplitPoint + 1, Last);
}  /* QuickSort */


/**********************************************************/
/*                        HEAPSORT                        */
/**********************************************************/
/* NOTE: Procedure HeapSort uses the ReheapDown operation */
/*       on heaps; this operation has been included here. */
/**********************************************************/

Static Void ReheapDown(HeapElements, Root, Bottom)
long *HeapElements;
long Root, Bottom;
{

  /* Restore the Order property of heaps to the subtree  */
  /* starting at Root. It is assumed that, on invocation */
  /* of the procedure, the Order property is violated    */
  /* only by the root node.                              */
  boolean HeapOK;   /* the heap repair is finished */
  long MaxChild;   /* index of the larger child value */


  HeapOK = false;

  /* Process until Root value is in its correct place. */
  while (Root * 2 <= Bottom && !HeapOK) {
    /* Calculate the index of child with larger value. */
    if (Root * 2 == Bottom) {   /* only one child node */
      MaxChild = Root * 2;

    } else {  /* pick greater of the two children */
      if (HeapElements[Root * 2 - 1] > HeapElements[Root * 2])
	    /* left  child */
	      MaxChild = Root * 2;
      else
	MaxChild = Root * 2 + 1;
      /* right child */
    }

    /* If heap property is violated, swap values. */
    if (HeapElements[Root - 1] < HeapElements[MaxChild - 1])
    {  /* not yet a heap */
      Swap(&HeapElements[Root - 1], &HeapElements[MaxChild - 1]);
      Root = MaxChild;
    } else {  /* already is a heap */
      HeapOK = true;

    }
  }  /* WHILE loop */


}  /* ReheapDown */


/* * * * * * * * * Main procedure HeapSort * * * * * * * * */

Static Void HeapSort(Data, NumElements)
long *Data;
long NumElements;
{

  /* Sorts the first NumElements values of array Data in */
  /* ascending order, using the HeapSort algorithm.      */
  long NodeIndex;


  /* Build the original heap from the unsorted elements. */
  for (NodeIndex = NumElements / 2; NodeIndex >= 1; NodeIndex--)
    ReheapDown(Data, NodeIndex, NumElements);

  /* Sort the elements in the heap by swapping the root    */
  /* (current largest) value with the last unsorted value, */
  /* then reheaping the remaining part of the array.       */
  for (NodeIndex = NumElements - 1; NodeIndex >= 1; NodeIndex--) {
    Swap(Data, &Data[NodeIndex]);
    ReheapDown(Data, 1L, NodeIndex);
  }  /* FOR loop */

}  /* HeapSort */


main(argc, argv)
int argc;
Char *argv[];
{  /* Main Program SortDriver */

  /* PASCAL_MAIN(argc, argv); */

  List[0] = 5;
  List[1] = 4;
  List[2] = 3;
  List[3] = 2;
  List[4] = 1;

/*
  printf("This is InsertSort 2.\n\n");
  InsertSort(List, 5L);
*/
/*
  printf("This is SelectSort 2.\n\n");
  SelectSort(List, 5L);
*/
/*
  printf("This is HeapSort 2.\n\n");
  HeapSort(List, 5L);
*/
/*
  printf("This is QuickSort 2.\n\n");
  QuickSort(List, 1L, 5L);
*/

  for (index_ = 1; index_ <= 5; index_++)
    printf("%12ld", List[index_ - 1]);
  putchar('\n');

  exit(EXIT_SUCCESS);
}  /* Main Program SortDriver */

/* End. */
