Data update
This commit is contained in:
parent
5150844a7d
commit
4bb20c9b71
7735 changed files with 38060 additions and 199180 deletions
|
|
@ -1,257 +0,0 @@
|
|||
----------------------------------------------------------------------
|
||||
|
||||
with Ada.Numerics.Float_Random;
|
||||
with Ada.Text_IO;
|
||||
|
||||
procedure quickselect_task
|
||||
is
|
||||
|
||||
use Ada.Numerics.Float_Random;
|
||||
use Ada.Text_IO;
|
||||
|
||||
gen : Generator;
|
||||
|
||||
----------------------------------------------------------------------
|
||||
--
|
||||
-- procedure partition
|
||||
--
|
||||
-- Partitioning a subarray into two halves: one with elements less
|
||||
-- than or equal to a pivot, the other with elements greater than or
|
||||
-- equal to a pivot.
|
||||
--
|
||||
|
||||
generic
|
||||
type T is private;
|
||||
type T_Array is array (Natural range <>) of T;
|
||||
procedure partition
|
||||
(less_than : access function
|
||||
(x, y : T)
|
||||
return Boolean;
|
||||
pivot : in T;
|
||||
i_first, i_last : in Natural;
|
||||
arr : in out T_Array;
|
||||
i_pivot : out Natural);
|
||||
|
||||
procedure partition
|
||||
(less_than : access function
|
||||
(x, y : T)
|
||||
return Boolean;
|
||||
pivot : in T;
|
||||
i_first, i_last : in Natural;
|
||||
arr : in out T_Array;
|
||||
i_pivot : out Natural)
|
||||
is
|
||||
i, j : Integer;
|
||||
temp : T;
|
||||
begin
|
||||
|
||||
i := Integer (i_first) - 1;
|
||||
j := i_last + 1;
|
||||
|
||||
while i /= j loop
|
||||
-- Move i so everything to the left of i is less than or equal
|
||||
-- to the pivot.
|
||||
i := i + 1;
|
||||
while i /= j and then not less_than (pivot, arr (i)) loop
|
||||
i := i + 1;
|
||||
end loop;
|
||||
|
||||
-- Move j so everything to the right of j is greater than or
|
||||
-- equal to the pivot.
|
||||
if i /= j then
|
||||
j := j - 1;
|
||||
while i /= j and then not less_than (arr (j), pivot) loop
|
||||
j := j - 1;
|
||||
end loop;
|
||||
end if;
|
||||
|
||||
-- Swap entries.
|
||||
temp := arr (i);
|
||||
arr (i) := arr (j);
|
||||
arr (j) := temp;
|
||||
end loop;
|
||||
|
||||
i_pivot := i;
|
||||
|
||||
end partition;
|
||||
|
||||
----------------------------------------------------------------------
|
||||
--
|
||||
-- procedure quickselect
|
||||
--
|
||||
-- Quickselect with a random pivot. Returns the (k+1)st element of a
|
||||
-- subarray, according to the given order predicate. Also rearranges
|
||||
-- the subarray so that anything "less than" the (k+1)st element is to
|
||||
-- the left of it, and anything "greater than" it is to its right.
|
||||
--
|
||||
-- I use a random pivot to get O(n) worst case *expected* running
|
||||
-- time. Code using a random pivot is easy to write and read, and for
|
||||
-- most purposes comes close enough to a criterion set by Scheme's
|
||||
-- SRFI-132: "Runs in O(n) time." (See
|
||||
-- https://srfi.schemers.org/srfi-132/srfi-132.html)
|
||||
--
|
||||
-- Of course we are not bound here by SRFI-132, but still I respect
|
||||
-- it as a guide.
|
||||
--
|
||||
-- A "median of medians" pivot gives O(n) running time, but
|
||||
-- quickselect with such a pivot is a complicated algorithm requiring
|
||||
-- many comparisons of array elements. A random number generator, by
|
||||
-- contrast, requires no comparisons of array elements.
|
||||
--
|
||||
|
||||
generic
|
||||
type T is private;
|
||||
type T_Array is array (Natural range <>) of T;
|
||||
procedure quickselect
|
||||
(less_than : access function
|
||||
(x, y : T)
|
||||
return Boolean;
|
||||
i_first, i_last : in Natural;
|
||||
k : in Natural;
|
||||
arr : in out T_Array;
|
||||
the_element : out T;
|
||||
the_elements_index : out Natural);
|
||||
|
||||
procedure quickselect
|
||||
(less_than : access function
|
||||
(x, y : T)
|
||||
return Boolean;
|
||||
i_first, i_last : in Natural;
|
||||
k : in Natural;
|
||||
arr : in out T_Array;
|
||||
the_element : out T;
|
||||
the_elements_index : out Natural)
|
||||
is
|
||||
procedure T_partition is new partition (T, T_Array);
|
||||
|
||||
procedure qselect
|
||||
(less_than : access function
|
||||
(x, y : T)
|
||||
return Boolean;
|
||||
i_first, i_last : in Natural;
|
||||
k : in Natural;
|
||||
arr : in out T_Array;
|
||||
the_element : out T;
|
||||
the_elements_index : out Natural)
|
||||
is
|
||||
i, j : Natural;
|
||||
i_pivot : Natural;
|
||||
i_final : Natural;
|
||||
pivot : T;
|
||||
begin
|
||||
|
||||
i := i_first;
|
||||
j := i_last;
|
||||
|
||||
while i /= j loop
|
||||
i_pivot :=
|
||||
i + Natural (Float'Floor (Random (gen) * Float (j - i + 1)));
|
||||
i_pivot := Natural'Min (j, i_pivot);
|
||||
pivot := arr (i_pivot);
|
||||
|
||||
-- Move the last element to where the pivot had been. Perhaps
|
||||
-- the pivot was already the last element, of course. In any
|
||||
-- case, we shall partition only from i to j - 1.
|
||||
arr (i_pivot) := arr (j);
|
||||
|
||||
-- Partition the array in the range i .. j - 1, leaving out
|
||||
-- the last element (which now can be considered garbage).
|
||||
T_partition (less_than, pivot, i, j - 1, arr, i_final);
|
||||
|
||||
-- Now everything that is less than the pivot is to the left
|
||||
-- of I_final.
|
||||
|
||||
-- Put the pivot at i_final, moving the element that had been
|
||||
-- there to the end. If i_final = j, then this element is
|
||||
-- actually garbage and will be overwritten with the pivot,
|
||||
-- which turns out to be the greatest element. Otherwise, the
|
||||
-- moved element is not less than the pivot and so the
|
||||
-- partitioning is preserved.
|
||||
arr (j) := arr (i_final);
|
||||
arr (i_final) := pivot;
|
||||
|
||||
-- Compare i_final and k, to see what to do next.
|
||||
if i_final < k then
|
||||
i := i_final + 1;
|
||||
elsif k < i_final then
|
||||
j := i_final - 1;
|
||||
else
|
||||
-- Exit the loop.
|
||||
i := i_final;
|
||||
j := i_final;
|
||||
end if;
|
||||
end loop;
|
||||
|
||||
the_element := arr (i);
|
||||
the_elements_index := i;
|
||||
|
||||
end qselect;
|
||||
begin
|
||||
-- Adjust k for the subarray's position.
|
||||
qselect
|
||||
(less_than, i_first, i_last, k + i_first, arr, the_element,
|
||||
the_elements_index);
|
||||
end quickselect;
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
type Integer_Array is array (Natural range <>) of Integer;
|
||||
|
||||
procedure integer_quickselect is new quickselect
|
||||
(Integer, Integer_Array);
|
||||
|
||||
procedure print_kth
|
||||
(less_than : access function
|
||||
(x, y : Integer)
|
||||
return Boolean;
|
||||
k : in Positive;
|
||||
i_first, i_last : in Integer;
|
||||
arr : in out Integer_Array)
|
||||
is
|
||||
copy_of_arr : Integer_Array (0 .. i_last);
|
||||
the_element : Integer;
|
||||
the_elements_index : Natural;
|
||||
begin
|
||||
for j in 0 .. i_last loop
|
||||
copy_of_arr (j) := arr (j);
|
||||
end loop;
|
||||
integer_quickselect
|
||||
(less_than, i_first, i_last, k - 1, copy_of_arr, the_element,
|
||||
the_elements_index);
|
||||
Put (Integer'Image (the_element));
|
||||
end print_kth;
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
example_numbers : Integer_Array := (9, 8, 7, 6, 5, 0, 1, 2, 3, 4);
|
||||
|
||||
function lt
|
||||
(x, y : Integer)
|
||||
return Boolean
|
||||
is
|
||||
begin
|
||||
return (x < y);
|
||||
end lt;
|
||||
|
||||
function gt
|
||||
(x, y : Integer)
|
||||
return Boolean
|
||||
is
|
||||
begin
|
||||
return (x > y);
|
||||
end gt;
|
||||
|
||||
begin
|
||||
Put ("With < as order predicate: ");
|
||||
for k in 1 .. 10 loop
|
||||
print_kth (lt'Access, k, 0, 9, example_numbers);
|
||||
end loop;
|
||||
Put_Line ("");
|
||||
Put ("With > as order predicate: ");
|
||||
for k in 1 .. 10 loop
|
||||
print_kth (gt'Access, k, 0, 9, example_numbers);
|
||||
end loop;
|
||||
Put_Line ("");
|
||||
end quickselect_task;
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
|
@ -7,13 +7,14 @@ quickselect: function [a k][
|
|||
left: select arr 'item -> item<pivot
|
||||
right: select arr 'item -> item>pivot
|
||||
|
||||
case [k]
|
||||
when? [= size left]-> return pivot
|
||||
when? [< size left]-> arr: new left
|
||||
else [
|
||||
when.has: k [
|
||||
[= size left] -> return pivot
|
||||
[< size left] -> arr: new left
|
||||
true [
|
||||
k: (k - size left) - 1
|
||||
arr: new right
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
int qselect(int *v, int len, int k)
|
||||
{
|
||||
# define SWAP(a, b) { tmp = v[a]; v[a] = v[b]; v[b] = tmp; }
|
||||
#define SWAP(a, b) { tmp = v[a]; v[a] = v[b]; v[b] = tmp; }
|
||||
int i, st, tmp;
|
||||
|
||||
for (st = i = 0; i < len - 1; i++) {
|
||||
|
|
@ -21,7 +21,7 @@ int qselect(int *v, int len, int k)
|
|||
|
||||
int main(void)
|
||||
{
|
||||
# define N (sizeof(x)/sizeof(x[0]))
|
||||
#define N (sizeof(x)/sizeof(x[0]))
|
||||
int x[] = {9, 8, 7, 6, 5, 0, 1, 2, 3, 4};
|
||||
int y[N];
|
||||
|
||||
|
|
|
|||
|
|
@ -1,95 +0,0 @@
|
|||
CLASS-ID MainProgram.
|
||||
|
||||
METHOD-ID Partition STATIC USING T.
|
||||
CONSTRAINTS.
|
||||
CONSTRAIN T IMPLEMENTS type IComparable.
|
||||
|
||||
DATA DIVISION.
|
||||
LOCAL-STORAGE SECTION.
|
||||
01 pivot-val T.
|
||||
|
||||
PROCEDURE DIVISION USING VALUE arr AS T OCCURS ANY,
|
||||
left-idx AS BINARY-LONG, right-idx AS BINARY-LONG,
|
||||
pivot-idx AS BINARY-LONG
|
||||
RETURNING ret AS BINARY-LONG.
|
||||
MOVE arr (pivot-idx) TO pivot-val
|
||||
INVOKE self::Swap(arr, pivot-idx, right-idx)
|
||||
DECLARE store-idx AS BINARY-LONG = left-idx
|
||||
PERFORM VARYING i AS BINARY-LONG FROM left-idx BY 1
|
||||
UNTIL i > right-idx
|
||||
IF arr (i) < pivot-val
|
||||
INVOKE self::Swap(arr, i, store-idx)
|
||||
ADD 1 TO store-idx
|
||||
END-IF
|
||||
END-PERFORM
|
||||
INVOKE self::Swap(arr, right-idx, store-idx)
|
||||
|
||||
MOVE store-idx TO ret
|
||||
END METHOD.
|
||||
|
||||
METHOD-ID Quickselect STATIC USING T.
|
||||
CONSTRAINTS.
|
||||
CONSTRAIN T IMPLEMENTS type IComparable.
|
||||
|
||||
PROCEDURE DIVISION USING VALUE arr AS T OCCURS ANY,
|
||||
left-idx AS BINARY-LONG, right-idx AS BINARY-LONG,
|
||||
n AS BINARY-LONG
|
||||
RETURNING ret AS T.
|
||||
IF left-idx = right-idx
|
||||
MOVE arr (left-idx) TO ret
|
||||
GOBACK
|
||||
END-IF
|
||||
|
||||
DECLARE rand AS TYPE Random = NEW Random()
|
||||
DECLARE pivot-idx AS BINARY-LONG = rand::Next(left-idx, right-idx)
|
||||
DECLARE pivot-new-idx AS BINARY-LONG
|
||||
= self::Partition(arr, left-idx, right-idx, pivot-idx)
|
||||
DECLARE pivot-dist AS BINARY-LONG = pivot-new-idx - left-idx + 1
|
||||
|
||||
EVALUATE TRUE
|
||||
WHEN pivot-dist = n
|
||||
MOVE arr (pivot-new-idx) TO ret
|
||||
|
||||
WHEN n < pivot-dist
|
||||
INVOKE self::Quickselect(arr, left-idx, pivot-new-idx - 1, n)
|
||||
RETURNING ret
|
||||
|
||||
WHEN OTHER
|
||||
INVOKE self::Quickselect(arr, pivot-new-idx + 1, right-idx,
|
||||
n - pivot-dist) RETURNING ret
|
||||
END-EVALUATE
|
||||
END METHOD.
|
||||
|
||||
METHOD-ID Swap STATIC USING T.
|
||||
CONSTRAINTS.
|
||||
CONSTRAIN T IMPLEMENTS type IComparable.
|
||||
|
||||
DATA DIVISION.
|
||||
LOCAL-STORAGE SECTION.
|
||||
01 temp T.
|
||||
|
||||
PROCEDURE DIVISION USING arr AS T OCCURS ANY,
|
||||
VALUE idx-1 AS BINARY-LONG, idx-2 AS BINARY-LONG.
|
||||
IF idx-1 <> idx-2
|
||||
MOVE arr (idx-1) TO temp
|
||||
MOVE arr (idx-2) TO arr (idx-1)
|
||||
MOVE temp TO arr (idx-2)
|
||||
END-IF
|
||||
END METHOD.
|
||||
|
||||
METHOD-ID Main STATIC.
|
||||
PROCEDURE DIVISION.
|
||||
DECLARE input-array AS BINARY-LONG OCCURS ANY
|
||||
= TABLE OF BINARY-LONG(9, 8, 7, 6, 5, 0, 1, 2, 3, 4)
|
||||
DISPLAY "Loop quick select 10 times."
|
||||
PERFORM VARYING i AS BINARY-LONG FROM 1 BY 1 UNTIL i > 10
|
||||
DISPLAY self::Quickselect(input-array, 1, input-array::Length, i)
|
||||
NO ADVANCING
|
||||
|
||||
IF i < 10
|
||||
DISPLAY ", " NO ADVANCING
|
||||
END-IF
|
||||
END-PERFORM
|
||||
DISPLAY SPACE
|
||||
END METHOD.
|
||||
END CLASS.
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
function partition($list, $left, $right, $pivotIndex) {
|
||||
$pivotValue = $list[$pivotIndex]
|
||||
$list[$pivotIndex], $list[$right] = $list[$right], $list[$pivotIndex]
|
||||
$storeIndex = $left
|
||||
foreach ($i in $left..($right-1)) {
|
||||
if ($list[$i] -lt $pivotValue) {
|
||||
$list[$storeIndex],$list[$i] = $list[$i], $list[$storeIndex]
|
||||
$storeIndex += 1
|
||||
}
|
||||
}
|
||||
$list[$right],$list[$storeIndex] = $list[$storeIndex], $list[$right]
|
||||
$storeIndex
|
||||
}
|
||||
|
||||
function rank($list, $left, $right, $n) {
|
||||
if ($left -eq $right) {$list[$left]}
|
||||
else {
|
||||
$pivotIndex = Get-Random -Minimum $left -Maximum $right
|
||||
$pivotIndex = partition $list $left $right $pivotIndex
|
||||
if ($n -eq $pivotIndex) {$list[$n]}
|
||||
elseif ($n -lt $pivotIndex) {(rank $list $left ($pivotIndex - 1) $n)}
|
||||
else {(rank $list ($pivotIndex+1) $right $n)}
|
||||
}
|
||||
}
|
||||
|
||||
function quickselect($list) {
|
||||
$right = $list.count-1
|
||||
foreach($left in 0..$right) {rank $list $left $right $left}
|
||||
}
|
||||
$arr = @(9, 8, 7, 6, 5, 0, 1, 2, 3, 4)
|
||||
"$(quickselect $arr)"
|
||||
Loading…
Add table
Add a link
Reference in a new issue