Chapter #8 Examples in Oz
% Utility functions
proc {While Expr Stmt}
if {Expr} then {Stmt} {While Expr Stmt} end
end
fun {ArrayMax A}
N = {NewCell A.{Array.low A}}
in
for I in {Array.low A}..{Array.high A} do
if @N < A.I then
N := A.I
end
end
@N
end
fun {ListToArray L}
N = {Length L}
A = {NewArray 1 N _}
in
for I in 1..N do
A.I := {Nth L I}
end
A
end
% 8.2 Counting Sort
proc {CountingSort A K B}
C = {NewArray 0 K _}
in
% Instantiate and initialize lookup array for calculating
% sorted positions of each element.
B = {NewArray 1 {Array.high A} _}
for I in 0..K do
C.I = 0
end
% Count the occurrences of each number.
for J in 1..{Array.high A} do
C.(A.J) := C.(A.J) + 1
end
% For each i from 0 to k, calculate the sorted position of
% the last element of array with a key equal to i.
for I in 1..K do
C.I := C.I + C.(I-1)
end
% Copy the elements of array to their sorted positions in sorted.
local
J = {NewCell {Array.high A}}
in
{While
fun {$} @J >= 1 end
proc {$}
B.(C.(A.@J)) := A.@J
C.(A.@J) := C.(A.@J) - 1
J := @J - 1
end}
end
end
local
A = {Tuple.toArray 5#2#4#6#1#3}
in
{Browse 'CountingSort'#{Array.toRecord '#' {CountingSort A {ArrayMax A}}}}
end
% 8.3 Radix Sort
% Note: The algorithm does not specify sort algorithm for each digit.
% Using modified InsertionSort for simplicity.
% calculate the optimal radix
fun {OptimalRadix A}
Bits = {CalculateDigits 2 {ArrayMax A}}
Lgn = {FloatToInt {Float.log {IntToFloat {Array.high A}}} / {Float.log 2.0}}
in
{Min Bits Lgn}
end
% Determines how many digits of a given radix are necessary.
fun {CalculateDigits Radix Max}
I = {NewCell 0} % number of digits
Ri = {NewCell 1} % radix^i
in
{While
fun {$} @Ri =< Max end
proc {$}
I := @I + 1
Ri := @Ri * Radix
end}
@I
end
% Extracts ith digit in base
fun {Extract Radix D N}
(N div {Pow Radix D-1}) mod Radix
end
proc {RadixSort A Radix Digits}
proc {DigitInsertionSort A D}
for J in 2..{Array.high A} do
local
Key = A.J
I = {NewCell J-1}
in
{While
fun {$}
@I > 0 andthen
{Extract Radix D A.@I} > {Extract Radix D Key}
end
proc {$}
A.(@I+1) := A.@I
I := @I - 1
end}
A.(@I+1) := Key
end
end
skip
end
in
for I in 1..Digits do
{DigitInsertionSort A I}
end
end
local
A = {Tuple.toArray 329#457#657#839#436#720#355}
Radix = {OptimalRadix A}
Digits = {CalculateDigits Radix {ArrayMax A}}
in
{RadixSort A Radix Digits}
{Browse 'RadixSort'#{Array.toRecord '#' A}}
end
% 8.4 Bucket Sort
% Note: The algorithm does not specify data structure or key of buckets.
% Using native lists to simplify things.
proc {BucketSort A NumBuckets B}
% simple hash algorithm to determine number of buckets and hash
fun {BucketHash X} 1 + X div (1 + {ArrayMax A} div NumBuckets) end
Buckets = {NewArray 1 NumBuckets nil}
Result = {NewCell nil}
in
for I in 1..{Array.high A} do
Buckets.{BucketHash A.I} := A.I | Buckets.{BucketHash A.I}
end
for I in 1..NumBuckets do
Buckets.I := {Sort Buckets.I Value.'<'}
end
for I in 1..NumBuckets do
Result := {Append @Result Buckets.I}
end
B = {ListToArray @Result}
end
local
A = {Tuple.toArray 329#457#657#839#436#720#355}
in
{Browse 'BucketSort'#{Array.toRecord '#' {BucketSort A 3}}}
end
|