home *** CD-ROM | disk | FTP | other *** search
- PROGRAM CompareSorts; {Problem 23. compare at least 5 sorts}
- {included: ultra, shell, quick, heap,}
- {bubble, flip, delayed replacement }
- USES {other good sorts not used: tree sort, radix sort, hash sort }
- Crt,Dos; { To use an ultra sort I cut the size of the random }
- CONST { range to 255. This had an effect on the speed of }
- Count = 1000; { the other sorts. Probably more scores of equal }
- Limit = 255; { value. The ultra sort is not really practical but }
- TYPE { it makes an impressive display. }
- Raytype = array[1..count] of integer;
- Othertype = array[0..limit] of integer;
- {-----------------------------}
- Procedure FillArray(VAR List:raytype);
- VAR
- X : integer;
- Begin
- For X := 1 to Count Do Begin
- List[X] := Random(limit) + 1;
- End; {for}
- End;
- {-----------------------------}
- Procedure ClearArray(VAR List:OtherType);
- VAR
- X : integer;
- Begin
- For X := 0 to Limit Do Begin
- List[X] := 0;
- End; {for}
- End;
- {-----------------------------}
- Function Seconds : real;
- VAR
- Hr,Min,Sec,Hund : word;
- Begin {returns total elapsed seconds since midnight}
- GetTime(Hr,Min,Sec,Hund);
- Seconds := Hr*3600 + Min*60 + Sec + Hund/100;
- End {seconds};
- {-----------------------------}
- Procedure DisplayTime(VAR Finish:real; Start:real; Adj:real);
- VAR
- Day,Time : real; { This procedure uses the starting time of }
- Min,Sec : integer; { an earlier event and returns the difference }
- { between then & now. A correction factor }
- Begin { for the time loop (Adj) can subtracted also.}
- Finish := Seconds; {--seconds since midnight }
- Day := 24*3600; {--number of seconds in an entire day }
- Time := Finish - Start - Adj; {--difference between start and finish }
- If Time < 0 then {--if clock cycles past midnight }
- Time := Time + Day;
- Min := Trunc(Time) Div 60; {-- print minutes }
- Write(Min:3,':');
- If Time-Min*60 < 10 then
- Write('0',Time-Min*60:4:2) { if second less than 10 ... add zero }
- Else
- Write(Time-Min*60:5:2); { - print seconds }
- End; {displaytime}
- {-----------------------------}
- Procedure View(List:RayType);
- VAR
- Row,Col,Next : integer;
- Ch : char;
-
- Begin
- GotoXY(1,24);
- Ch := chr(32);
- Write('Do you wish to view list (Y or N) ?':57);
- Repeat
- Ch := UpCase(ReadKey);
- Until Ch In['Y','N'];
- If Ch = 'Y' then Begin
- Row := 6;
- Col := 1;
- Next:= 0;
- Repeat
- GotoXY(Col,Row);
- Next := Next + 1;
- Write(Next:4,':',List[Next]:4,chr(222));
- Row := Row + 1;
- If Row = 23 then Begin
- Col := Col + 10;
- Row := 6;
- If Col > 80 then Begin
- GotoXY(1,24);
- ClrEol;
- Write('- press any key to continue -':48);
- Ch := ReadKey;
- Col := 1;
- GotoXY(1,24);
- ClrEol;
- End; {if col}
- End; {if row}
- Until Next = Count;
- If Row <> 23 then
- GotoXY(Col,Row)
- Else
- If Col < 80 then
- GotoXY(Col + 10,Row)
- Else
- GotoXY(1,8);
- Write(' ',chr(222));
- End; {if Y}
- GotoXY(1,24);
- ClrEol;
- End; {view}
- {-----------------------------}
- Procedure UltraSort(VAR NumList:raytype; VAR FreqTab:othertype);
- VAR
- Y,X,W : integer; { based on logic taken from 'PASCALGORYTHM' }
- { there could not be a faster sort! }
- Begin
- For X := 0 to Count Do Begin
- FreqTab[NumList[X]] := FreqTab[NumList[X]] + 1;
- End;
- Y := 0;
- For X := 0 to Limit Do Begin
- If FreqTab[X] > 0 then Begin
- For W := 1 to FreqTab[X] Do Begin
- Y := Y + 1;
- NumList[Y] := X;
- End; {for}
- End; {if}
- End; {for x}
- End; {ultrasort}
- {-----------------------------}
- Procedure Mergesort(VAR List1 : RayType; lo,hi : integer);
- {
- Sorts List1[lo] through List1[hi] ... inclusive
- }
- VAR
- t,size : integer;
- {..............................}
- Procedure Merges(VAR List1 : RayType; lo,hi:integer);
- VAR
- i,j,k,mid,m,n : integer;
- Temp : RayType;
- Begin
- k := 1;
- j := 1;
- i := 1;
- lo := lo - 1;
- mid := (lo + hi) Div 2;
- m := mid - lo;
- n := hi - mid;
- While k <= m + n Do Begin
- If i > m then Begin
- Temp[k] := List1[mid + j];
- j := j + 1;
- End {if i}
- Else If j > n then Begin
- Temp[k] := List1[lo + i];
- i := i + 1;
- End {if j}
- Else If List1[lo + i] <= List1[mid + j] then Begin
- Temp[k] := List1[lo + i];
- i := i + 1;
- End {if lo}
- Else Begin
- Temp[k] := List1[mid + j];
- j := j + 1;
- End; {mid}
- k := k +1;
- End; {while}
- For k := 1 to m + n Do
- List1[lo + k] := Temp[k];
- End; {merges}
- {.............................}
- Begin {mergesort}
- size := hi - lo + 1;
- If (size = 2) and (List1[hi] < List1[lo]) then Begin {exchange}
- t := List1[hi];
- List1[hi] := List1[lo];
- List1[lo] := t;
- End {swap}
- Else If size > 2 then Begin
- Mergesort(List1,lo,lo - 1 + size Div 2);
- Mergesort(List1,lo + size Div 2,hi);
- Merges(List1,lo,hi)
- End; {else > 2}
- End; {mergesort}
- {-----------------------------}
- Procedure Shellsort(VAR List:raytype; N:integer);
- VAR
- X,Right,Lptr,Rptr,Gap,Temp : integer; { After my meeting with you 9/3 }
- Change : boolean; { I looked up shell sort in the }
- Begin { the other references you provided }
- Gap := N; { me. None seemed to be the same as }
- While Gap > 0 Do Begin { we discussed. So I build this one }
- Gap := Gap Div 2; { from scratch. I was very pleased }
- Right := N - Gap; { with the result. According to the }
- For X := 1 to Right Do Begin { book 'PASCALGORITHM' It should be }
- Lptr := X; { slightly faster than MERGESORT. }
- Repeat
- Rptr := Lptr + Gap;
- If List[Lptr] > List[Rptr] then Begin
- Temp := List[Lptr];
- List[Lptr] := List[Rptr];
- List[Rptr] := Temp;
- Change := true;
- Lptr := Lptr - Gap;
- End
- Else
- Change := false;
- Until (Lptr < 1) or Not Change;
- End; {for}
- End; {while}
- End; {shellsort}
- {-----------------------------}
- Procedure BubbleSort(VAR List:RayType; N:integer);
- VAR
- X,Y,Temp : integer;
- Begin
- For X := 1 to N - 1 Do Begin
- For Y := X + 1 to N Do Begin
- If List[X] > List[Y] then Begin
- Temp := List[X];
- List[X] := List[Y];
- List[Y] := Temp;
- End; {if}
- End; {for y}
- End; {for x}
- End; {bubblesort}
- {----------------------------}
- Procedure QuickSort(VAR A:raytype; L,R : integer);
- {
- Sorts array A[L..R], where the main program has set A[R + 1] to
- "infinity," that is, a number guaranteed to be larger than any A[L..R]
- }
- VAR
- i,j,PIV,t : integer;
- Begin
- If L < R then Begin
- i := L + 1; { initialize left pointer }
- j := R; { initialize right pointer }
- PIV := A[L]; { select left most array element for a pivot }
- Repeat { move the pointers i & j as far inward as possible }
- While A[i] <= PIV Do
- i := i + 1; { move left pointer to the right }
- While A[j] > PIV Do
- j := j - 1; { move right pointer to the left }
- If i < j then Begin { exchange items pointed to by i and j}
- t := A[i];
- A[i] := A[j];
- A[j] := t;
- End;
- Until i > j;
- { now two final replacements complete a partitioning }
- A[L] := A[j];
- A[j] := PIV;
- { finish by recursively sorting the left and right partitions}
- Quicksort(A,L,j - 1);
- Quicksort(A,i,R)
- End; { logic performed only when L < R }
- End; {quicksort}
- {----------------------------}
- Procedure FlipSort(VAR List:Raytype; N :integer);
- VAR
- X,Temp,Top,Bot,Flips : integer; { This is my sort, Now I admit that it is }
- { not fast, but at the time I thought of }
- Begin { it, I didn't know what a fast sort was. }
- Bot := N; { Its value comes in an array where only }
- Top := 1; { a few elements need to be sorted. After }
- Repeat { an editing session. }
- Flips := 0;
- For X := Bot downto Top + 1 Do Begin
- If List[X] < List[X-1] then Begin
- Temp := List[X];
- List[X] := List[X-1];
- List[X-1] := Temp;
- Flips := Flips + 1;
- End; {if}
- End; {going up}
- Top := Top +1;
- If Flips > 0 Then Begin
- Flips := 0;
- For X := Top to Bot - 1 Do Begin
- If List[X] > List[X+1] then Begin
- Temp := List[X];
- List[X] := List[X+1];
- List[X+1] := Temp;
- Flips := Flips + 1;
- End; {if}
- End; {for}
- End; {if}
- Bot := Bot-1;
- Until (Flips = 0) or (Top >= Bot);
- End; {flipsort}
- {-----------------------------}
- Procedure DelaySort(VAR List:RayType; N:integer);
- VAR
- X,Y,Temp,SmallPtr : integer;
- { this sorts small to large }
- Begin
- For X := 1 to N - 1 Do Begin
- SmallPtr := X;
- For Y := X + 1 to N Do Begin
- If List[SmallPtr] > List[Y] then
- SmallPtr := Y;
- End; {for y}
- Temp := List[X];
- List[X] := List[SmallPtr];
- List[SmallPtr] := Temp;
- End; {for X}
- End; {delaysort}
- {------------------------}
- Procedure Heapsort(VAR A:raytype; N:integer);
- VAR
- i : integer;
- Procedure Exchange(VAR a,b : integer);
- VAR
- t : integer;
- Begin
- t := a;
- a := b;
- b := t;
- End; {exchange}
- {----------}
- Procedure Rebuild(j,m : integer);
- VAR
- k : integer;
- sinking : boolean;
- Begin
- sinking := true;
- k := j + 1;
- While (k <= m) and sinking Do Begin
- If a[k] < a[k + 1] then
- If k < m then
- k := k + 1; {find the larger child}
- If a[j] < a[k] then {exchange a[j] with the larger of its children}
- Begin
- Exchange(a[j],a[k]);
- j := k; {advance j to point to latest point of insertion}
- k := 2*k {advance k to point to first child of old k }
- End {to see if item should further sink down }
- Else {change sentinel to force termination }
- sinking := false
- End
- End; {rebuild}
- {----------}
- Procedure Buildheap;
- VAR
- i : integer;
- Begin
- For i := n Div 2 downto 1 Do
- Rebuild(i,n);
- End; {buildheap}
- {----------}
- BEGIN {heapsort}
- Buildheap;
- For i := n downto 2 Do Begin
- Exchange(a[1],a[i]); { exchange top of heap and current last element }
- Rebuild(1,i-1) { restore heap }
- End;
- END; {heapsort}
- {-----------------------------}
- Procedure Empty(VAR List:raytype);
- Begin
- End;
- {-----------------------------}
- VAR
- FreqTab : othertype;
- TestList,OriginList : raytype;
- X : integer;
- Start,Adj,Finish : real;
- Begin {main}
- Randomize;
- ClrScr;
- Writeln(' 23. Run various sorts with a common array to compare the',
- ' completion time.');
- For X := 1 to 80 Do Write(chr(196));
- Writeln; Writeln;
- For X := 1 to 80 Do Write(chr(196));
- GotoXY(1,23);
- For X := 1 to 80 Do Write(chr(196));
- ClearArray(FreqTab);
- FillArray(TestList);
- OriginList := TestList; { save array before sort }
- {----------------------------}
- GotoXY(24,24); { This is a check to see if the program }
- Adj := 0; { uses any time during the Seconds and }
- Write('Adjustment = '); { and DisplayTime procedure calls. The }
- Start := Seconds; { variable Adj will then adjust any use }
- Empty(TestList); { of this sequence in future uses. It }
- DisplayTime(Finish,Start,Adj); { appears after running this program }
- Adj := Finish - Start; { that it was not needed, but I left it }
- {---------------------------- in in case this is run on a slow comp.}
- GotoXY(1,3); Write('BubbleSort');{ to adjust for a slow display. }
- GotoXY(1,4);
- Start := Seconds;
- BubbleSort(TestList,Count);
- DisplayTime(Finish,Start,Adj);
- Write(^G);
- View(TestList);
- TestList := OriginList;
- {-----------------------------}
- GotoXY(12,3); Write('FlipSort');
- GotoXY(11,4);
- Start := Seconds;
- FlipSort(TestList,Count);
- DisplayTime(Finish,Start,Adj);
- Write(^G);
- View(TestList);
- TestList := OriginList;
- TestList := OriginList;
- {----------------------------}
- GotoXY(22,3); Write('DelaySort');
- GotoXY(21,4);
- Start := Seconds;
- DelaySort(TestList,Count);
- DisplayTime(Finish,Start,Adj);
- Write(^G);
- View(TestList);
- TestList := OriginList;
- {----------------------------}
- GotoXY(32,3); Write('HeapSort');
- GotoXY(31,4);
- Start := Seconds;
- Heapsort(TestList,Count);
- DisplayTime(Finish,Start,Adj);
- Write(^G);
- View(TestList);
- TestList := OriginList;
- {----------------------------}
- GotoXY(42,3); Write('ShellSort');
- GotoXY(41,4);
- Start := Seconds;
- ShellSort(TestList,Count);
- DisplayTime(Finish,Start,Adj);
- Write(^G);
- View(TestList);
- TestList := OriginList;
- {----------------------------}
- GotoXY(52,3); Write('MergeSort');
- GotoXY(51,4);
- Start := Seconds;
- MergeSort(TestList,1,Count);
- DisplayTime(Finish,Start,Adj);
- Write(^G);
- View(TestList);
- TestList := OriginList;
- {----------------------------}
- GotoXY(62,3); Write('QuickSort');
- GotoXY(61,4);
- Start := Seconds;
- QuickSort(TestList,1,Count);
- DisplayTime(Finish,Start,Adj);
- Write(^G);
- View(TestList);
- TestList := OriginList;
- {----------------------------}
- GotoXY(72,3); Write('UltraSrt');
- GotoXY(71,4);
- Start := Seconds;
- UltraSort(TestList,FreqTab);
- DisplayTime(Finish,Start,Adj);
- Write(^G);
- View(TestList);
- TestList := OriginList;
- {----------------------------}
- End. {compare}
-