1
(* Animation of sorting algorithms. *)
5
(* Information on a given sorting process *)
8
{ array: int array; (* Data to sort *)
9
x0: int; (* X coordinate, lower left corner *)
10
y0: int; (* Y coordinate, lower left corner *)
11
width: int; (* Width in pixels *)
12
height: int; (* Height in pixels *)
13
nelts: int; (* Number of elements in the array *)
14
maxval: int; (* Max val in the array + 1 *)
15
rad: int (* Dimension of the rectangles *)
18
(* Array assignment and exchange with screen update *)
20
let screen_mutex = Mutex.create()
23
fill_rect (gc.x0 + (gc.width * i) / gc.nelts)
24
(gc.y0 + (gc.height * v) / gc.maxval)
28
Mutex.lock screen_mutex;
29
set_color background; draw gc i gc.array.(i);
30
set_color foreground; draw gc i v;
32
Mutex.unlock screen_mutex
35
let val_i = gc.array.(i) in
36
assign gc i gc.array.(j);
39
(* Construction of a graphic context *)
41
let initialize name array maxval x y w h =
42
let (_, label_height) = text_size name in
43
let rad = (w - 2) / (Array.length array) - 1 in
45
{ array = Array.copy array;
46
x0 = x + 1; (* Leave one pixel left for Y axis *)
47
y0 = y + 1; (* Leave one pixel below for X axis *)
48
width = w - 2; (* 1 pixel left, 1 pixel right *)
49
height = h - 1 - label_height - rad;
50
nelts = Array.length array;
53
moveto (gc.x0 - 1) (gc.y0 + gc.height);
54
lineto (gc.x0 - 1) (gc.y0 - 1);
55
lineto (gc.x0 + gc.width) (gc.y0 - 1);
56
moveto (gc.x0 - 1) (gc.y0 + gc.height);
58
for i = 0 to Array.length array - 1 do
63
(* Main animation function *)
65
let display functs nelts maxval =
66
let a = Array.create nelts 0 in
67
for i = 0 to nelts - 1 do
68
a.(i) <- Random.int maxval
70
let num_finished = ref 0 in
71
let lock_finished = Mutex.create() in
72
let cond_finished = Condition.create() in
73
for i = 0 to Array.length functs - 1 do
74
let (name, funct, x, y, w, h) = functs.(i) in
75
let gc = initialize name a maxval x y w h in
79
Mutex.lock lock_finished;
81
Mutex.unlock lock_finished;
82
Condition.signal cond_finished)
85
Mutex.lock lock_finished;
86
while !num_finished < Array.length functs do
87
Condition.wait cond_finished lock_finished
89
Mutex.unlock lock_finished;
96
let gc = Queue.take q in
97
begin match gc.action with
101
for i = 0 to !delay do () done;
104
if key_pressed() then begin
105
match read_key() with
109
delay := (Char.code c - 48) * 500
115
| Queue.Empty -> read_key(); ()
118
(* The sorting functions. *)
123
let ordered = ref false in
124
while not !ordered do
126
for i = 0 to Array.length gc.array - 2 do
127
if gc.array.(i+1) < gc.array.(i) then begin
136
let insertion_sort gc =
137
for i = 1 to Array.length gc.array - 1 do
138
let val_i = gc.array.(i) in
139
let j = ref (i - 1) in
140
while !j >= 0 && val_i < gc.array.(!j) do
141
assign gc (!j + 1) gc.array.(!j);
144
assign gc (!j + 1) val_i
149
let selection_sort gc =
150
for i = 0 to Array.length gc.array - 1 do
152
for j = i+1 to Array.length gc.array - 1 do
153
if gc.array.(j) < gc.array.(!min) then min := j
161
let rec quick lo hi =
162
if lo < hi then begin
165
let pivot = gc.array.(hi) in
167
while !i < hi && gc.array.(!i) <= pivot do incr i done;
168
while !j > lo && gc.array.(!j) >= pivot do decr j done;
169
if !i < !j then exchange gc !i !j
175
in quick 0 (Array.length gc.array - 1)
180
let rec merge i l1 l2 =
185
assign gc i v2; merge (i+1) l1 r2
187
assign gc i v1; merge (i+1) r1 l2
188
| (v1::r1, v2::r2) ->
190
then begin assign gc i v1; merge (i+1) r1 l2 end
191
else begin assign gc i v2; merge (i+1) l1 r2 end in
192
let rec msort start len =
193
if len < 2 then () else begin
196
msort (start+m) (len-m);
198
(Array.to_list (Array.sub gc.array start m))
199
(Array.to_list (Array.sub gc.array (start+m) (len-m)))
201
msort 0 (Array.length gc.array)
207
moveto 0 0; draw_string "Press a key to start...";
209
while not (key_pressed()) do incr seed done;
213
let prompt = "0: fastest ... 9: slowest, press 'q' to quit" in
214
moveto 0 0; draw_string prompt;
215
let (_, h) = text_size prompt in
216
let sx = size_x() / 2 and sy = (size_y() - h) / 3 in
217
display [| "Bubble", bubble_sort, 0, h, sx, sy;
218
"Insertion", insertion_sort, 0, h+sy, sx, sy;
219
"Selection", selection_sort, 0, h+2*sy, sx, sy;
220
"Quicksort", quick_sort, sx, h, sx, sy;
221
(** "Heapsort", heap_sort, sx, h+sy, sx, sy; **)
222
"Mergesort", merge_sort, sx, h+2*sy, sx, sy |]
226
let _ = if !Sys.interactive then () else begin animate(); exit 0 end