Article View: comp.lang.eiffel
Article #1618Re: Quicksort? (was Re: Coping with failure)
From: PAWLOWSKY marc
Date: Thu, 01 Mar 1990 20:26
Date: Thu, 01 Mar 1990 20:26
481 lines
11187 bytes
11187 bytes
In article <17412@cs.yale.edu> jellinghaus-robert@yale.UUCP writes:
>
>On another note, would it be possible for you to post your quicksort class?
Ok, here it is. It is kinda messy and I will post a better version
later on (cleaned up removing debug statements, plus probably adding
heap sort).
class ARRAY_COMPAR[T -> COMPARABLE]
-- Marc Pawlowsky
-- Graduate Student
-- Concordia University
-- Montreal, Quebec, Canada
-- This file is placed in the public domain. It may be used
-- freely as long as no charge is made for this file alone,
-- or as part of a library package. Programs using this
-- file may be charged for.
-- Copyright 1990 Marc Pawlowsky
export
repeat ARRAY,
is_sorted, is_sorted_range, quick_sort, merge, min_value, max_value,
min_value_range, max_value_range, print_range
inherit
ARRAY[T] rename Create as array_create;
STD_FILES
feature
Create(low, up: INTEGER) is
do
array_create(low, up);
end; -- Create
is_sorted: BOOLEAN is
-- is the array sorted
do
debug
output.putstring("is_sorted range is ");
output.putint(lower);
output.putstring(" .. ");
output.putint(upper);
output.new_line;
end; -- debug
Result := is_sorted_range(lower, upper);
end; -- is_sorted
is_sorted_range(low: INTEGER, up: INTEGER): BOOLEAN is
-- the objects in low .. up in nondecreasing order
require
low_large_enough: low >= lower;
up_small_enough: up <= upper;
low_small_enough: low <= up;
local
i: INTEGER;
k,l: T;
do
from i := up - 1;
Result := True;
invariant -- records greater than i are in nondecreasing order
variant i
until (not Result) or (i < low)
loop
k := item(i);
l := item(i + 1);
Result := (k <= l);
debug
k.print;
output.putstring(" <= ");
l.print;
if Result then
output.putstring(" True\n");
else
output.putstring(" False\n");
end; -- if
end; -- debug
i := i - 1;
end; -- loop
end; -- is_sorted_range
quick_sort is
-- sort the array in nondescending order
do
qsort(lower, upper);
ensure
sorted: Current.is_sorted;
end; -- quick_sort
qsort(m,n:INTEGER) is
-- sort records m..n into nondescending order
local
i,j: INTEGER;
k, temp, t2: T;
stop, stop2: BOOLEAN;
do
debug
output.putstring("Entering qsort(");
output.putint(m);
output.putchar(',');
output.putint(n);
output.putstring(")\n");
end; -- debug
-- QUICK SORT ALGORITHM
if m < n then
debug
print_range(m, n);
end; -- debug
k := Current.item(m);
from i := m + 1;
j := n;
invariant
left_low: max_value_range(m, i - 1) <= k;
right_high: (j < n) implies (min_value_range(j + 1, n) > k)
variant ends_converging: j - i + 2
until i > j
loop
debug
output.putstring("i=");
output.putint(i);
output.putstring(" j=");
output.putint(j);
output.new_line;
print_range(i, j);
end; -- debug
if item(i) <= k then
i := i + 1;
elsif item(j) > k then
j := j - 1
else
-- swap item(i) and item(j)
temp := item(i);
t2 := item(j);
put(temp, j);
put(t2, i);
i := i + 1;
j := j - 1;
end; -- if
end; -- loop
debug
output.putstring("start recursion i=");
output.putint(i);
output.putstring(" j=");
output.putint(j);
output.new_line;
print_range(m, n);
end; -- debug
temp := item(j);
put(temp, m);
put(k, j);
debug
print_range(m,n);
end; -- debug
check
new_up_smaller: (j - 1) < n;
new_low_larger: (j + 1) > m;
end;
qsort(m, j - 1);
qsort(j + 1, n);
debug
output.putstring("Exiting qsort(");
output.putint(m);
output.putchar(',');
output.putint(n);
output.putstring(")\n");
print_range(m,n);
end; -- debug
end; -- if
ensure
(m < n) implies is_sorted_range(m, n);
end; -- qsort
merge(other: like Current): like Current is
-- Give the sorted array after merging Current and Other
require
Current_sorted: Current.is_sorted;
other_sorted: other.is_sorted;
local
i, j, k: INTEGER;
do
Result.Create(1, (other.count + Current.count));
from i:= 1;
j := Current.lower;
k := other.lower;
invariant -- (Result.item(1 .. (i-1)) are sorted
-- (old j < j) or (old k < k)
variant (Result.count - i + 1)
until (j > Current.upper) or (k > other.upper)
loop
if Current.item(j) <= other.item(k) then
Result.put(Current.item(j), i);
j := j + 1;
else
Result.put(other.item(k), i);
k := k + 1;
end; -- if
i := i + 1;
end; -- loop
-- transfer the remaining records
if j <= Current.upper then
from
invariant
variant Current.count - j + 1
until j > Current.upper
loop
Result.put(Current.item(j), i);
i := i + 1;
j := j + 1;
end; -- loop
else
from
invariant
variant other.count - k + 1
until k > other.upper
loop
Result.put(other.item(k), i);
i := i + 1;
k := k + 1;
end; -- loop
end; -- if
end; -- merge
print_range(low, up:INTEGER) is
-- print low..up to output
require
low_large_enough: low >= lower;
up_small_enough: up <= upper;
low_small_enough: low <= up;
local
i: INTEGER;
do
from i:= low;
variant up - i + 1
until i > up
loop
output.putint(i);
output.putchar(' ');
item(i).print;
output.new_line;
i := i + 1;
end; -- loop
end; -- print_range
min_value: T is
-- the minimum value in teh array
do
Result := min_value_range(lower, upper);
end; -- min_value
max_value: T is
-- the maximum value in the array.
do
Result := max_value_range(lower, upper);
end; -- max_value
min_value_range(low, up: INTEGER): T is
-- the lowest element in the array for the range low .. up
require
low >= lower;
up <= upper;
low <= up;
local
i: INTEGER;
do
from i:= up;
Result := item(i);
i := i - 1;
invariant -- Result is the lowest for all j > i, Current.item(j)
variant i - low + 1
until i < low
loop
if item(i) < Result then
Result := item(i);
end; -- if
i := i - 1;
end; -- loop
end; -- min_value_range
max_value_range(low, up: INTEGER): T is
-- the highest element in the array for range low .. up
require
low >= lower;
up <= upper;
low <= up;
local
i: INTEGER;
do
from i:= up;
Result := item(i);
i := i - 1;
invariant -- Result is the highest for all j > i, Current.item(j)
variant i - low + 1
until i < low
loop
if item(i) > Result then
Result := item(i);
end; -- if
i := i - 1;
end; -- loop
end; -- max_value_range
end -- class ARRAY_COMPAR
---------------------------------------------------------------------------
testing classes
---------------------------------------------------------------------------
class COUNTER
-- An integer counter
export
item, increment, decrement, add, set,
out,
repeat COMPARABLE
inherit
ANY redefine out;
COMPARABLE redefine out
feature
item: INTEGER;
out: STRING is
-- print string
do
Result := item.out;
end; -- out
Create(i: INTEGER) is
do
item := i;
end; -- Create
set(i: INTEGER) is
do
item := i;
ensure
item = i;
end; -- set
increment is
do
item := item + 1;
ensure
(old item) + 1 = item;
end; -- increment
decrement is
do
item := item - 1;
ensure
(old item) - 1 = item;
end; -- decrement
add(x: INTEGER) is
do
item := item + x;
ensure
(old item) + x = item
end; -- add
infix "<" (other: like Current): BOOLEAN is
-- Is current element less than `other`
do
Result := item < other.item;
end; -- "<"
end; -- class COUNTER
class TEST_ARRAY_COMPAR
inherit
ANY;
RANDOM_NUMBERS;
STD_FILES
feature
amount: INTEGER is 20;
Create is
local
a: ARRAY_COMPAR[COUNTER];
i,j,mini,maxi: INTEGER;
k: COUNTER;
do
a.Create(1,amount);
from i := amount;
variant i
until i < 1
loop
j := random_int(1,9999);
k.Create(j);
a.put(k, i);
i := i - 1;
end; -- loop
putstring("BEFORE:\n");
putstring("is sorted: ");
if a.is_sorted then
putstring("TRUE\n");
else
putstring("FALSE\n");
end; -- if
mini := a.min_value.item;
maxi := a.max_value.item;
putint(mini);
putchar(' ');
putint(maxi);
new_line;
from i := amount;
variant i
until i < 1
loop
putint(a.item(i).item);
new_line;
i := i - 1;
end; -- loop
a.quick_sort;
putstring("AFTER:\n");
putstring("is sorted: ");
if a.is_sorted then
putstring("TRUE\n");
else
putstring("FALSE\n");
end; -- if
mini := a.min_value.item;
maxi := a.max_value.item;
putint(mini);
putchar(' ');
putint(maxi);
new_line;
from i := amount;
variant i
until i < 1
loop
putint(a.item(i).item);
new_line;
i := i - 1;
end; -- loop
end; -- Create
end -- class TEST_ARRAY_COMPAR
Technical Details
Message-ID:
<1884@clyde.concordia.ca>Path:
arc1-ca.pugleaf.net!utzoo!attcan!uunet!clyde.concordia.ca!hercule!marcapReferences:
<25EB6B0D.2249@maccs.dcss.mcmaster.ca> <1880@clyde.concordia.ca> <17412@cs.yale.edu>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!attcan!uunet!clyde.concordia.ca!hercule!marcap From: marcap@hercule.cs.concordia.ca (PAWLOWSKY marc) Newsgroups: comp.lang.eiffel Subject: Re: Quicksort? (was Re: Coping with failure) Message-ID: <1884@clyde.concordia.ca> Date: 1 Mar 90 20:26:55 GMT References: <25EB6B0D.2249@maccs.dcss.mcmaster.ca> <1880@clyde.concordia.ca> <17412@cs.yale.edu> Sender: usenet@clyde.concordia.ca Reply-To: marcap@hercule.CS.Concordia.CA (PAWLOWSKY marc) Organization: Concordia University, Montreal Quebec Lines: 481