Initial data commit

This commit is contained in:
Ingy döt Net 2023-07-01 11:58:00 -04:00
parent 72d218235f
commit f23f22d71c
199087 changed files with 3378941 additions and 0 deletions

View file

@ -0,0 +1,3 @@
---
from: http://rosettacode.org/wiki/Sorting_algorithms/Quicksort
note: Sorting Algorithms

View file

@ -0,0 +1,79 @@
{{Sorting Algorithm}}
[[Category:Sorting]]
[[Category:Recursion]]
{{Wikipedia|Quicksort}}
;Task:
Sort an array (or list) elements using the   [https://en.wikipedia.org/wiki/Quicksort ''quicksort'']   algorithm.
The elements must have a   [https://en.wikipedia.org/wiki/Weak_ordering strict weak order]   and the index of the array can be of any discrete type.
For languages where this is not possible, sort an array of integers.
Quicksort, also known as   ''partition-exchange sort'',   uses these steps.
::#   Choose any element of the array to be the pivot.
::#   Divide all other elements (except the pivot) into two partitions.
::#*   All elements less than the pivot must be in the first partition.
::#*   All elements greater than the pivot must be in the second partition.
::#   Use recursion to sort both partitions.
::#   Join the first sorted partition, the pivot, and the second sorted partition.
<br>
The best pivot creates partitions of equal length (or lengths differing by &nbsp; '''1''').
The worst pivot creates an empty partition (for example, if the pivot is the first or last element of a sorted array).
The run-time of Quicksort ranges from &nbsp; <big> ''[[O]](n ''log'' n)'' </big> &nbsp; with the best pivots, to &nbsp; <big> ''[[O]](n<sup>2</sup>)'' </big> &nbsp; with the worst pivots, where &nbsp; <big> ''n'' </big> &nbsp; is the number of elements in the array.
This is a simple quicksort algorithm, adapted from Wikipedia.
'''function''' ''quicksort''(array)
less, equal, greater ''':=''' three empty arrays
'''if''' length(array) > 1
pivot ''':=''' ''select any element of'' array
'''for each''' x '''in''' array
'''if''' x < pivot '''then add''' x '''to''' less
'''if''' x = pivot '''then add''' x '''to''' equal
'''if''' x > pivot '''then add''' x '''to''' greater
quicksort(less)
quicksort(greater)
array ''':=''' concatenate(less, equal, greater)
A better quicksort algorithm works in place, by swapping elements within the array, to avoid the memory allocation of more arrays.
'''function''' ''quicksort''(array)
'''if''' length(array) > 1
pivot ''':=''' ''select any element of'' array
left ''':= first index of''' array
right ''':=''' '''last index of''' array
'''while''' left ≤ right
'''while''' array[left] < pivot
left := left + 1
'''while''' array[right] > pivot
right := right - 1
'''if''' left ≤ right
'''swap''' array[left] '''with''' array[right]
left := left + 1
right := right - 1
quicksort(array '''from first index to''' right)
quicksort(array '''from''' left '''to last index''')
Quicksort has a reputation as the fastest sort. Optimized variants of quicksort are common features of many languages and libraries. One often contrasts quicksort with &nbsp; [[../Merge sort|merge sort]], &nbsp; because both sorts have an average time of &nbsp; <big> ''[[O]](n ''log'' n)''. </big>
: ''"On average, mergesort does fewer comparisons than quicksort, so it may be better when complicated comparison routines are used. Mergesort also takes advantage of pre-existing order, so it would be favored for using sort() to merge several sorted arrays. On the other hand, quicksort is often faster for small arrays, and on arrays of a few distinct values, repeated many times."'' — http://perldoc.perl.org/sort.html
Quicksort is at one end of the spectrum of divide-and-conquer algorithms, with merge sort at the opposite end.
* Quicksort is a conquer-then-divide algorithm, which does most of the work during the partitioning and the recursive calls. The subsequent reassembly of the sorted partitions involves trivial effort.
* Merge sort is a divide-then-conquer algorithm. The partioning happens in a trivial way, by splitting the input array in half. Most of the work happens during the recursive calls and the merge phase.
<br>
With quicksort, every element in the first partition is less than or equal to every element in the second partition. Therefore, the merge phase of quicksort is so trivial that it needs no mention!
This task has not specified whether to allocate new arrays, or sort in place. This task also has not specified how to choose the pivot element. (Common ways to are to choose the first element, the middle element, or the median of three elements.) Thus there is a variety among the following implementations.
<br><br>

View file

@ -0,0 +1,23 @@
F _quicksort(&array, start, stop) -> N
I stop - start > 0
V pivot = array[start]
V left = start
V right = stop
L left <= right
L array[left] < pivot
left++
L array[right] > pivot
right--
I left <= right
swap(&array[left], &array[right])
left++
right--
_quicksort(&array, start, right)
_quicksort(&array, left, stop)
F quicksort(&array)
_quicksort(&array, 0, array.len - 1)
V arr = [7, 6, 5, 9, 8, 4, 3, 1, 2, 0]
quicksort(&arr)
print(arr)

View file

@ -0,0 +1,172 @@
* Quicksort 14/09/2015 & 23/06/2016
QUICKSOR CSECT
USING QUICKSOR,R13 base register
B 72(R15) skip savearea
DC 17F'0' savearea
STM R14,R12,12(R13) prolog
ST R13,4(R15) "
ST R15,8(R13) "
LR R13,R15 "
MVC A,=A(1) a(1)=1
MVC B,=A(NN) b(1)=hbound(t)
L R6,=F'1' k=1
DO WHILE=(LTR,R6,NZ,R6) do while k<>0 ==================
LR R1,R6 k
SLA R1,2 ~
L R10,A-4(R1) l=a(k)
LR R1,R6 k
SLA R1,2 ~
L R11,B-4(R1) m=b(k)
BCTR R6,0 k=k-1
LR R4,R11 m
C R4,=F'2' if m<2
BL ITERATE then iterate
LR R2,R10 l
AR R2,R11 +m
BCTR R2,0 -1
ST R2,X x=l+m-1
LR R2,R11 m
SRA R2,1 m/2
AR R2,R10 +l
ST R2,Y y=l+m/2
L R1,X x
SLA R1,2 ~
L R4,T-4(R1) r4=t(x)
L R1,Y y
SLA R1,2 ~
L R5,T-4(R1) r5=t(y)
LR R1,R10 l
SLA R1,2 ~
L R3,T-4(R1) r3=t(l)
IF CR,R4,LT,R3 if t(x)<t(l) ---+
IF CR,R5,LT,R4 if t(y)<t(x) |
LR R7,R4 p=t(x) |
L R1,X x |
SLA R1,2 ~ |
ST R3,T-4(R1) t(x)=t(l) |
ELSEIF CR,R5,GT,R3 elseif t(y)>t(l) |
LR R7,R3 p=t(l) |
ELSE , else |
LR R7,R5 p=t(y) |
L R1,Y y |
SLA R1,2 ~ |
ST R3,T-4(R1) t(y)=t(l) |
ENDIF , end if |
ELSE , else |
IF CR,R5,LT,R3 if t(y)<t(l) |
LR R7,R3 p=t(l) |
ELSEIF CR,R5,GT,R4 elseif t(y)>t(x) |
LR R7,R4 p=t(x) |
L R1,X x |
SLA R1,2 ~ |
ST R3,T-4(R1) t(x)=t(l) |
ELSE , else |
LR R7,R5 p=t(y) |
L R1,Y y |
SLA R1,2 ~ |
ST R3,T-4(R1) t(y)=t(l) |
ENDIF , end if |
ENDIF , end if ---+
LA R8,1(R10) i=l+1
L R9,X j=x
FOREVER EQU * do forever --------------------+
LR R1,R8 i |
SLA R1,2 ~ |
LA R2,T-4(R1) @t(i) |
L R0,0(R2) t(i) |
DO WHILE=(CR,R8,LE,R9,AND, while i<=j and ---+ | X
CR,R0,LE,R7) t(i)<=p | |
AH R8,=H'1' i=i+1 | |
AH R2,=H'4' @t(i) | |
L R0,0(R2) t(i) | |
ENDDO , end while ---+ |
LR R1,R9 j |
SLA R1,2 ~ |
LA R2,T-4(R1) @t(j) |
L R0,0(R2) t(j) |
DO WHILE=(CR,R8,LT,R9,AND, while i<j and ---+ | X
CR,R0,GE,R7) t(j)>=p | |
SH R9,=H'1' j=j-1 | |
SH R2,=H'4' @t(j) | |
L R0,0(R2) t(j) | |
ENDDO , end while ---+ |
CR R8,R9 if i>=j |
BNL LEAVE then leave (segment finished) |
LR R1,R8 i |
SLA R1,2 ~ |
LA R2,T-4(R1) @t(i) |
LR R1,R9 j |
SLA R1,2 ~ |
LA R3,T-4(R1) @t(j) |
L R0,0(R2) w=t(i) + |
MVC 0(4,R2),0(R3) t(i)=t(j) |swap t(i),t(j) |
ST R0,0(R3) t(j)=w + |
B FOREVER end do forever ----------------+
LEAVE EQU *
LR R9,R8 j=i
BCTR R9,0 j=i-1
LR R1,R9 j
SLA R1,2 ~
LA R3,T-4(R1) @t(j)
L R2,0(R3) t(j)
LR R1,R10 l
SLA R1,2 ~
ST R2,T-4(R1) t(l)=t(j)
ST R7,0(R3) t(j)=p
LA R6,1(R6) k=k+1
LR R1,R6 k
SLA R1,2 ~
LA R4,A-4(R1) r4=@a(k)
LA R5,B-4(R1) r5=@b(k)
IF C,R8,LE,Y if i<=y ----+
ST R8,0(R4) a(k)=i |
L R2,X x |
SR R2,R8 -i |
LA R2,1(R2) +1 |
ST R2,0(R5) b(k)=x-i+1 |
LA R6,1(R6) k=k+1 |
ST R10,4(R4) a(k)=l |
LR R2,R9 j |
SR R2,R10 -l |
ST R2,4(R5) b(k)=j-l |
ELSE , else |
ST R10,4(R4) a(k)=l |
LR R2,R9 j |
SR R2,R10 -l |
ST R2,0(R5) b(k)=j-l |
LA R6,1(R6) k=k+1 |
ST R8,4(R4) a(k)=i |
L R2,X x |
SR R2,R8 -i |
LA R2,1(R2) +1 |
ST R2,4(R5) b(k)=x-i+1 |
ENDIF , end if ----+
ITERATE EQU *
ENDDO , end while =====================
* *** ********* print sorted table
LA R3,PG ibuffer
LA R4,T @t(i)
DO WHILE=(C,R4,LE,=A(TEND)) do i=1 to hbound(t)
L R2,0(R4) t(i)
XDECO R2,XD edit t(i)
MVC 0(4,R3),XD+8 put in buffer
LA R3,4(R3) ibuffer=ibuffer+1
LA R4,4(R4) i=i+1
ENDDO , end do
XPRNT PG,80 print buffer
L R13,4(0,R13) epilog
LM R14,R12,12(R13) "
XR R15,R15 "
BR R14 exit
T DC F'10',F'9',F'9',F'6',F'7',F'16',F'1',F'16',F'17',F'15'
DC F'1',F'9',F'18',F'16',F'8',F'20',F'18',F'2',F'19',F'8'
TEND DS 0F
NN EQU (TEND-T)/4)
A DS (NN)F same size as T
B DS (NN)F same size as T
X DS F
Y DS F
PG DS CL80
XD DS CL12
YREGS
END QUICKSOR

View file

@ -0,0 +1,189 @@
/* ARM assembly AARCH64 Raspberry PI 3B */
/* program quickSort64.s */
/*******************************************/
/* Constantes file */
/*******************************************/
/* for this file see task include a file in language AArch64 assembly */
.include "../includeConstantesARM64.inc"
/*********************************/
/* Initialized data */
/*********************************/
.data
szMessSortOk: .asciz "Table sorted.\n"
szMessSortNok: .asciz "Table not sorted !!!!!.\n"
sMessResult: .asciz "Value : @ \n"
szCarriageReturn: .asciz "\n"
.align 4
TableNumber: .quad 1,3,6,2,5,9,10,8,4,7,11
#TableNumber: .quad 10,9,8,7,6,-5,4,3,2,1
.equ NBELEMENTS, (. - TableNumber) / 8
/*********************************/
/* UnInitialized data */
/*********************************/
.bss
sZoneConv: .skip 24
/*********************************/
/* code section */
/*********************************/
.text
.global main
main: // entry of program
ldr x0,qAdrTableNumber // address number table
mov x1,0 // first element
mov x2,NBELEMENTS // number of élements
bl quickSort
ldr x0,qAdrTableNumber // address number table
bl displayTable
ldr x0,qAdrTableNumber // address number table
mov x1,NBELEMENTS // number of élements
bl isSorted // control sort
cmp x0,1 // sorted ?
beq 1f
ldr x0,qAdrszMessSortNok // no !! error sort
bl affichageMess
b 100f
1: // yes
ldr x0,qAdrszMessSortOk
bl affichageMess
100: // standard end of the program
mov x0,0 // return code
mov x8,EXIT // request to exit program
svc 0 // perform the system call
qAdrsZoneConv: .quad sZoneConv
qAdrszCarriageReturn: .quad szCarriageReturn
qAdrsMessResult: .quad sMessResult
qAdrTableNumber: .quad TableNumber
qAdrszMessSortOk: .quad szMessSortOk
qAdrszMessSortNok: .quad szMessSortNok
/******************************************************************/
/* control sorted table */
/******************************************************************/
/* x0 contains the address of table */
/* x1 contains the number of elements > 0 */
/* x0 return 0 if not sorted 1 if sorted */
isSorted:
stp x2,lr,[sp,-16]! // save registers
stp x3,x4,[sp,-16]! // save registers
mov x2,0
ldr x4,[x0,x2,lsl 3]
1:
add x2,x2,1
cmp x2,x1
bge 99f
ldr x3,[x0,x2, lsl 3]
cmp x3,x4
blt 98f
mov x4,x3
b 1b
98:
mov x0,0 // not sorted
b 100f
99:
mov x0,1 // sorted
100:
ldp x3,x4,[sp],16 // restaur 2 registers
ldp x2,lr,[sp],16 // restaur 2 registers
ret // return to address lr x30
/***************************************************/
/* Appel récursif Tri Rapide quicksort */
/***************************************************/
/* x0 contains the address of table */
/* x1 contains index of first item */
/* x2 contains the number of elements > 0 */
quickSort:
stp x2,lr,[sp,-16]! // save registers
stp x3,x4,[sp,-16]! // save registers
str x5, [sp,-16]! // save registers
sub x2,x2,1 // last item index
cmp x1,x2 // first > last ?
bge 100f // yes -> end
mov x4,x0 // save x0
mov x5,x2 // save x2
bl partition1 // cutting into 2 parts
mov x2,x0 // index partition
mov x0,x4 // table address
bl quickSort // sort lower part
add x1,x2,1 // index begin = index partition + 1
add x2,x5,1 // number of elements
bl quickSort // sort higter part
100: // end function
ldr x5, [sp],16 // restaur 1 register
ldp x3,x4,[sp],16 // restaur 2 registers
ldp x2,lr,[sp],16 // restaur 2 registers
ret // return to address lr x30
/******************************************************************/
/* Partition table elements */
/******************************************************************/
/* x0 contains the address of table */
/* x1 contains index of first item */
/* x2 contains index of last item */
partition1:
stp x1,lr,[sp,-16]! // save registers
stp x2,x3,[sp,-16]! // save registers
stp x4,x5,[sp,-16]! // save registers
stp x6,x7,[sp,-16]! // save registers
ldr x3,[x0,x2,lsl 3] // load value last index
mov x4,x1 // init with first index
mov x5,x1 // init with first index
1: // begin loop
ldr x6,[x0,x5,lsl 3] // load value
cmp x6,x3 // compare value
bge 2f
ldr x7,[x0,x4,lsl 3] // if < swap value table
str x6,[x0,x4,lsl 3]
str x7,[x0,x5,lsl 3]
add x4,x4,1 // and increment index 1
2:
add x5,x5,1 // increment index 2
cmp x5,x2 // end ?
blt 1b // no loop
ldr x7,[x0,x4,lsl 3] // swap value
str x3,[x0,x4,lsl 3]
str x7,[x0,x2,lsl 3]
mov x0,x4 // return index partition
100:
ldp x6,x7,[sp],16 // restaur 2 registers
ldp x4,x5,[sp],16 // restaur 2 registers
ldp x2,x3,[sp],16 // restaur 2 registers
ldp x1,lr,[sp],16 // restaur 2 registers
ret // return to address lr x30
/******************************************************************/
/* Display table elements */
/******************************************************************/
/* x0 contains the address of table */
displayTable:
stp x1,lr,[sp,-16]! // save registers
stp x2,x3,[sp,-16]! // save registers
mov x2,x0 // table address
mov x3,0
1: // loop display table
ldr x0,[x2,x3,lsl 3]
ldr x1,qAdrsZoneConv
bl conversion10S // décimal conversion
ldr x0,qAdrsMessResult
ldr x1,qAdrsZoneConv
bl strInsertAtCharInc // insert result at // character
bl affichageMess // display message
add x3,x3,1
cmp x3,NBELEMENTS - 1
ble 1b
ldr x0,qAdrszCarriageReturn
bl affichageMess
mov x0,x2
100:
ldp x2,x3,[sp],16 // restaur 2 registers
ldp x1,lr,[sp],16 // restaur 2 registers
ret // return to address lr x30
/********************************************************/
/* File Include fonctions */
/********************************************************/
/* for this file see task include a file in language AArch64 assembly */
.include "../includeARM64.inc"

View file

@ -0,0 +1,38 @@
report z_quicksort.
data(numbers) = value int4_table( ( 4 ) ( 65 ) ( 2 ) ( -31 ) ( 0 ) ( 99 ) ( 2 ) ( 83 ) ( 782 ) ( 1 ) ).
perform quicksort changing numbers.
write `[`.
loop at numbers assigning field-symbol(<numbers>).
write <numbers>.
endloop.
write `]`.
form quicksort changing numbers type int4_table.
data(less) = value int4_table( ).
data(equal) = value int4_table( ).
data(greater) = value int4_table( ).
if lines( numbers ) > 1.
data(pivot) = numbers[ lines( numbers ) / 2 ].
loop at numbers assigning field-symbol(<number>).
if <number> < pivot.
append <number> to less.
elseif <number> = pivot.
append <number> to equal.
elseif <number> > pivot.
append <number> to greater.
endif.
endloop.
perform quicksort changing less.
perform quicksort changing greater.
clear numbers.
append lines of less to numbers.
append lines of equal to numbers.
append lines of greater to numbers.
endif.
endform.

View file

@ -0,0 +1,17 @@
(defun partition (p xs)
(if (endp xs)
(mv nil nil)
(mv-let (less more)
(partition p (rest xs))
(if (< (first xs) p)
(mv (cons (first xs) less) more)
(mv less (cons (first xs) more))))))
(defun qsort (xs)
(if (endp xs)
nil
(mv-let (less more)
(partition (first xs) (rest xs))
(append (qsort less)
(list (first xs))
(qsort more)))))

View file

@ -0,0 +1,2 @@
> (qsort '(8 6 7 5 3 0 9))
(0 3 5 6 7 8 9)

View file

@ -0,0 +1,62 @@
#--- Swap function ---#
PROC swap = (REF []INT array, INT first, INT second) VOID:
(
INT temp := array[first];
array[first] := array[second];
array[second]:= temp
);
#--- Quick sort 3 arg function ---#
PROC quick = (REF [] INT array, INT first, INT last) VOID:
(
INT smaller := first + 1,
larger := last,
pivot := array[first];
WHILE smaller <= larger DO
WHILE array[smaller] < pivot AND smaller < last DO
smaller +:= 1
OD;
WHILE array[larger] > pivot AND larger > first DO
larger -:= 1
OD;
IF smaller < larger THEN
swap(array, smaller, larger);
smaller +:= 1;
larger -:= 1
ELSE
smaller +:= 1
FI
OD;
swap(array, first, larger);
IF first < larger-1 THEN
quick(array, first, larger-1)
FI;
IF last > larger +1 THEN
quick(array, larger+1, last)
FI
);
#--- Quick sort 1 arg function ---#
PROC quicksort = (REF []INT array) VOID:
(
IF UPB array > 1 THEN
quick(array, 1, UPB array)
FI
);
#***************************************************************#
main:
(
[10]INT a;
FOR i FROM 1 TO UPB a DO
a[i] := ROUND(random*1000)
OD;
print(("Before:", a));
quicksort(a);
print((newline, newline));
print(("After: ", a))
)

View file

@ -0,0 +1,26 @@
% Quicksorts in-place the array of integers v, from lb to ub %
procedure quicksort ( integer array v( * )
; integer value lb, ub
) ;
if ub > lb then begin
% more than one element, so must sort %
integer left, right, pivot;
left := lb;
right := ub;
% choosing the middle element of the array as the pivot %
pivot := v( left + ( ( right + 1 ) - left ) div 2 );
while begin
while left <= ub and v( left ) < pivot do left := left + 1;
while right >= lb and v( right ) > pivot do right := right - 1;
left <= right
end do begin
integer swap;
swap := v( left );
v( left ) := v( right );
v( right ) := swap;
left := left + 1;
right := right - 1
end while_left_le_right ;
quicksort( v, lb, right );
quicksort( v, left, ub )
end quicksort ;

View file

@ -0,0 +1,3 @@
qsort {1: e[?] ((<e)/) , ((=e)/) , ((>e)/)}
qsort 31 4 1 5 9 2 6 5 3 5 8
1 2 3 4 5 5 5 6 8 9 31

View file

@ -0,0 +1,3 @@
sort {[]}
sort 31 4 1 5 9 2 6 5 3 5 8
1 2 3 4 5 5 5 6 8 9 31

View file

@ -0,0 +1,254 @@
/* ARM assembly Raspberry PI */
/* program quickSort.s */
/* look pseudo code in wikipedia quicksort */
/************************************/
/* Constantes */
/************************************/
.equ STDOUT, 1 @ Linux output console
.equ EXIT, 1 @ Linux syscall
.equ WRITE, 4 @ Linux syscall
/*********************************/
/* Initialized data */
/*********************************/
.data
szMessSortOk: .asciz "Table sorted.\n"
szMessSortNok: .asciz "Table not sorted !!!!!.\n"
sMessResult: .ascii "Value : "
sMessValeur: .fill 11, 1, ' ' @ size => 11
szCarriageReturn: .asciz "\n"
.align 4
iGraine: .int 123456
.equ NBELEMENTS, 10
#TableNumber: .int 9,5,6,1,2,3,10,8,4,7
#TableNumber: .int 1,3,5,2,4,6,10,8,4,7
#TableNumber: .int 1,3,5,2,4,6,10,8,4,7
#TableNumber: .int 1,2,3,4,5,6,10,8,4,7
TableNumber: .int 10,9,8,7,6,5,4,3,2,1
#TableNumber: .int 13,12,11,10,9,8,7,6,5,4,3,2,1
/*********************************/
/* UnInitialized data */
/*********************************/
.bss
/*********************************/
/* code section */
/*********************************/
.text
.global main
main: @ entry of program
1:
ldr r0,iAdrTableNumber @ address number table
mov r1,#0 @ indice first item
mov r2,#NBELEMENTS @ number of élements
bl triRapide @ call quicksort
ldr r0,iAdrTableNumber @ address number table
bl displayTable
ldr r0,iAdrTableNumber @ address number table
mov r1,#NBELEMENTS @ number of élements
bl isSorted @ control sort
cmp r0,#1 @ sorted ?
beq 2f
ldr r0,iAdrszMessSortNok @ no !! error sort
bl affichageMess
b 100f
2: @ yes
ldr r0,iAdrszMessSortOk
bl affichageMess
100: @ standard end of the program
mov r0, #0 @ return code
mov r7, #EXIT @ request to exit program
svc #0 @ perform the system call
iAdrsMessValeur: .int sMessValeur
iAdrszCarriageReturn: .int szCarriageReturn
iAdrsMessResult: .int sMessResult
iAdrTableNumber: .int TableNumber
iAdrszMessSortOk: .int szMessSortOk
iAdrszMessSortNok: .int szMessSortNok
/******************************************************************/
/* control sorted table */
/******************************************************************/
/* r0 contains the address of table */
/* r1 contains the number of elements > 0 */
/* r0 return 0 if not sorted 1 if sorted */
isSorted:
push {r2-r4,lr} @ save registers
mov r2,#0
ldr r4,[r0,r2,lsl #2]
1:
add r2,#1
cmp r2,r1
movge r0,#1
bge 100f
ldr r3,[r0,r2, lsl #2]
cmp r3,r4
movlt r0,#0
blt 100f
mov r4,r3
b 1b
100:
pop {r2-r4,lr}
bx lr @ return
/***************************************************/
/* Appel récursif Tri Rapide quicksort */
/***************************************************/
/* r0 contains the address of table */
/* r1 contains index of first item */
/* r2 contains the number of elements > 0 */
triRapide:
push {r2-r5,lr} @ save registers
sub r2,#1 @ last item index
cmp r1,r2 @ first > last ?
bge 100f @ yes -> end
mov r4,r0 @ save r0
mov r5,r2 @ save r2
bl partition1 @ cutting into 2 parts
mov r2,r0 @ index partition
mov r0,r4 @ table address
bl triRapide @ sort lower part
add r1,r2,#1 @ index begin = index partition + 1
add r2,r5,#1 @ number of elements
bl triRapide @ sort higter part
100: @ end function
pop {r2-r5,lr} @ restaur registers
bx lr @ return
/******************************************************************/
/* Partition table elements */
/******************************************************************/
/* r0 contains the address of table */
/* r1 contains index of first item */
/* r2 contains index of last item */
partition1:
push {r1-r7,lr} @ save registers
ldr r3,[r0,r2,lsl #2] @ load value last index
mov r4,r1 @ init with first index
mov r5,r1 @ init with first index
1: @ begin loop
ldr r6,[r0,r5,lsl #2] @ load value
cmp r6,r3 @ compare value
ldrlt r7,[r0,r4,lsl #2] @ if < swap value table
strlt r6,[r0,r4,lsl #2]
strlt r7,[r0,r5,lsl #2]
addlt r4,#1 @ and increment index 1
add r5,#1 @ increment index 2
cmp r5,r2 @ end ?
blt 1b @ no loop
ldr r7,[r0,r4,lsl #2] @ swap value
str r3,[r0,r4,lsl #2]
str r7,[r0,r2,lsl #2]
mov r0,r4 @ return index partition
100:
pop {r1-r7,lr}
bx lr
/******************************************************************/
/* Display table elements */
/******************************************************************/
/* r0 contains the address of table */
displayTable:
push {r0-r3,lr} @ save registers
mov r2,r0 @ table address
mov r3,#0
1: @ loop display table
ldr r0,[r2,r3,lsl #2]
ldr r1,iAdrsMessValeur @ display value
bl conversion10 @ call function
ldr r0,iAdrsMessResult
bl affichageMess @ display message
add r3,#1
cmp r3,#NBELEMENTS - 1
ble 1b
ldr r0,iAdrszCarriageReturn
bl affichageMess
100:
pop {r0-r3,lr}
bx lr
/******************************************************************/
/* display text with size calculation */
/******************************************************************/
/* r0 contains the address of the message */
affichageMess:
push {r0,r1,r2,r7,lr} @ save registres
mov r2,#0 @ counter length
1: @ loop length calculation
ldrb r1,[r0,r2] @ read octet start position + index
cmp r1,#0 @ if 0 its over
addne r2,r2,#1 @ else add 1 in the length
bne 1b @ and loop
@ so here r2 contains the length of the message
mov r1,r0 @ address message in r1
mov r0,#STDOUT @ code to write to the standard output Linux
mov r7, #WRITE @ code call system "write"
svc #0 @ call systeme
pop {r0,r1,r2,r7,lr} @ restaur des 2 registres */
bx lr @ return
/******************************************************************/
/* Converting a register to a decimal unsigned */
/******************************************************************/
/* r0 contains value and r1 address area */
/* r0 return size of result (no zero final in area) */
/* area size => 11 bytes */
.equ LGZONECAL, 10
conversion10:
push {r1-r4,lr} @ save registers
mov r3,r1
mov r2,#LGZONECAL
1: @ start loop
bl divisionpar10U @ unsigned r0 <- dividende. quotient ->r0 reste -> r1
add r1,#48 @ digit
strb r1,[r3,r2] @ store digit on area
cmp r0,#0 @ stop if quotient = 0
subne r2,#1 @ else previous position
bne 1b @ and loop
@ and move digit from left of area
mov r4,#0
2:
ldrb r1,[r3,r2]
strb r1,[r3,r4]
add r2,#1
add r4,#1
cmp r2,#LGZONECAL
ble 2b
@ and move spaces in end on area
mov r0,r4 @ result length
mov r1,#' ' @ space
3:
strb r1,[r3,r4] @ store space in area
add r4,#1 @ next position
cmp r4,#LGZONECAL
ble 3b @ loop if r4 <= area size
100:
pop {r1-r4,lr} @ restaur registres
bx lr @return
/***************************************************/
/* division par 10 unsigned */
/***************************************************/
/* r0 dividende */
/* r0 quotient */
/* r1 remainder */
divisionpar10U:
push {r2,r3,r4, lr}
mov r4,r0 @ save value
//mov r3,#0xCCCD @ r3 <- magic_number lower raspberry 3
//movt r3,#0xCCCC @ r3 <- magic_number higter raspberry 3
ldr r3,iMagicNumber @ r3 <- magic_number raspberry 1 2
umull r1, r2, r3, r0 @ r1<- Lower32Bits(r1*r0) r2<- Upper32Bits(r1*r0)
mov r0, r2, LSR #3 @ r2 <- r2 >> shift 3
add r2,r0,r0, lsl #2 @ r2 <- r0 * 5
sub r1,r4,r2, lsl #1 @ r1 <- r4 - (r2 * 2) = r4 - (r0 * 10)
pop {r2,r3,r4,lr}
bx lr @ leave function
iMagicNumber: .int 0xCCCCCCCD

View file

@ -0,0 +1,153 @@
(*------------------------------------------------------------------*)
(* Quicksort in ATS2, for non-linear lists. *)
(*------------------------------------------------------------------*)
#include "share/atspre_staload.hats"
#define NIL list_nil ()
#define :: list_cons
(*------------------------------------------------------------------*)
(* A simple quicksort working on "garbage-collected" linked lists,
with first element as pivot. This is meant as a demonstration, not
as a superior sort algorithm.
It is based on the "not-in-place" task pseudocode. *)
datatype comparison_result =
| first_is_less_than_second of ()
| first_is_equal_to_second of ()
| first_is_greater_than_second of ()
extern fun {a : t@ype}
list_quicksort$comparison (x : a, y : a) :<> comparison_result
extern fun {a : t@ype}
list_quicksort {n : int}
(lst : list (a, n)) :<> list (a, n)
(* - - - - - - - - - - - - - - - - - - - - - - *)
implement {a}
list_quicksort {n} (lst) =
let
fun
partition {n : nat}
.<n>. (* Proof of termination. *)
(lst : list (a, n),
pivot : a)
:<> [n1, n2, n3 : int | n1 + n2 + n3 == n]
@(list (a, n1), list (a, n2), list (a, n3)) =
(* This implementation is *not* tail recursive. I may get a
scolding for using ATS to risk stack overflow! However, I
need more practice writing non-tail routines. :) Also, a lot
of programmers in other languages would do it this
way--especially if the lists are evaluated lazily. *)
case+ lst of
| NIL => @(NIL, NIL, NIL)
| head :: tail =>
let
val @(lt, eq, gt) = partition (tail, pivot)
prval () = lemma_list_param lt
prval () = lemma_list_param eq
prval () = lemma_list_param gt
in
case+ list_quicksort$comparison<a> (head, pivot) of
| first_is_less_than_second () => @(head :: lt, eq, gt)
| first_is_equal_to_second () => @(lt, head :: eq, gt)
| first_is_greater_than_second () => @(lt, eq, head :: gt)
end
fun
quicksort {n : nat}
.<n>. (* Proof of termination. *)
(lst : list (a, n))
:<> list (a, n) =
case+ lst of
| NIL => lst
| _ :: NIL => lst
| head :: tail =>
let
(* We are careful here to run "partition" on "tail" rather
than "lst", so the termination metric will be provably
decreasing. (Really the compiler *forces* us to take such
care, or else to change :<> to :<!ntm>) *)
val pivot = head
prval () = lemma_list_param tail
val @(lt, eq, gt) = partition {n - 1} (tail, pivot)
prval () = lemma_list_param lt
prval () = lemma_list_param eq
prval () = lemma_list_param gt
val eq = pivot :: eq
and lt = quicksort lt
and gt = quicksort gt
in
lt + (eq + gt)
end
prval () = lemma_list_param lst
in
quicksort {n} lst
end
(*------------------------------------------------------------------*)
val example_strings =
$list ("choose", "any", "element", "of", "the", "array",
"to", "be", "the", "pivot",
"divide", "all", "other", "elements", "except",
"the", "pivot", "into", "two", "partitions",
"all", "elements", "less", "than", "the", "pivot",
"must", "be", "in", "the", "first", "partition",
"all", "elements", "greater", "than", "the", "pivot",
"must", "be", "in", "the", "second", "partition",
"use", "recursion", "to", "sort", "both", "partitions",
"join", "the", "first", "sorted", "partition", "the",
"pivot", "and", "the", "second", "sorted", "partition")
implement
list_quicksort$comparison<string> (x, y) =
let
val i = strcmp (x, y)
in
if i < 0 then
first_is_less_than_second
else if i = 0 then
first_is_equal_to_second
else
first_is_greater_than_second
end
implement
main0 () =
let
val sorted_strings = list_quicksort<string> example_strings
fun
print_strings {n : nat} .<n>.
(strings : list (string, n),
i : int) : void =
case+ strings of
| NIL => if i <> 1 then println! () else ()
| head :: tail =>
begin
print! head;
if i = 8 then
begin
println! ();
print_strings (tail, 1)
end
else
begin
print! " ";
print_strings (tail, succ i)
end
end
in
println! (length example_strings);
println! (length sorted_strings);
print_strings (sorted_strings, 1)
end
(*------------------------------------------------------------------*)

View file

@ -0,0 +1,170 @@
(*------------------------------------------------------------------*)
(* Quicksort in ATS2, for linear lists. *)
(*------------------------------------------------------------------*)
#include "share/atspre_staload.hats"
#define NIL list_vt_nil ()
#define :: list_vt_cons
(*------------------------------------------------------------------*)
(* A simple quicksort working on linear linked lists, with first
element as pivot. This is meant as a demonstration, not as a
superior sort algorithm.
It is based on the "not-in-place" task pseudocode. *)
#define FIRST_IS_LESS_THAN_SECOND 1
#define FIRST_IS_EQUAL_TO_SECOND 2
#define FIRST_IS_GREATER_THAN_SECOND 3
typedef comparison_result =
[i : int | (i == FIRST_IS_LESS_THAN_SECOND ||
i == FIRST_IS_EQUAL_TO_SECOND ||
i == FIRST_IS_GREATER_THAN_SECOND)]
int i
extern fun {a : vt@ype}
list_vt_quicksort$comparison (x : !a, y : !a) :<> comparison_result
extern fun {a : vt@ype}
list_vt_quicksort {n : int}
(lst : list_vt (a, n)) :<!wrt> list_vt (a, n)
(* - - - - - - - - - - - - - - - - - - - - - - *)
implement {a}
list_vt_quicksort {n} (lst) =
let
fun
partition {n : nat}
.<n>. (* Proof of termination. *)
(lst : list_vt (a, n),
pivot : !a)
:<> [n1, n2, n3 : int | n1 + n2 + n3 == n]
@(list_vt (a, n1), list_vt (a, n2), list_vt (a, n3)) =
(* This implementation is *not* tail recursive. I may get a
scolding for using ATS to risk stack overflow! However, I
need more practice writing non-tail routines. :) Also, a lot
of programmers in other languages would do it this
way--especially if the lists are evaluated lazily. *)
case+ lst of
| ~ NIL => @(NIL, NIL, NIL)
| ~ head :: tail =>
let
val @(lt, eq, gt) = partition (tail, pivot)
prval () = lemma_list_vt_param lt
prval () = lemma_list_vt_param eq
prval () = lemma_list_vt_param gt
in
case+ list_vt_quicksort$comparison<a> (head, pivot) of
| FIRST_IS_LESS_THAN_SECOND => @(head :: lt, eq, gt)
| FIRST_IS_EQUAL_TO_SECOND => @(lt, head :: eq, gt)
| FIRST_IS_GREATER_THAN_SECOND => @(lt, eq, head :: gt)
end
fun
quicksort {n : nat}
.<n>. (* Proof of termination. *)
(lst : list_vt (a, n))
:<!wrt> list_vt (a, n) =
case+ lst of
| NIL => lst
| _ :: NIL => lst
| ~ head :: tail =>
let
(* We are careful here to run "partition" on "tail" rather
than "lst", so the termination metric will be provably
decreasing. (Really the compiler *forces* us to take such
care, or else to add !ntm to the effects.) *)
val pivot = head
prval () = lemma_list_vt_param tail
val @(lt, eq, gt) = partition {n - 1} (tail, pivot)
prval () = lemma_list_vt_param lt
prval () = lemma_list_vt_param eq
prval () = lemma_list_vt_param gt
val eq = pivot :: eq
and lt = quicksort lt
and gt = quicksort gt
in
list_vt_append (lt, list_vt_append (eq, gt))
end
prval () = lemma_list_vt_param lst
in
quicksort {n} lst
end
(*------------------------------------------------------------------*)
implement
list_vt_quicksort$comparison<Strptr1> (x, y) =
let
val i = compare (x, y)
in
if i < 0 then
FIRST_IS_LESS_THAN_SECOND
else if i = 0 then
FIRST_IS_EQUAL_TO_SECOND
else
FIRST_IS_GREATER_THAN_SECOND
end
implement
list_vt_map$fopr<string><Strptr1> (s) = string0_copy s
implement
list_vt_freelin$clear<Strptr1> (x) = strptr_free x
implement
main0 () =
let
val example_strings =
$list_vt
("choose", "any", "element", "of", "the", "array",
"to", "be", "the", "pivot",
"divide", "all", "other", "elements", "except",
"the", "pivot", "into", "two", "partitions",
"all", "elements", "less", "than", "the", "pivot",
"must", "be", "in", "the", "first", "partition",
"all", "elements", "greater", "than", "the", "pivot",
"must", "be", "in", "the", "second", "partition",
"use", "recursion", "to", "sort", "both", "partitions",
"join", "the", "first", "sorted", "partition", "the",
"pivot", "and", "the", "second", "sorted", "partition")
val example_strptrs =
list_vt_map<string><Strptr1> (example_strings)
val sorted_strptrs = list_vt_quicksort<Strptr1> example_strptrs
fun
print_strptrs {n : nat} .<n>.
(strptrs : !list_vt (Strptr1, n),
i : int) : void =
case+ strptrs of
| NIL => if i <> 1 then println! () else ()
| @ head :: tail =>
begin
print! head;
if i = 8 then
begin
println! ();
print_strptrs (tail, 1)
end
else
begin
print! " ";
print_strptrs (tail, succ i)
end;
fold@ strptrs
end
in
println! (length example_strings);
println! (length sorted_strptrs);
print_strptrs (sorted_strptrs, 1);
list_vt_freelin<Strptr1> sorted_strptrs;
list_vt_free<string> example_strings
end
(*------------------------------------------------------------------*)

View file

@ -0,0 +1,216 @@
(*------------------------------------------------------------------*)
(* Quicksort in ATS2, for arrays of non-linear values. *)
(*------------------------------------------------------------------*)
#include "share/atspre_staload.hats"
#define NIL list_nil ()
#define :: list_cons
(*------------------------------------------------------------------*)
(* A simple quicksort working on arrays of non-linear values, using
a programmer-selectible pivot.
It is based on the "in-place" task pseudocode. *)
extern fun {a : t@ype} (* A "less-than" predicate. *)
array_quicksort$lt (x : a, y : a) : bool
extern fun {a : t@ype}
array_quicksort$select_pivot {n : int}
{i, j : nat | i < j; j < n}
(arr : &array (a, n) >> _,
first : size_t i,
last : size_t j) : a
extern fun {a : t@ype}
array_quicksort {n : int}
(arr : &array (a, n) >> _,
n : size_t n) : void
(* - - - - - - - - - - - - - - - - - - - - - - *)
fn {a : t@ype}
swap {n : int}
{i, j : nat | i < n; j < n}
(arr : &array(a, n) >> _,
i : size_t i,
j : size_t j) : void =
{
val x = arr[i] and y = arr[j]
val () = (arr[i] := y) and () = (arr[j] := x)
}
implement {a}
array_quicksort {n} (arr, n) =
let
sortdef index = {i : nat | i < n}
typedef index (i : int) = [0 <= i; i < n] size_t i
typedef index = [i : index] index i
macdef lt = array_quicksort$lt<a>
fun
quicksort {i, j : index}
(arr : &array(a, n) >> _,
first : index i,
last : index j) : void =
if first < last then
{
val pivot : a =
array_quicksort$select_pivot<a> (arr, first, last)
fun
search_rightwards (arr : &array (a, n),
left : index) : index =
if arr[left] \lt pivot then
let
val () = assertloc (succ left <> n)
in
search_rightwards (arr, succ left)
end
else
left
fun
search_leftwards (arr : &array (a, n),
left : index,
right : index) : index =
if right < left then
right
else if pivot \lt arr[right] then
let
val () = assertloc (right <> i2sz 0)
in
search_leftwards (arr, left, pred right)
end
else
right
fun
partition (arr : &array (a, n) >> _,
left0 : index,
right0 : index) : @(index, index) =
let
val left = search_rightwards (arr, left0)
val right = search_leftwards (arr, left, right0)
in
if left <= right then
let
val () = assertloc (succ left <> n)
and () = assertloc (right <> i2sz 0)
in
swap (arr, left, right);
partition (arr, succ left, pred right)
end
else
@(left, right)
end
val @(left, right) = partition (arr, first, last)
val () = quicksort (arr, first, right)
and () = quicksort (arr, left, last)
}
in
if i2sz 2 <= n then
quicksort {0, n - 1} (arr, i2sz 0, pred n)
end
(*------------------------------------------------------------------*)
val example_strings =
$list ("choose", "any", "element", "of", "the", "array",
"to", "be", "the", "pivot",
"divide", "all", "other", "elements", "except",
"the", "pivot", "into", "two", "partitions",
"all", "elements", "less", "than", "the", "pivot",
"must", "be", "in", "the", "first", "partition",
"all", "elements", "greater", "than", "the", "pivot",
"must", "be", "in", "the", "second", "partition",
"use", "recursion", "to", "sort", "both", "partitions",
"join", "the", "first", "sorted", "partition", "the",
"pivot", "and", "the", "second", "sorted", "partition")
implement
array_quicksort$lt<string> (x, y) =
strcmp (x, y) < 0
implement
array_quicksort$select_pivot<string> {n} (arr, first, last) =
(* Median of three, with swapping around of elements during pivot
selection. See https://archive.ph/oYENx *)
let
macdef lt = array_quicksort$lt<string>
val middle = first + ((last - first) / i2sz 2)
val xfirst = arr[first]
and xmiddle = arr[middle]
and xlast = arr[last]
in
if (xmiddle \lt xfirst) xor (xlast \lt xfirst) then
begin
swap (arr, first, middle);
if xlast \lt xmiddle then
swap (arr, first, last);
xfirst
end
else if (xmiddle \lt xfirst) xor (xmiddle \lt xlast) then
begin
if xlast \lt xfirst then
swap (arr, first, last);
xmiddle
end
else
begin
swap (arr, middle, last);
if xmiddle \lt xfirst then
swap (arr, first, last);
xlast
end
end
implement
main0 () =
let
prval () = lemma_list_param example_strings
val n = length example_strings
val @(pf, pfgc | p) = array_ptr_alloc<string> (i2sz n)
macdef arr = !p
val () = array_initize_list (arr, n, example_strings)
val () = array_quicksort<string> (arr, i2sz n)
val sorted_strings = list_vt2t (array2list (arr, i2sz n))
val () = array_ptr_free (pf, pfgc | p)
fun
print_strings {n : nat} .<n>.
(strings : list (string, n),
i : int) : void =
case+ strings of
| NIL => if i <> 1 then println! () else ()
| head :: tail =>
begin
print! head;
if i = 8 then
begin
println! ();
print_strings (tail, 1)
end
else
begin
print! " ";
print_strings (tail, succ i)
end
end
in
println! (length example_strings);
println! (length sorted_strings);
print_strings (sorted_strings, 1)
end
(*------------------------------------------------------------------*)

View file

@ -0,0 +1,364 @@
(*------------------------------------------------------------------*)
(* Quicksort in ATS2, for arrays of (possibly) linear values. *)
(*------------------------------------------------------------------*)
#include "share/atspre_staload.hats"
#define NIL list_vt_nil ()
#define :: list_vt_cons
(*------------------------------------------------------------------*)
(* A simple quicksort working on arrays of non-linear values, using
a programmer-selectible pivot.
It is based on the "in-place" task pseudocode. *)
extern fun {a : vt@ype} (* A "less-than" predicate. *)
array_quicksort$lt {px, py : addr}
(pfx : !(a @ px),
pfy : !(a @ py) |
px : ptr px,
py : ptr py) : bool
extern fun {a : vt@ype}
array_quicksort$select_pivot_index {n : int}
{i, j : nat | i < j; j < n}
(arr : &array (a, n),
first : size_t i,
last : size_t j)
: [k : int | i <= k; k <= j] size_t k
extern fun {a : vt@ype}
array_quicksort {n : int}
(arr : &array (a, n) >> _,
n : size_t n) : void
(* - - - - - - - - - - - - - - - - - - - - - - *)
prfn (* Subdivide an array view into three views. *)
array_v_subdivide3 {a : vt@ype} {p : addr} {n1, n2, n3 : nat}
(pf : @[a][n1 + n2 + n3] @ p)
:<prf> @(@[a][n1] @ p,
@[a][n2] @ (p + n1 * sizeof a),
@[a][n3] @ (p + (n1 + n2) * sizeof a)) =
let
prval (pf1, pf23) =
array_v_split {a} {p} {n1 + n2 + n3} {n1} pf
prval (pf2, pf3) =
array_v_split {a} {p + n1 * sizeof a} {n2 + n3} {n2} pf23
in
@(pf1, pf2, pf3)
end
prfn (* Join three contiguous array views into one view. *)
array_v_join3 {a : vt@ype} {p : addr} {n1, n2, n3 : nat}
(pf1 : @[a][n1] @ p,
pf2 : @[a][n2] @ (p + n1 * sizeof a),
pf3 : @[a][n3] @ (p + (n1 + n2) * sizeof a))
:<prf> @[a][n1 + n2 + n3] @ p =
let
prval pf23 =
array_v_unsplit {a} {p + n1 * sizeof a} {n2, n3} (pf2, pf3)
prval pf = array_v_unsplit {a} {p} {n1, n2 + n3} (pf1, pf23)
in
pf
end
fn {a : vt@ype} (* Safely swap two elements of an array. *)
swap_elems_1 {n : int}
{i, j : nat | i <= j; j < n}
{p : addr}
(pfarr : !array_v(a, p, n) >> _ |
p : ptr p,
i : size_t i,
j : size_t j) : void =
let
fn {a : vt@ype}
swap {n : int}
{i, j : nat | i < j; j < n}
{p : addr}
(pfarr : !array_v(a, p, n) >> _ |
p : ptr p,
i : size_t i,
j : size_t j) : void =
{
(* Safely swapping linear elements requires that views of
those elements be split off from the rest of the
array. Why? Because those elements will temporarily be in
an uninitialized state. (Actually they will be "?!", but
the difference is unimportant here.)
Remember, a linear value is consumed by using it.
The view for the whole array can be reassembled only after
new values have been stored, making the entire array once
again initialized. *)
prval @(pf1, pf2, pf3) =
array_v_subdivide3 {a} {p} {i, j - i, n - j} pfarr
prval @(pfi, pf2_) = array_v_uncons pf2
prval @(pfj, pf3_) = array_v_uncons pf3
val pi = ptr_add<a> (p, i)
and pj = ptr_add<a> (p, j)
val xi = ptr_get<a> (pfi | pi)
and xj = ptr_get<a> (pfj | pj)
val () = ptr_set<a> (pfi | pi, xj)
and () = ptr_set<a> (pfj | pj, xi)
prval pf2 = array_v_cons (pfi, pf2_)
prval pf3 = array_v_cons (pfj, pf3_)
prval () = pfarr := array_v_join3 (pf1, pf2, pf3)
}
in
if i < j then
swap {n} {i, j} {p} (pfarr | p, i, j)
else
() (* i = j must be handled specially, due to linear typing.*)
end
fn {a : vt@ype} (* Safely swap two elements of an array. *)
swap_elems_2 {n : int}
{i, j : nat | i <= j; j < n}
(arr : &array(a, n) >> _,
i : size_t i,
j : size_t j) : void =
swap_elems_1 (view@ arr | addr@ arr, i, j)
overload swap_elems with swap_elems_1
overload swap_elems with swap_elems_2
overload swap with swap_elems
fn {a : vt@ype} (* Safely compare two elements of an array. *)
lt_elems_1 {n : int}
{i, j : nat | i < n; j < n}
{p : addr}
(pfarr : !array_v(a, p, n) |
p : ptr p,
i : size_t i,
j : size_t j) : bool =
let
fn
compare {n : int}
{i, j : nat | i < j; j < n}
{p : addr}
(pfarr : !array_v(a, p, n) |
p : ptr p,
i : size_t i,
j : size_t j,
gt : bool) : bool =
let
prval @(pf1, pf2, pf3) =
array_v_subdivide3 {a} {p} {i, j - i, n - j} pfarr
prval @(pfi, pf2_) = array_v_uncons pf2
prval @(pfj, pf3_) = array_v_uncons pf3
val pi = ptr_add<a> (p, i)
and pj = ptr_add<a> (p, j)
val retval =
if gt then
array_quicksort$lt<a> (pfj, pfi | pj, pi)
else
array_quicksort$lt<a> (pfi, pfj | pi, pj)
prval pf2 = array_v_cons (pfi, pf2_)
prval pf3 = array_v_cons (pfj, pf3_)
prval () = pfarr := array_v_join3 (pf1, pf2, pf3)
in
retval
end
in
if i < j then
compare {n} {i, j} {p} (pfarr | p, i, j, false)
else if j < i then
compare {n} {j, i} {p} (pfarr | p, j, i, true)
else
false
end
fn {a : vt@ype} (* Safely compare two elements of an array. *)
lt_elems_2 {n : int}
{i, j : nat | i < n; j < n}
(arr : &array (a, n),
i : size_t i,
j : size_t j) : bool =
lt_elems_1 (view@ arr | addr@ arr, i, j)
overload lt_elems with lt_elems_1
overload lt_elems with lt_elems_2
implement {a}
array_quicksort {n} (arr, n) =
let
sortdef index = {i : nat | i < n}
typedef index (i : int) = [0 <= i; i < n] size_t i
typedef index = [i : index] index i
macdef lt = array_quicksort$lt<a>
fun
quicksort {i, j : index}
(arr : &array(a, n) >> _,
first : index i,
last : index j) : void =
if first < last then
{
val pivot =
array_quicksort$select_pivot_index<a> (arr, first, last)
(* Swap the pivot with the last element. *)
val () = swap (arr, pivot, last)
val pivot = last
fun
search_rightwards (arr : &array (a, n),
left : index) : index =
if lt_elems<a> (arr, left, pivot) then
let
val () = assertloc (succ left <> n)
in
search_rightwards (arr, succ left)
end
else
left
fun
search_leftwards (arr : &array (a, n),
left : index,
right : index) : index =
if right < left then
right
else if lt_elems<a> (arr, pivot, right) then
let
val () = assertloc (right <> i2sz 0)
in
search_leftwards (arr, left, pred right)
end
else
right
fun
partition (arr : &array (a, n) >> _,
left0 : index,
right0 : index) : @(index, index) =
let
val left = search_rightwards (arr, left0)
val right = search_leftwards (arr, left, right0)
in
if left <= right then
let
val () = assertloc (succ left <> n)
and () = assertloc (right <> i2sz 0)
in
swap (arr, left, right);
partition (arr, succ left, pred right)
end
else
@(left, right)
end
val @(left, right) = partition (arr, first, pred last)
val () = quicksort (arr, first, right)
and () = quicksort (arr, left, last)
}
in
if i2sz 2 <= n then
quicksort {0, n - 1} (arr, i2sz 0, pred n)
end
(*------------------------------------------------------------------*)
implement
array_quicksort$lt<Strptr1> (pfx, pfy | px, py) =
compare (!px, !py) < 0
implement
array_quicksort$select_pivot_index<Strptr1> {n} (arr, first, last) =
(* Median of three. *)
let
val middle = first + ((last - first) / i2sz 2)
in
if lt_elems<Strptr1> (arr, middle, first)
xor lt_elems<Strptr1> (arr, last, first) then
first
else if lt_elems<Strptr1> (arr, middle, first)
xor lt_elems<Strptr1> (arr, middle, last) then
middle
else
last
end
implement
list_vt_map$fopr<string><Strptr1> (s) = string0_copy s
implement
list_vt_freelin$clear<Strptr1> (x) = strptr_free x
implement
main0 () =
let
val example_strings =
$list_vt
("choose", "any", "element", "of", "the", "array",
"to", "be", "the", "pivot",
"divide", "all", "other", "elements", "except",
"the", "pivot", "into", "two", "partitions",
"all", "elements", "less", "than", "the", "pivot",
"must", "be", "in", "the", "first", "partition",
"all", "elements", "greater", "than", "the", "pivot",
"must", "be", "in", "the", "second", "partition",
"use", "recursion", "to", "sort", "both", "partitions",
"join", "the", "first", "sorted", "partition", "the",
"pivot", "and", "the", "second", "sorted", "partition")
val example_strptrs =
list_vt_map<string><Strptr1> (example_strings)
prval () = lemma_list_vt_param example_strptrs
val n = length example_strptrs
val @(pf, pfgc | p) = array_ptr_alloc<Strptr1> (i2sz n)
macdef arr = !p
val () = array_initize_list_vt<Strptr1> (arr, n, example_strptrs)
val () = array_quicksort<Strptr1> (arr, i2sz n)
val sorted_strptrs = array2list (arr, i2sz n)
fun
print_strptrs {n : nat} .<n>.
(strptrs : !list_vt (Strptr1, n),
i : int) : void =
case+ strptrs of
| NIL => if i <> 1 then println! () else ()
| @ head :: tail =>
begin
print! head;
if i = 8 then
begin
println! ();
print_strptrs (tail, 1)
end
else
begin
print! " ";
print_strptrs (tail, succ i)
end;
fold@ strptrs
end
in
println! (length example_strings);
println! (length sorted_strptrs);
print_strptrs (sorted_strptrs, 1);
list_vt_freelin<Strptr1> sorted_strptrs;
array_ptr_free (pf, pfgc | p);
list_vt_free<string> example_strings
end
(*------------------------------------------------------------------*)

View file

@ -0,0 +1,113 @@
# the following qsort implementation extracted from:
#
# ftp://ftp.armory.com/pub/lib/awk/qsort
#
# Copyleft GPLv2 John DuBois
#
# @(#) qsort 1.2.1 2005-10-21
# 1990 john h. dubois iii (john@armory.com)
#
# qsortArbIndByValue(): Sort an array according to the values of its elements.
#
# Input variables:
#
# Arr[] is an array of values with arbitrary (associative) indices.
#
# Output variables:
#
# k[] is returned with numeric indices 1..n. The values assigned to these
# indices are the indices of Arr[], ordered so that if Arr[] is stepped
# through in the order Arr[k[1]] .. Arr[k[n]], it will be stepped through in
# order of the values of its elements.
#
# Return value: The number of elements in the arrays (n).
#
# NOTES:
#
# Full example for accessing results:
#
# foolist["second"] = 2;
# foolist["zero"] = 0;
# foolist["third"] = 3;
# foolist["first"] = 1;
#
# outlist[1] = 0;
# n = qsortArbIndByValue(foolist, outlist)
#
# for (i = 1; i <= n; i++) {
# printf("item at %s has value %d\n", outlist[i], foolist[outlist[i]]);
# }
# delete outlist;
#
function qsortArbIndByValue(Arr, k,
ArrInd, ElNum)
{
ElNum = 0;
for (ArrInd in Arr) {
k[++ElNum] = ArrInd;
}
qsortSegment(Arr, k, 1, ElNum);
return ElNum;
}
#
# qsortSegment(): Sort a segment of an array.
#
# Input variables:
#
# Arr[] contains data with arbitrary indices.
#
# k[] has indices 1..nelem, with the indices of Arr[] as values.
#
# Output variables:
#
# k[] is modified by this function. The elements of Arr[] that are pointed to
# by k[start..end] are sorted, with the values of elements of k[] swapped
# so that when this function returns, Arr[k[start..end]] will be in order.
#
# Return value: None.
#
function qsortSegment(Arr, k, start, end,
left, right, sepval, tmp, tmpe, tmps)
{
if ((end - start) < 1) { # 0 or 1 elements
return;
}
# handle two-element case explicitly for a tiny speedup
if ((end - start) == 1) {
if (Arr[tmps = k[start]] > Arr[tmpe = k[end]]) {
k[start] = tmpe;
k[end] = tmps;
}
return;
}
# Make sure comparisons act on these as numbers
left = start + 0;
right = end + 0;
sepval = Arr[k[int((left + right) / 2)]];
# Make every element <= sepval be to the left of every element > sepval
while (left < right) {
while (Arr[k[left]] < sepval) {
left++;
}
while (Arr[k[right]] > sepval) {
right--;
}
if (left < right) {
tmp = k[left];
k[left++] = k[right];
k[right--] = tmp;
}
}
if (left == right)
if (Arr[k[left]] < sepval) {
left++;
} else {
right--;
}
if (start < right) {
qsortSegment(Arr, k, start, right);
}
if (left < end) {
qsortSegment(Arr, k, left, end);
}
}

View file

@ -0,0 +1,96 @@
DEFINE MAX_COUNT="100"
INT ARRAY stack(MAX_COUNT)
INT stackSize
PROC PrintArray(INT ARRAY a INT size)
INT i
Put('[)
FOR i=0 TO size-1
DO
IF i>0 THEN Put(' ) FI
PrintI(a(i))
OD
Put(']) PutE()
RETURN
PROC InitStack()
stackSize=0
RETURN
BYTE FUNC IsEmpty()
IF stackSize=0 THEN
RETURN (1)
FI
RETURN (0)
PROC Push(INT low,high)
stack(stackSize)=low stackSize==+1
stack(stackSize)=high stackSize==+1
RETURN
PROC Pop(INT POINTER low,high)
stackSize==-1 high^=stack(stackSize)
stackSize==-1 low^=stack(stackSize)
RETURN
INT FUNC Partition(INT ARRAY a INT low,high)
INT part,v,i,tmp
v=a(high)
part=low-1
FOR i=low TO high-1
DO
IF a(i)<=v THEN
part==+1
tmp=a(part) a(part)=a(i) a(i)=tmp
FI
OD
part==+1
tmp=a(part) a(part)=a(high) a(high)=tmp
RETURN (part)
PROC QuickSort(INT ARRAY a INT size)
INT low,high,part
InitStack()
Push(0,size-1)
WHILE IsEmpty()=0
DO
Pop(@low,@high)
part=Partition(a,low,high)
IF part-1>low THEN
Push(low,part-1)
FI
IF part+1<high THEN
Push(part+1,high)
FI
OD
RETURN
PROC Test(INT ARRAY a INT size)
PrintE("Array before sort:")
PrintArray(a,size)
QuickSort(a,size)
PrintE("Array after sort:")
PrintArray(a,size)
PutE()
RETURN
PROC Main()
INT ARRAY
a(10)=[1 4 65535 0 3 7 4 8 20 65530],
b(21)=[10 9 8 7 6 5 4 3 2 1 0
65535 65534 65533 65532 65531
65530 65529 65528 65527 65526],
c(8)=[101 102 103 104 105 106 107 108],
d(12)=[1 65535 1 65535 1 65535 1
65535 1 65535 1 65535]
Test(a,10)
Test(b,21)
Test(c,8)
Test(d,12)
RETURN

View file

@ -0,0 +1,11 @@
function quickSort (array:Array):Array
{
if (array.length <= 1)
return array;
var pivot:Number = array[Math.round(array.length / 2)];
return quickSort(array.filter(function (x:Number, index:int, array:Array):Boolean { return x < pivot; })).concat(
array.filter(function (x:Number, index:int, array:Array):Boolean { return x == pivot; })).concat(
quickSort(array.filter(function (x:Number, index:int, array:Array):Boolean { return x > pivot; })));
}

View file

@ -0,0 +1,24 @@
function quickSort (array:Array):Array
{
if (array.length <= 1)
return array;
var pivot:Number = array[Math.round(array.length / 2)];
var less:Array = [];
var equal:Array = [];
var greater:Array = [];
for each (var x:Number in array) {
if (x < pivot)
less.push(x);
if (x == pivot)
equal.push(x);
if (x > pivot)
greater.push(x);
}
return quickSort(less).concat(
equal).concat(
quickSort(greater));
}

View file

@ -0,0 +1,9 @@
-----------------------------------------------------------------------
-- Generic Quick_Sort procedure
-----------------------------------------------------------------------
generic
type Element is private;
type Index is (<>);
type Element_Array is array(Index range <>) of Element;
with function "<" (Left, Right : Element) return Boolean is <>;
procedure Quick_Sort(A : in out Element_Array);

View file

@ -0,0 +1,44 @@
-----------------------------------------------------------------------
-- Generic Quick_Sort procedure
-----------------------------------------------------------------------
procedure Quick_Sort (A : in out Element_Array) is
procedure Swap(Left, Right : Index) is
Temp : Element := A (Left);
begin
A (Left) := A (Right);
A (Right) := Temp;
end Swap;
begin
if A'Length > 1 then
declare
Pivot_Value : Element := A (A'First);
Right : Index := A'Last;
Left : Index := A'First;
begin
loop
while Left < Right and not (Pivot_Value < A (Left)) loop
Left := Index'Succ (Left);
end loop;
while Pivot_Value < A (Right) loop
Right := Index'Pred (Right);
end loop;
exit when Right <= Left;
Swap (Left, Right);
Left := Index'Succ (Left);
Right := Index'Pred (Right);
end loop;
if Right = A'Last then
Right := Index'Pred (Right);
Swap (A'First, A'Last);
end if;
if Left = A'First then
Left := Index'Succ (Left);
end if;
Quick_Sort (A (A'First .. Right));
Quick_Sort (A (Left .. A'Last));
end;
end if;
end Quick_Sort;

View file

@ -0,0 +1,32 @@
with Ada.Text_Io;
with Ada.Float_Text_IO; use Ada.Float_Text_IO;
with Quick_Sort;
procedure Sort_Test is
type Days is (Mon, Tue, Wed, Thu, Fri, Sat, Sun);
type Sales is array (Days range <>) of Float;
procedure Sort_Days is new Quick_Sort(Float, Days, Sales);
procedure Print (Item : Sales) is
begin
for I in Item'range loop
Put(Item => Item(I), Fore => 5, Aft => 2, Exp => 0);
end loop;
end Print;
Weekly_Sales : Sales := (Mon => 300.0,
Tue => 700.0,
Wed => 800.0,
Thu => 500.0,
Fri => 200.0,
Sat => 100.0,
Sun => 900.0);
begin
Print(Weekly_Sales);
Ada.Text_Io.New_Line(2);
Sort_Days(Weekly_Sales);
Print(Weekly_Sales);
end Sort_Test;

View file

@ -0,0 +1,66 @@
-- quickSort :: (Ord a) => [a] -> [a]
on quickSort(xs)
if length of xs > 1 then
set {h, t} to uncons(xs)
-- lessOrEqual :: a -> Bool
script lessOrEqual
on |λ|(x)
x h
end |λ|
end script
set {less, more} to partition(lessOrEqual, t)
quickSort(less) & h & quickSort(more)
else
xs
end if
end quickSort
-- TEST -----------------------------------------------------------------------
on run
quickSort([11.8, 14.1, 21.3, 8.5, 16.7, 5.7])
--> {5.7, 8.5, 11.8, 14.1, 16.7, 21.3}
end run
-- GENERIC FUNCTIONS ----------------------------------------------------------
-- partition :: predicate -> List -> (Matches, nonMatches)
-- partition :: (a -> Bool) -> [a] -> ([a], [a])
on partition(f, xs)
tell mReturn(f)
set lst to {{}, {}}
repeat with x in xs
set v to contents of x
set end of item ((|λ|(v) as integer) + 1) of lst to v
end repeat
return {item 2 of lst, item 1 of lst}
end tell
end partition
-- uncons :: [a] -> Maybe (a, [a])
on uncons(xs)
if length of xs > 0 then
{item 1 of xs, rest of xs}
else
missing value
end if
end uncons
-- Lift 2nd class handler function into 1st class script wrapper
-- mReturn :: Handler -> Script
on mReturn(f)
if class of f is script then
f
else
script
property |λ| : f
end script
end if
end mReturn

View file

@ -0,0 +1 @@
{5.7, 8.5, 11.8, 14.1, 16.7, 21.3}

View file

@ -0,0 +1,59 @@
-- In-place Quicksort (basic algorithm).
-- Algorithm: S.A.R. (Tony) Hoare, 1960.
on quicksort(theList, l, r) -- Sort items l thru r of theList.
set listLength to (count theList)
if (listLength < 2) then return
-- Convert negative and/or transposed range indices.
if (l < 0) then set l to listLength + l + 1
if (r < 0) then set r to listLength + r + 1
if (l > r) then set {l, r} to {r, l}
-- Script object containing the list as a property (to allow faster references to its items)
-- and the recursive subhandler.
script o
property lst : theList
on qsrt(l, r)
set pivot to my lst's item ((l + r) div 2)
set i to l
set j to r
repeat until (i > j)
set lv to my lst's item i
repeat while (pivot > lv)
set i to i + 1
set lv to my lst's item i
end repeat
set rv to my lst's item j
repeat while (rv > pivot)
set j to j - 1
set rv to my lst's item j
end repeat
if (j > i) then
set my lst's item i to rv
set my lst's item j to lv
else if (i > j) then
exit repeat
end if
set i to i + 1
set j to j - 1
end repeat
if (j > l) then qsrt(l, j)
if (i < r) then qsrt(i, r)
end qsrt
end script
tell o to qsrt(l, r)
return -- nothing.
end quicksort
property sort : quicksort
-- Demo:
local aList
set aList to {28, 9, 95, 22, 67, 55, 20, 41, 60, 53, 100, 72, 19, 67, 14, 42, 29, 20, 74, 39}
sort(aList, 1, -1) -- Sort items 1 thru -1 of aList.
return aList

View file

@ -0,0 +1 @@
{9, 14, 19, 20, 20, 22, 28, 29, 39, 41, 42, 53, 55, 60, 67, 67, 72, 74, 95, 100}

View file

@ -0,0 +1,6 @@
(def qs (seq)
(if (empty seq) nil
(let pivot (car seq)
(join (qs (keep [< _ pivot] (cdr seq)))
(list pivot)
(qs (keep [>= _ pivot] (cdr seq)))))))

View file

@ -0,0 +1,11 @@
quickSort: function [items][
if 2 > size items -> return items
pivot: first items
left: select slice items 1 (size items)-1 'x -> x < pivot
right: select slice items 1 (size items)-1 'x -> x >= pivot
((quickSort left) ++ pivot) ++ quickSort right
]
print quickSort [3 1 2 8 5 7 9 4 6]

View file

@ -0,0 +1,29 @@
a := [4, 65, 2, -31, 0, 99, 83, 782, 7]
for k, v in QuickSort(a)
Out .= "," v
MsgBox, % SubStr(Out, 2)
return
QuickSort(a)
{
if (a.MaxIndex() <= 1)
return a
Less := [], Same := [], More := []
Pivot := a[1]
for k, v in a
{
if (v < Pivot)
less.Insert(v)
else if (v > Pivot)
more.Insert(v)
else
same.Insert(v)
}
Less := QuickSort(Less)
Out := QuickSort(More)
if (Same.MaxIndex())
Out.Insert(1, Same*) ; insert all values of same at index 1
if (Less.MaxIndex())
Out.Insert(1, Less*) ; insert all values of less at index 1
return Out
}

View file

@ -0,0 +1,24 @@
MsgBox % quicksort("8,4,9,2,1")
quicksort(list)
{
StringSplit, list, list, `,
If (list0 <= 1)
Return list
pivot := list1
Loop, Parse, list, `,
{
If (A_LoopField < pivot)
less = %less%,%A_LoopField%
Else If (A_LoopField > pivot)
more = %more%,%A_LoopField%
Else
pivotlist = %pivotlist%,%A_LoopField%
}
StringTrimLeft, less, less, 1
StringTrimLeft, more, more, 1
StringTrimLeft, pivotList, pivotList, 1
less := quicksort(less)
more := quicksort(more)
Return less . pivotList . more
}

View file

@ -0,0 +1,50 @@
DECLARE SUB quicksort (arr() AS INTEGER, leftN AS INTEGER, rightN AS INTEGER)
DIM q(99) AS INTEGER
DIM n AS INTEGER
RANDOMIZE TIMER
FOR n = 0 TO 99
q(n) = INT(RND * 9999)
NEXT
OPEN "output.txt" FOR OUTPUT AS 1
FOR n = 0 TO 99
PRINT #1, q(n),
NEXT
PRINT #1,
quicksort q(), 0, 99
FOR n = 0 TO 99
PRINT #1, q(n),
NEXT
CLOSE
SUB quicksort (arr() AS INTEGER, leftN AS INTEGER, rightN AS INTEGER)
DIM pivot AS INTEGER, leftNIdx AS INTEGER, rightNIdx AS INTEGER
leftNIdx = leftN
rightNIdx = rightN
IF (rightN - leftN) > 0 THEN
pivot = (leftN + rightN) / 2
WHILE (leftNIdx <= pivot) AND (rightNIdx >= pivot)
WHILE (arr(leftNIdx) < arr(pivot)) AND (leftNIdx <= pivot)
leftNIdx = leftNIdx + 1
WEND
WHILE (arr(rightNIdx) > arr(pivot)) AND (rightNIdx >= pivot)
rightNIdx = rightNIdx - 1
WEND
SWAP arr(leftNIdx), arr(rightNIdx)
leftNIdx = leftNIdx + 1
rightNIdx = rightNIdx - 1
IF (leftNIdx - 1) = pivot THEN
rightNIdx = rightNIdx + 1
pivot = rightNIdx
ELSEIF (rightNIdx + 1) = pivot THEN
leftNIdx = leftNIdx - 1
pivot = leftNIdx
END IF
WEND
quicksort arr(), leftN, pivot - 1
quicksort arr(), pivot + 1, rightN
END IF
END SUB

View file

@ -0,0 +1,28 @@
DIM test(9)
test() = 4, 65, 2, -31, 0, 99, 2, 83, 782, 1
PROCquicksort(test(), 0, 10)
FOR i% = 0 TO 9
PRINT test(i%) ;
NEXT
PRINT
END
DEF PROCquicksort(a(), s%, n%)
LOCAL l%, p, r%, t%
IF n% < 2 THEN ENDPROC
t% = s% + n% - 1
l% = s%
r% = t%
p = a((l% + r%) DIV 2)
REPEAT
WHILE a(l%) < p l% += 1 : ENDWHILE
WHILE a(r%) > p r% -= 1 : ENDWHILE
IF l% <= r% THEN
SWAP a(l%), a(r%)
l% += 1
r% -= 1
ENDIF
UNTIL l% > r%
IF s% < r% PROCquicksort(a(), s%, r% - s% + 1)
IF l% < t% PROCquicksort(a(), l%, t% - l% + 1 )
ENDPROC

View file

@ -0,0 +1,53 @@
// This can be run using Cintcode BCPL freely available from www.cl.cam.ac.uk/users/mr10.
GET "libhdr.h"
LET quicksort(v, n) BE qsort(v+1, v+n)
AND qsort(l, r) BE
{ WHILE l+8<r DO
{ LET midpt = (l+r)/2
// Select a good(ish) median value.
LET val = middle(!l, !midpt, !r)
LET i = partition(val, l, r)
// Only use recursion on the smaller partition.
TEST i>midpt THEN { qsort(i, r); r := i-1 }
ELSE { qsort(l, i-1); l := i }
}
FOR p = l+1 TO r DO // Now perform insertion sort.
FOR q = p-1 TO l BY -1 TEST q!0<=q!1 THEN BREAK
ELSE { LET t = q!0
q!0 := q!1
q!1 := t
}
}
AND middle(a, b, c) = a<b -> b<c -> b,
a<c -> c,
a,
b<c -> a<c -> a,
c,
b
AND partition(median, p, q) = VALOF
{ LET t = ?
WHILE !p < median DO p := p+1
WHILE !q > median DO q := q-1
IF p>=q RESULTIS p
t := !p
!p := !q
!q := t
p, q := p+1, q-1
} REPEAT
LET start() = VALOF {
LET v = VEC 1000
FOR i = 1 TO 1000 DO v!i := randno(1_000_000)
quicksort(v, 1000)
FOR i = 1 TO 1000 DO
{ IF i MOD 10 = 0 DO newline()
writef(" %i6", v!i)
}
newline()
}

View file

@ -0,0 +1,36 @@
beads 1 program Quicksort
calc main_init
var arr = [1, 3, 5, 1, 7, 9, 8, 6, 4, 2]
var arr2 = arr
quicksort(arr, 1, tree_count(arr))
var tempStr : str
loop across:arr index:ix
tempStr = tempStr & ' ' & to_str(arr[ix])
log tempStr
calc quicksort(
arr:array of num
startIndex
highIndex
)
if (startIndex < highIndex)
var partitionIndex = partition(arr, startIndex, highIndex)
quicksort(arr, startIndex, partitionIndex - 1)
quicksort(arr, partitionIndex+1, highIndex)
calc partition(
arr:array of num
startIndex
highIndex
):num
var pivot = arr[highIndex]
var i = startIndex - 1
var j = startIndex
loop while:(j <= highIndex - 1)
if arr[j] < pivot
inc i
swap arr[i] <=> arr[j]
inc j
swap arr[i+1] <=> arr[highIndex]
return (i+1)

View file

@ -0,0 +1,19 @@
( ( Q
= Less Greater Equal pivot element
. !arg:%(?pivot:?Equal) %?arg
& :?Less:?Greater
& whl
' ( !arg:%?element ?arg
& (.!element)+(.!pivot) { BAD: 1900+90 adds to 1990, GOOD: (.1900)+(.90) is sorted to (.90)+(.1900) }
: ( (.!element)+(.!pivot)
& !element !Less:?Less
| (.!pivot)+(.!element)
& !element !Greater:?Greater
| ?&!element !Equal:?Equal
)
)
& Q$!Less !Equal Q$!Greater
| !arg
)
& out$Q$(1900 optimized variants of 4001/2 Quicksort (quick,sort) are (quick,sober) features of 90 languages)
);

View file

@ -0,0 +1,70 @@
#include <iterator>
#include <algorithm> // for std::partition
#include <functional> // for std::less
// helper function for median of three
template<typename T>
T median(T t1, T t2, T t3)
{
if (t1 < t2)
{
if (t2 < t3)
return t2;
else if (t1 < t3)
return t3;
else
return t1;
}
else
{
if (t1 < t3)
return t1;
else if (t2 < t3)
return t3;
else
return t2;
}
}
// helper object to get <= from <
template<typename Order> struct non_strict_op:
public std::binary_function<typename Order::second_argument_type,
typename Order::first_argument_type,
bool>
{
non_strict_op(Order o): order(o) {}
bool operator()(typename Order::second_argument_type arg1,
typename Order::first_argument_type arg2) const
{
return !order(arg2, arg1);
}
private:
Order order;
};
template<typename Order> non_strict_op<Order> non_strict(Order o)
{
return non_strict_op<Order>(o);
}
template<typename RandomAccessIterator,
typename Order>
void quicksort(RandomAccessIterator first, RandomAccessIterator last, Order order)
{
if (first != last && first+1 != last)
{
typedef typename std::iterator_traits<RandomAccessIterator>::value_type value_type;
RandomAccessIterator mid = first + (last - first)/2;
value_type pivot = median(*first, *mid, *(last-1));
RandomAccessIterator split1 = std::partition(first, last, std::bind2nd(order, pivot));
RandomAccessIterator split2 = std::partition(split1, last, std::bind2nd(non_strict(order), pivot));
quicksort(first, split1, order);
quicksort(split2, last, order);
}
}
template<typename RandomAccessIterator>
void quicksort(RandomAccessIterator first, RandomAccessIterator last)
{
quicksort(first, last, std::less<typename std::iterator_traits<RandomAccessIterator>::value_type>());
}

View file

@ -0,0 +1,22 @@
#include <iterator>
#include <algorithm> // for std::partition
#include <functional> // for std::less
template<typename RandomAccessIterator,
typename Order>
void quicksort(RandomAccessIterator first, RandomAccessIterator last, Order order)
{
if (last - first > 1)
{
RandomAccessIterator split = std::partition(first+1, last, std::bind2nd(order, *first));
std::iter_swap(first, split-1);
quicksort(first, split-1, order);
quicksort(split, last, order);
}
}
template<typename RandomAccessIterator>
void quicksort(RandomAccessIterator first, RandomAccessIterator last)
{
quicksort(first, last, std::less<typename std::iterator_traits<RandomAccessIterator>::value_type>());
}

View file

@ -0,0 +1,176 @@
//
// The Tripartite conditional enables Bentley-McIlroy 3-way Partitioning.
// This performs additional compares to isolate islands of keys equal to
// the pivot value. Use unless key-equivalent classes are of small size.
//
#define Tripartite
namespace RosettaCode {
using System;
using System.Diagnostics;
public class QuickSort<T> where T : IComparable {
#region Constants
public const UInt32 INSERTION_LIMIT_DEFAULT = 12;
private const Int32 SAMPLES_MAX = 19;
#endregion
#region Properties
public UInt32 InsertionLimit { get; }
private T[] Samples { get; }
private Int32 Left { get; set; }
private Int32 Right { get; set; }
private Int32 LeftMedian { get; set; }
private Int32 RightMedian { get; set; }
#endregion
#region Constructors
public QuickSort(UInt32 insertionLimit = INSERTION_LIMIT_DEFAULT) {
this.InsertionLimit = insertionLimit;
this.Samples = new T[SAMPLES_MAX];
}
#endregion
#region Sort Methods
public void Sort(T[] entries) {
Sort(entries, 0, entries.Length - 1);
}
public void Sort(T[] entries, Int32 first, Int32 last) {
var length = last + 1 - first;
while (length > 1) {
if (length < InsertionLimit) {
InsertionSort<T>.Sort(entries, first, last);
return;
}
Left = first;
Right = last;
var median = pivot(entries);
partition(median, entries);
//[Note]Right < Left
var leftLength = Right + 1 - first;
var rightLength = last + 1 - Left;
//
// First recurse over shorter partition, then loop
// on the longer partition to elide tail recursion.
//
if (leftLength < rightLength) {
Sort(entries, first, Right);
first = Left;
length = rightLength;
}
else {
Sort(entries, Left, last);
last = Right;
length = leftLength;
}
}
}
/// <summary>Return an odd sample size proportional to the log of a large interval size.</summary>
private static Int32 sampleSize(Int32 length, Int32 max = SAMPLES_MAX) {
var logLen = (Int32)Math.Log10(length);
var samples = Math.Min(2 * logLen + 1, max);
return Math.Min(samples, length);
}
/// <summary>Estimate the median value of entries[Left:Right]</summary>
/// <remarks>A sample median is used as an estimate the true median.</remarks>
private T pivot(T[] entries) {
var length = Right + 1 - Left;
var samples = sampleSize(length);
// Sample Linearly:
for (var sample = 0; sample < samples; sample++) {
// Guard against Arithmetic Overflow:
var index = (Int64)length * sample / samples + Left;
Samples[sample] = entries[index];
}
InsertionSort<T>.Sort(Samples, 0, samples - 1);
return Samples[samples / 2];
}
private void partition(T median, T[] entries) {
var first = Left;
var last = Right;
#if Tripartite
LeftMedian = first;
RightMedian = last;
#endif
while (true) {
//[Assert]There exists some index >= Left where entries[index] >= median
//[Assert]There exists some index <= Right where entries[index] <= median
// So, there is no need for Left or Right bound checks
while (median.CompareTo(entries[Left]) > 0) Left++;
while (median.CompareTo(entries[Right]) < 0) Right--;
//[Assert]entries[Right] <= median <= entries[Left]
if (Right <= Left) break;
Swap(entries, Left, Right);
swapOut(median, entries);
Left++;
Right--;
//[Assert]entries[first:Left - 1] <= median <= entries[Right + 1:last]
}
if (Left == Right) {
Left++;
Right--;
}
//[Assert]Right < Left
swapIn(entries, first, last);
//[Assert]entries[first:Right] <= median <= entries[Left:last]
//[Assert]entries[Right + 1:Left - 1] == median when non-empty
}
#endregion
#region Swap Methods
[Conditional("Tripartite")]
private void swapOut(T median, T[] entries) {
if (median.CompareTo(entries[Left]) == 0) Swap(entries, LeftMedian++, Left);
if (median.CompareTo(entries[Right]) == 0) Swap(entries, Right, RightMedian--);
}
[Conditional("Tripartite")]
private void swapIn(T[] entries, Int32 first, Int32 last) {
// Restore Median entries
while (first < LeftMedian) Swap(entries, first++, Right--);
while (RightMedian < last) Swap(entries, Left++, last--);
}
/// <summary>Swap entries at the left and right indicies.</summary>
public void Swap(T[] entries, Int32 left, Int32 right) {
Swap(ref entries[left], ref entries[right]);
}
/// <summary>Swap two entities of type T.</summary>
public static void Swap(ref T e1, ref T e2) {
var e = e1;
e1 = e2;
e2 = e;
}
#endregion
}
#region Insertion Sort
static class InsertionSort<T> where T : IComparable {
public static void Sort(T[] entries, Int32 first, Int32 last) {
for (var next = first + 1; next <= last; next++)
insert(entries, first, next);
}
/// <summary>Bubble next entry up to its sorted location, assuming entries[first:next - 1] are already sorted.</summary>
private static void insert(T[] entries, Int32 first, Int32 next) {
var entry = entries[next];
while (next > first && entries[next - 1].CompareTo(entry) > 0)
entries[next] = entries[--next];
entries[next] = entry;
}
}
#endregion
}

View file

@ -0,0 +1,11 @@
using Sort;
using System;
class Program {
static void Main(String[] args) {
var entries = new Int32[] { 1, 3, 5, 7, 9, 8, 6, 4, 2 };
var sorter = new QuickSort<Int32>();
sorter.Sort(entries);
Console.WriteLine(String.Join(" ", entries));
}
}

View file

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace QSort
{
class QSorter
{
private static IEnumerable<IComparable> empty = new List<IComparable>();
public static IEnumerable<IComparable> QSort(IEnumerable<IComparable> iEnumerable)
{
if(iEnumerable.Any())
{
var pivot = iEnumerable.First();
return QSort(iEnumerable.Where((anItem) => pivot.CompareTo(anItem) > 0)).
Concat(iEnumerable.Where((anItem) => pivot.CompareTo(anItem) == 0)).
Concat(QSort(iEnumerable.Where((anItem) => pivot.CompareTo(anItem) < 0)));
}
return empty;
}
}
}

View file

@ -0,0 +1,44 @@
#include <stdio.h>
void quicksort(int *A, int len);
int main (void) {
int a[] = {4, 65, 2, -31, 0, 99, 2, 83, 782, 1};
int n = sizeof a / sizeof a[0];
int i;
for (i = 0; i < n; i++) {
printf("%d ", a[i]);
}
printf("\n");
quicksort(a, n);
for (i = 0; i < n; i++) {
printf("%d ", a[i]);
}
printf("\n");
return 0;
}
void quicksort(int *A, int len) {
if (len < 2) return;
int pivot = A[len / 2];
int i, j;
for (i = 0, j = len - 1; ; i++, j--) {
while (A[i] < pivot) i++;
while (A[j] > pivot) j--;
if (i >= j) break;
int temp = A[i];
A[i] = A[j];
A[j] = temp;
}
quicksort(A, i);
quicksort(A + i, len - i);
}

View file

@ -0,0 +1,29 @@
#include <stdlib.h> // REQ: rand()
void swap(int *a, int *b) {
int c = *a;
*a = *b;
*b = c;
}
int partition(int A[], int p, int q) {
swap(&A[p + (rand() % (q - p + 1))], &A[q]); // PIVOT = A[q]
int i = p - 1;
for(int j = p; j <= q; j++) {
if(A[j] <= A[q]) {
swap(&A[++i], &A[j]);
}
}
return i;
}
void quicksort(int A[], int p, int q) {
if(p < q) {
int pivotIndx = partition(A, p, q);
quicksort(A, p, pivotIndx - 1);
quicksort(A, pivotIndx + 1, q);
}
}

View file

@ -0,0 +1,66 @@
IDENTIFICATION DIVISION.
PROGRAM-ID. quicksort RECURSIVE.
DATA DIVISION.
LOCAL-STORAGE SECTION.
01 temp PIC S9(8).
01 pivot PIC S9(8).
01 left-most-idx PIC 9(5).
01 right-most-idx PIC 9(5).
01 left-idx PIC 9(5).
01 right-idx PIC 9(5).
LINKAGE SECTION.
78 Arr-Length VALUE 50.
01 arr-area.
03 arr PIC S9(8) OCCURS Arr-Length TIMES.
01 left-val PIC 9(5).
01 right-val PIC 9(5).
PROCEDURE DIVISION USING REFERENCE arr-area, OPTIONAL left-val,
OPTIONAL right-val.
IF left-val IS OMITTED OR right-val IS OMITTED
MOVE 1 TO left-most-idx, left-idx
MOVE Arr-Length TO right-most-idx, right-idx
ELSE
MOVE left-val TO left-most-idx, left-idx
MOVE right-val TO right-most-idx, right-idx
END-IF
IF right-most-idx - left-most-idx < 1
GOBACK
END-IF
COMPUTE pivot = arr ((left-most-idx + right-most-idx) / 2)
PERFORM UNTIL left-idx > right-idx
PERFORM VARYING left-idx FROM left-idx BY 1
UNTIL arr (left-idx) >= pivot
END-PERFORM
PERFORM VARYING right-idx FROM right-idx BY -1
UNTIL arr (right-idx) <= pivot
END-PERFORM
IF left-idx <= right-idx
MOVE arr (left-idx) TO temp
MOVE arr (right-idx) TO arr (left-idx)
MOVE temp TO arr (right-idx)
ADD 1 TO left-idx
SUBTRACT 1 FROM right-idx
END-IF
END-PERFORM
CALL "quicksort" USING REFERENCE arr-area,
CONTENT left-most-idx, right-idx
CALL "quicksort" USING REFERENCE arr-area, CONTENT left-idx,
right-most-idx
GOBACK
.

View file

@ -0,0 +1,35 @@
mod! SIMPLE-LIST(X :: TRIV){
[NeList < List ]
op [] : -> List
op [_] : Elt -> List
op (_:_) : Elt List -> NeList -- consr
op _++_ : List List -> List {assoc} -- concatenate
var E : Elt
vars L L' : List
eq [ E ] = E : [] .
eq [] ++ L = L .
eq (E : L) ++ L' = E : (L ++ L') .
}
mod! QUICKSORT{
pr(SIMPLE-LIST(NAT))
op qsort_ : List -> List
op smaller__ : List Nat -> List
op larger__ : List Nat -> List
vars x y : Nat
vars xs ys : List
eq qsort [] = [] .
eq qsort (x : xs) = (qsort (smaller xs x)) ++ [ x ] ++ (qsort (larger xs x)) .
eq smaller [] x = [] .
eq smaller (x : xs) y = if x <= y then (x : (smaller xs y)) else (smaller xs y) fi .
eq larger [] x = [] .
eq larger (x : xs) y = if x <= y then (larger xs y) else (x : (larger xs y)) fi .
}
open QUICKSORT .
red qsort(5 : 4 : 3 : 2 : 1 : 0 : []) .
red qsort(5 : 5 : 4 : 3 : 5 : 2 : 1 : 1 : 0 : []) .
eof

View file

@ -0,0 +1,7 @@
(defn qsort [L]
(if (empty? L)
'()
(let [[pivot & L2] L]
(lazy-cat (qsort (for [y L2 :when (< y pivot)] y))
(list pivot)
(qsort (for [y L2 :when (>= y pivot)] y))))))

View file

@ -0,0 +1,5 @@
(defn qsort [[pvt & rs]]
(if pvt
`(~@(qsort (filter #(< % pvt) rs))
~pvt
~@(qsort (filter #(>= % pvt) rs)))))

View file

@ -0,0 +1,6 @@
(defn qsort [[pivot & xs]]
(when pivot
(let [smaller #(< % pivot)]
(lazy-cat (qsort (filter smaller xs))
[pivot]
(qsort (remove smaller xs))))))

View file

@ -0,0 +1,4 @@
(defn qsort3 [[pvt :as coll]]
(when pvt
(let [{left -1 mid 0 right 1} (group-by #(compare % pvt) coll)]
(lazy-cat (qsort3 left) mid (qsort3 right)))))

View file

@ -0,0 +1,5 @@
(defn qsort3 [[pivot :as coll]]
(when pivot
(lazy-cat (qsort (filter #(< % pivot) coll))
(filter #{pivot} coll)
(qsort (filter #(> % pivot) coll)))))

View file

@ -0,0 +1,5 @@
quicksort = ([x, xs...]) ->
return [] unless x?
smallerOrEqual = (a for a in xs when a <= x)
larger = (a for a in xs when a > x)
(quicksort smallerOrEqual).concat(x).concat(quicksort larger)

View file

@ -0,0 +1,6 @@
(defun quicksort (list &aux (pivot (car list)) )
(if (cdr list)
(nconc (quicksort (remove-if-not #'(lambda (x) (< x pivot)) list))
(remove-if-not #'(lambda (x) (= x pivot)) list)
(quicksort (remove-if-not #'(lambda (x) (> x pivot)) list)))
list))

View file

@ -0,0 +1,6 @@
(defun qs (list)
(if (cdr list)
(flet ((pivot (test)
(remove (car list) list :test-not test)))
(nconc (qs (pivot #'>)) (pivot #'=) (qs (pivot #'<))))
list))

View file

@ -0,0 +1,14 @@
(defun quicksort (sequence)
(labels ((swap (a b) (rotatef (elt sequence a) (elt sequence b)))
(sub-sort (left right)
(when (< left right)
(let ((pivot (elt sequence right))
(index left))
(loop for i from left below right
when (<= (elt sequence i) pivot)
do (swap i (prog1 index (incf index))))
(swap right index)
(sub-sort left (1- index))
(sub-sort (1+ index) right)))))
(sub-sort 0 (1- (length sequence)))
sequence))

View file

@ -0,0 +1,6 @@
(defun quicksort (list)
(when list
(destructuring-bind (x . xs) list
(nconc (quicksort (remove-if (lambda (a) (> a x)) xs))
`(,x)
(quicksort (remove-if (lambda (a) (<= a x)) xs))))))

View file

@ -0,0 +1,102 @@
include "cowgol.coh";
# Comparator interface, on the model of C, i.e:
# foo < bar => -1, foo == bar => 0, foo > bar => 1
typedef CompRslt is int(-1, 1);
interface Comparator(foo: intptr, bar: intptr): (rslt: CompRslt);
# Quicksort an array of pointer-sized integers given a comparator function
# (This is the closest you can get to polymorphism in Cowgol).
# Because Cowgol does not support recursion, a pointer to free memory
# for a stack must also be given.
sub qsort(A: [intptr], len: intptr, comp: Comparator, stack: [intptr]) is
# The partition function can be taken almost verbatim from Wikipedia
sub partition(lo: intptr, hi: intptr): (p: intptr) is
# This is not quite as bad as it looks: /2 compiles into a single shift
# and "@bytesof intptr" is always power of 2 so compiles into shift(s).
var pivot := [A + (hi/2 + lo/2) * @bytesof intptr];
var i := lo - 1;
var j := hi + 1;
loop
loop
i := i + 1;
if comp([A + i*@bytesof intptr], pivot) != -1 then
break;
end if;
end loop;
loop
j := j - 1;
if comp([A + j*@bytesof intptr], pivot) != 1 then
break;
end if;
end loop;
if i >= j then
p := j;
return;
end if;
var ii := i * @bytesof intptr;
var jj := j * @bytesof intptr;
var t := [A+ii];
[A+ii] := [A+jj];
[A+jj] := t;
end loop;
end sub;
# Cowgol lacks recursion, so we'll have to solve it by implementing
# the stack ourselves.
var sp: intptr := 0; # stack index
sub push(n: intptr) is
sp := sp + 1;
[stack] := n;
stack := @next stack;
end sub;
sub pop(): (n: intptr) is
sp := sp - 1;
stack := @prev stack;
n := [stack];
end sub;
# start by sorting [0..length-1]
push(len-1);
push(0);
while sp != 0 loop
var lo := pop();
var hi := pop();
if lo < hi then
var p := partition(lo, hi);
push(hi); # note the order - we need to push the high pair
push(p+1); # first for it to be done last
push(p);
push(lo);
end if;
end loop;
end sub;
# Test: sort a list of numbers
sub NumComp implements Comparator is
# Compare the inputs as numbers
if foo < bar then rslt := -1;
elseif foo > bar then rslt := 1;
else rslt := 0;
end if;
end sub;
# Numbers
var numbers: intptr[] := {
65,13,4,84,29,5,96,73,5,11,17,76,38,26,44,20,36,12,44,51,79,8,99,7,19,95,26
};
# Room for the stack
var stackbuf: intptr[256];
# Sort the numbers in place
qsort(&numbers as [intptr], @sizeof numbers, NumComp, &stackbuf as [intptr]);
# Print the numbers (hopefully in order)
var i: @indexof numbers := 0;
while i < @sizeof numbers loop
print_i32(numbers[i] as uint32);
print_char(' ');
i := i + 1;
end loop;
print_nl();

View file

@ -0,0 +1,100 @@
define size = 10, point = 0, top = 0
define high = 0, low = 0, pivot = 0
dim list[size]
dim stack[size]
gosub fill
gosub sort
gosub show
end
sub fill
for i = 0 to size - 1
let list[i] = int(rnd * 100)
next i
return
sub sort
let low = 0
let high = size - 1
let top = -1
let top = top + 1
let stack[top] = low
let top = top + 1
let stack[top] = high
do
if top < 0 then
break
endif
let high = stack[top]
let top = top - 1
let low = stack[top]
let top = top - 1
let i = low - 1
for j = low to high - 1
if list[j] <= list[high] then
let i = i + 1
let t = list[i]
let list[i] = list[j]
let list[j] = t
endif
next j
let point = i + 1
let t = list[point]
let list[point] = list[high]
let list[high] = t
let pivot = i + 1
if pivot - 1 > low then
let top = top + 1
let stack[top] = low
let top = top + 1
let stack[top] = pivot - 1
endif
if pivot + 1 < high then
let top = top + 1
let stack[top] = pivot + 1
let top = top + 1
let stack[top] = high
endif
wait
loop top >= 0
return
sub show
for i = 0 to size - 1
print i, ": ", list[i]
next i
return

View file

@ -0,0 +1,9 @@
def quick_sort(a : Array(Int32)) : Array(Int32)
return a if a.size <= 1
p = a[0]
lt, rt = a[1 .. -1].partition { |x| x < p }
return quick_sort(lt) + [p] + quick_sort(rt)
end
a = [7, 6, 5, 9, 8, 4, 3, 1, 2, 0]
puts quick_sort(a) # => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

View file

@ -0,0 +1,7 @@
-- quicksort using higher-order functions:
qsort :: [Int] -> [Int]
qsort [] = []
qsort (x:l) = qsort (filter (<x) l) ++ x : qsort (filter (>=x) l)
goal = qsort [2,3,1,0]

View file

@ -0,0 +1,12 @@
import std.stdio : writefln, writeln;
import std.algorithm: filter;
import std.array;
T[] quickSort(T)(T[] xs) =>
xs.length == 0 ? [] :
xs[1 .. $].filter!(x => x< xs[0]).array.quickSort ~
xs[0 .. 1] ~
xs[1 .. $].filter!(x => x>=xs[0]).array.quickSort;
void main() =>
[4, 65, 2, -31, 0, 99, 2, 83, 782, 1].quickSort.writeln;

View file

@ -0,0 +1,14 @@
import std.stdio, std.array;
T[] quickSort(T)(T[] items) pure nothrow {
if (items.empty)
return items;
T[] less, notLess;
foreach (x; items[1 .. $])
(x < items[0] ? less : notLess) ~= x;
return less.quickSort ~ items[0] ~ notLess.quickSort;
}
void main() {
[4, 65, 2, -31, 0, 99, 2, 83, 782, 1].quickSort.writeln;
}

View file

@ -0,0 +1,15 @@
import std.stdio, std.algorithm;
void quickSort(T)(T[] items) pure nothrow @safe @nogc {
if (items.length >= 2) {
auto parts = partition3(items, items[$ / 2]);
parts[0].quickSort;
parts[2].quickSort;
}
}
void main() {
auto items = [4, 65, 2, -31, 0, 99, 2, 83, 782, 1];
items.quickSort;
items.writeln;
}

View file

@ -0,0 +1,39 @@
quickSort(List a) {
if (a.length <= 1) {
return a;
}
var pivot = a[0];
var less = [];
var more = [];
var pivotList = [];
// Partition
a.forEach((var i){
if (i.compareTo(pivot) < 0) {
less.add(i);
} else if (i.compareTo(pivot) > 0) {
more.add(i);
} else {
pivotList.add(i);
}
});
// Recursively sort sublists
less = quickSort(less);
more = quickSort(more);
// Concatenate results
less.addAll(pivotList);
less.addAll(more);
return less;
}
void main() {
var arr=[1,5,2,7,3,9,4,6,8];
print("Before sort");
arr.forEach((var i)=>print("$i"));
arr = quickSort(arr);
print("After sort");
arr.forEach((var i)=>print("$i"));
}

View file

@ -0,0 +1,140 @@
{Dynamic array of pointers}
type TPointerArray = array of Pointer;
procedure QuickSort(SortList: TPointerArray; L, R: Integer; SCompare: TListSortCompare);
{Do quick sort on items held in TPointerArray}
{SCompare controls how the pointers are interpreted}
var I, J: Integer;
var P,T: Pointer;
begin
repeat
begin
I := L;
J := R;
P := SortList[(L + R) shr 1];
repeat
begin
while SCompare(SortList[I], P) < 0 do Inc(I);
while SCompare(SortList[J], P) > 0 do Dec(J);
if I <= J then
begin
{Exchange itesm}
T:=SortList[I];
SortList[I]:=SortList[J];
SortList[J]:=T;
if P = SortList[I] then P := SortList[J]
else if P = SortList[J] then P := SortList[I];
Inc(I);
Dec(J);
end;
end
until I > J;
if L < J then QuickSort(SortList, L, J, SCompare);
L := I;
end
until I >= R;
end;
procedure DisplayStrings(Memo: TMemo; PA: TPointerArray);
{Display pointers as strings}
var I: integer;
var S: string;
begin
S:='[';
for I:=0 to High(PA) do
begin
if I>0 then S:=S+' ';
S:=S+string(PA[I]^);
end;
S:=S+']';
Memo.Lines.Add(S);
end;
procedure DisplayIntegers(Memo: TMemo; PA: TPointerArray);
{Display pointer array as integers}
var I: integer;
var S: string;
begin
S:='[';
for I:=0 to High(PA) do
begin
if I>0 then S:=S+' ';
S:=S+IntToStr(Integer(PA[I]));
end;
S:=S+']';
Memo.Lines.Add(S);
end;
function IntCompare(Item1, Item2: Pointer): Integer;
{Compare for integer sort}
begin
Result:=Integer(Item1)-Integer(Item2);
end;
function StringCompare(Item1, Item2: Pointer): Integer;
{Compare for alphabetical string sort}
begin
Result:=AnsiCompareText(string(Item1^),string(Item2^));
end;
function StringRevCompare(Item1, Item2: Pointer): Integer;
{Compare for reverse alphabetical order}
begin
Result:=AnsiCompareText(string(Item2^),string(Item1^));
end;
function StringLenCompare(Item1, Item2: Pointer): Integer;
{Compare for string length sort}
begin
Result:=Length(string(Item1^))-Length(string(Item2^));
end;
{Arrays of strings and integers}
var IA: array [0..9] of integer = (23, 14, 62, 28, 56, 91, 33, 30, 75, 5);
var SA: array [0..15] of string = ('Now','is','the','time','for','all','good','men','to','come','to','the','aid','of','the','party.');
procedure ShowQuickSort(Memo: TMemo);
var L: TStringList;
var PA: TPointerArray;
var I: integer;
begin
Memo.Lines.Add('Integer Sort');
SetLength(PA,Length(IA));
for I:=0 to High(IA) do PA[I]:=Pointer(IA[I]);
Memo.Lines.Add('Before Sorting');
DisplayIntegers(Memo,PA);
QuickSort(PA,0,High(PA),IntCompare);
Memo.Lines.Add('After Sorting');
DisplayIntegers(Memo,PA);
Memo.Lines.Add('');
Memo.Lines.Add('String Sort - Alphabetical');
SetLength(PA,Length(SA));
for I:=0 to High(SA) do PA[I]:=Pointer(@SA[I]);
Memo.Lines.Add('Before Sorting');
DisplayStrings(Memo,PA);
QuickSort(PA,0,High(PA),StringCompare);
Memo.Lines.Add('After Sorting');
DisplayStrings(Memo,PA);
Memo.Lines.Add('');
Memo.Lines.Add('String Sort - Reverse Alphabetical');
QuickSort(PA,0,High(PA),StringRevCompare);
Memo.Lines.Add('After Sorting');
DisplayStrings(Memo,PA);
Memo.Lines.Add('');
Memo.Lines.Add('String Sort - By Length');
QuickSort(PA,0,High(PA),StringLenCompare);
Memo.Lines.Add('After Sorting');
DisplayStrings(Memo,PA);
end;

View file

@ -0,0 +1,47 @@
def quicksort := {
def swap(container, ixA, ixB) {
def temp := container[ixA]
container[ixA] := container[ixB]
container[ixB] := temp
}
def partition(array, var first :int, var last :int) {
if (last <= first) { return }
# Choose a pivot
def pivot := array[def pivotIndex := (first + last) // 2]
# Move pivot to end temporarily
swap(array, pivotIndex, last)
var swapWith := first
# Scan array except for pivot, and...
for i in first..!last {
if (array[i] <= pivot) { # items ≤ the pivot
swap(array, i, swapWith) # are moved to consecutive positions on the left
swapWith += 1
}
}
# Swap pivot into between-partition position.
# Because of the swapping we know that everything before swapWith is less
# than or equal to the pivot, and the item at swapWith (since it was not
# swapped) is greater than the pivot, so inserting the pivot at swapWith
# will preserve the partition.
swap(array, swapWith, last)
return swapWith
}
def quicksortR(array, first :int, last :int) {
if (last <= first) { return }
def pivot := partition(array, first, last)
quicksortR(array, first, pivot - 1)
quicksortR(array, pivot + 1, last)
}
def quicksort(array) { # returned from block
quicksortR(array, 0, array.size() - 1)
}
}

View file

@ -0,0 +1,79 @@
PROGRAM QUICKSORT_DEMO
DIM ARRAY[21]
!$DYNAMIC
DIM QSTACK[0]
!$INCLUDE="PC.LIB"
PROCEDURE QSORT(ARRAY[],START,NUM)
FIRST=START ! initialize work variables
LAST=START+NUM-1
LOOP
REPEAT
TEMP=ARRAY[(LAST+FIRST) DIV 2] ! seek midpoint
I=FIRST
J=LAST
REPEAT ! reverse both < and > below to sort descending
WHILE ARRAY[I]<TEMP DO
I=I+1
END WHILE
WHILE ARRAY[J]>TEMP DO
J=J-1
END WHILE
EXIT IF I>J
IF I<J THEN SWAP(ARRAY[I],ARRAY[J]) END IF
I=I+1
J=J-1
UNTIL NOT(I<=J)
IF I<LAST THEN ! Done
QSTACK[SP]=I ! Push I
QSTACK[SP+1]=LAST ! Push Last
SP=SP+2
END IF
LAST=J
UNTIL NOT(FIRST<LAST)
EXIT IF SP=0
SP=SP-2
FIRST=QSTACK[SP] ! Pop First
LAST=QSTACK[SP+1] ! Pop Last
END LOOP
END PROCEDURE
BEGIN
RANDOMIZE(TIMER) ! generate a new series each run
! create an array
FOR X=1 TO 21 DO ! fill with random numbers
ARRAY[X]=RND(1)*500 ! between 0 and 500
END FOR
PRIMO=6 ! sort starting here
NUM=10 ! sort this many elements
CLS
PRINT("Before Sorting:";TAB(31);"After sorting:")
PRINT("===============";TAB(31);"==============")
FOR X=1 TO 21 DO ! show them before sorting
IF X>=PRIMO AND X<=PRIMO+NUM-1 THEN
PRINT("==>";)
END IF
PRINT(TAB(5);)
WRITE("###.##";ARRAY[X])
END FOR
! create a stack
!$DIM QSTACK[INT(NUM/5)+10]
QSORT(ARRAY[],PRIMO,NUM)
!$ERASE QSTACK
LOCATE(2,1)
FOR X=1 TO 21 DO ! print them after sorting
LOCATE(2+X,30)
IF X>=PRIMO AND X<=PRIMO+NUM-1 THEN
PRINT("==>";) ! point to sorted items
END IF
LOCATE(2+X,35)
WRITE("###.##";ARRAY[X])
END FOR
END PROGRAM

View file

@ -0,0 +1,28 @@
proc qsort left right . d[] .
while left < right
# partition
piv = d[left]
mid = left
for i = left + 1 to right
if d[i] < piv
mid += 1
swap d[i] d[mid]
.
.
swap d[left] d[mid]
#
if mid < (right + left) / 2
call qsort left mid - 1 d[]
left = mid + 1
else
call qsort mid + 1 right d[]
right = mid - 1
.
.
.
func sort . d[] .
call qsort 1 len d[] d[]
.
d[] = [ 29 4 72 44 55 26 27 77 92 5 ]
call sort d[]
print d[]

View file

@ -0,0 +1,14 @@
(lib 'list) ;; list-partition
(define compare 0) ;; counter
(define (quicksort L compare-predicate: proc aux: (part null))
(if (<= (length L) 1) L
(begin
;; counting the number of comparisons
(set! compare (+ compare (length (rest L))))
;; pivot = first element of list
(set! part (list-partition (rest L) proc (first L)))
(append (quicksort (first part) proc )
(list (first L))
(quicksort (second part) proc)))))

View file

@ -0,0 +1,18 @@
(shuffle (iota 15))
→ (10 0 14 11 13 9 2 5 4 8 1 7 12 3 6)
(quicksort (shuffle (iota 15)) <)
→ (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14)
;; random list of numbers in [0 .. n[
;; count number of comparisons
(define (qtest (n 10000))
(set! compare 0)
(quicksort (shuffle (iota n)) >)
(writeln 'n n 'compare# compare ))
(qtest 1000)
n 1000 compare# 12764
(qtest 10000)
n 10000 compare# 277868
(qtest 100000)
n 100000 compare# 6198601

View file

@ -0,0 +1,36 @@
#import <Foundation/Foundation.h>
void quicksortInPlace(MutableArray array, const long first, const long last)
if first >= last
return
Value pivot = array[(first + last) / 2]
left := first
right := last
while left <= right
while array[left] < pivot
left++
while array[right] > pivot
right--
if left <= right
array.exchangeObjectAtIndex: left++, withObjectAtIndex: right--
quicksortInPlace(array, first, right)
quicksortInPlace(array, left, last)
Array quicksort(Array unsorted)
a := []
a.addObjectsFromArray: unsorted
quicksortInPlace(a, 0, a.count - 1)
return a
int main(int argc, const char * argv[])
autoreleasepool
a := [1, 3, 5, 7, 9, 8, 6, 4, 2]
Log( 'Unsorted: %@', a)
Log( 'Sorted: %@', quicksort(a) )
b := ['Emil', 'Peg', 'Helen', 'Juergen', 'David', 'Rick', 'Barb', 'Mike', 'Tom']
Log( 'Unsorted: %@', b)
Log( 'Sorted: %@', quicksort(b) )
return 0

View file

@ -0,0 +1,33 @@
#import <Foundation/Foundation.h>
implementation Array (Quicksort)
plus: Array array, return Array =
self.arrayByAddingObjectsFromArray: array
filter: BOOL (^)(id) predicate, return Array
array := []
for id item in self
if predicate(item)
array.addObject: item
return array.copy
quicksort, return Array = self
if self.count > 1
id x = self[self.count / 2]
lesser := self.filter: (id y | return y < x)
greater := self.filter: (id y | return y > x)
return lesser.quicksort + [x] + greater.quicksort
end
int main()
autoreleasepool
a := [1, 3, 5, 7, 9, 8, 6, 4, 2]
Log( 'Unsorted: %@', a)
Log( 'Sorted: %@', a.quicksort )
b := ['Emil', 'Peg', 'Helen', 'Juergen', 'David', 'Rick', 'Barb', 'Mike', 'Tom']
Log( 'Unsorted: %@', b)
Log( 'Sorted: %@', b.quicksort )
return 0

View file

@ -0,0 +1 @@
QUICKSORT

View file

@ -0,0 +1,94 @@
class
QUICKSORT [G -> COMPARABLE]
create
make
feature {NONE} --Implementation
is_sorted (list: ARRAY [G]): BOOLEAN
require
not_void: list /= Void
local
i: INTEGER
do
Result := True
from
i := list.lower + 1
invariant
i >= list.lower + 1 and i <= list.upper + 1
until
i > list.upper
loop
Result := Result and list [i - 1] <= list [i]
i := i + 1
variant
list.upper + 1 - i
end
end
concatenate_array (a: ARRAY [G] b: ARRAY [G]): ARRAY [G]
require
not_void: a /= Void and b /= Void
do
create Result.make_from_array (a)
across
b as t
loop
Result.force (t.item, Result.upper + 1)
end
ensure
same_size: a.count + b.count = Result.count
end
quicksort_array (list: ARRAY [G]): ARRAY [G]
require
not_void: list /= Void
local
less_a: ARRAY [G]
equal_a: ARRAY [G]
more_a: ARRAY [G]
pivot: G
do
create less_a.make_empty
create more_a.make_empty
create equal_a.make_empty
create Result.make_empty
if list.count <= 1 then
Result := list
else
pivot := list [list.lower]
across
list as li
invariant
less_a.count + equal_a.count + more_a.count <= list.count
loop
if li.item < pivot then
less_a.force (li.item, less_a.upper + 1)
elseif li.item = pivot then
equal_a.force (li.item, equal_a.upper + 1)
elseif li.item > pivot then
more_a.force (li.item, more_a.upper + 1)
end
end
Result := concatenate_array (Result, quicksort_array (less_a))
Result := concatenate_array (Result, equal_a)
Result := concatenate_array (Result, quicksort_array (more_a))
end
ensure
same_size: list.count = Result.count
sorted: is_sorted (Result)
end
feature -- Initialization
make
do
end
quicksort (a: ARRAY [G]): ARRAY [G]
do
Result := quicksort_array (a)
end
end

View file

@ -0,0 +1,28 @@
class
APPLICATION
create
make
feature {NONE} -- Initialization
make
-- Run application.
local
test: ARRAY [INTEGER]
sorted: ARRAY [INTEGER]
sorter: QUICKSORT [INTEGER]
do
create sorter.make
test := <<1, 3, 2, 4, 5, 5, 7, -1>>
sorted := sorter.quicksort (test)
across
sorted as s
loop
print (s.item)
print (" ")
end
print ("%N")
end
end

View file

@ -0,0 +1,49 @@
import extensions;
import system'routines;
import system'collections;
extension op
{
quickSort()
{
if (self.isEmpty()) { ^ self };
var pivot := self[0];
auto less := new ArrayList();
auto pivotList := new ArrayList();
auto more := new ArrayList();
self.forEach:(item)
{
if (item < pivot)
{
less.append(item)
}
else if (item > pivot)
{
more.append(item)
}
else
{
pivotList.append(item)
}
};
less := less.quickSort();
more := more.quickSort();
less.appendRange(pivotList);
less.appendRange(more);
^ less
}
}
public program()
{
var list := new int[]{3, 14, 1, 5, 9, 2, 6, 3};
console.printLine("before:", list.asEnumerable());
console.printLine("after :", list.quickSort().asEnumerable());
}

View file

@ -0,0 +1,7 @@
defmodule Sort do
def qsort([]), do: []
def qsort([h | t]) do
{lesser, greater} = Enum.split_with(t, &(&1 < h))
qsort(lesser) ++ [h] ++ qsort(greater)
end
end

View file

@ -0,0 +1,10 @@
(require 'seq)
(defun quicksort (xs)
(if (null xs)
()
(let* ((head (car xs))
(tail (cdr xs))
(lower-part (quicksort (seq-filter (lambda (x) (<= x head)) tail)))
(higher-part (quicksort (seq-filter (lambda (x) (> x head)) tail))))
(append lower-part (list head) higher-part))))

View file

@ -0,0 +1,7 @@
-module( quicksort ).
-export( [qsort/1] ).
qsort([]) -> [];
qsort([X|Xs]) ->
qsort([ Y || Y <- Xs, Y < X]) ++ [X] ++ qsort([ Y || Y <- Xs, Y >= X]).

View file

@ -0,0 +1,20 @@
quick_sort(L) -> qs(L, trunc(math:log2(erlang:system_info(schedulers)))).
qs([],_) -> [];
qs([H|T], N) when N > 0 ->
{Parent, Ref} = {self(), make_ref()},
spawn(fun()-> Parent ! {l1, Ref, qs([E||E<-T, E<H], N-1)} end),
spawn(fun()-> Parent ! {l2, Ref, qs([E||E<-T, H =< E], N-1)} end),
{L1, L2} = receive_results(Ref, undefined, undefined),
L1 ++ [H] ++ L2;
qs([H|T],_) ->
qs([E||E<-T, E<H],0) ++ [H] ++ qs([E||E<-T, H =< E],0).
receive_results(Ref, L1, L2) ->
receive
{l1, Ref, L1R} when L2 == undefined -> receive_results(Ref, L1R, L2);
{l2, Ref, L2R} when L1 == undefined -> receive_results(Ref, L1, L2R);
{l1, Ref, L1R} -> {L1R, L2};
{l2, Ref, L2R} -> {L1, L2R}
after 5000 -> receive_results(Ref, L1, L2)
end.

View file

@ -0,0 +1,5 @@
let rec qsort = function
hd :: tl ->
let less, greater = List.partition ((>=) hd) tl
List.concat [qsort less; [hd]; qsort greater]
| _ -> []

View file

@ -0,0 +1,5 @@
: qsort ( seq -- seq )
dup empty? [
unclip [ [ < ] curry partition [ qsort ] bi@ ] keep
prefix append
] unless ;

View file

@ -0,0 +1,29 @@
; utility for list joining
(= join (fn (a b)
(if (is a nil) b (is b nil) a (do
(let res a)
(while (cdr a) (= a (cdr a)))
(setcdr a b)
res))))
(= quicksort (fn (lst)
(if (not (cdr lst)) lst (do
(let pivot (car lst))
(let less nil)
(let equal nil)
(let greater nil)
; filter list for less than pivot, equal to pivot and greater than pivot
(while lst
(let x (car lst))
(if (< x pivot) (= less (cons x less))
(< pivot x) (= greater (cons x greater))
(= equal (cons x equal)))
(= lst (cdr lst)))
; sort 'less' and 'greater' partitions ('equal' partition is always sorted)
(= less (quicksort less))
(= greater (quicksort greater))
; join partitions to one
(join less (join equal greater))))))
(print '(4 65 0 2 -31 99 2 0 83 782 1))
(print (quicksort '(4 65 0 2 -31 99 2 0 83 782 1)))

View file

@ -0,0 +1,2 @@
(4 65 0 2 -31 99 2 0 83 782 1)
(-31 0 0 1 2 2 4 65 83 99 782)

View file

@ -0,0 +1,18 @@
# (sort xs) is the ordered list of all elements in list xs.
# This version preserves duplicates.
\sort==
(\xs
xs [] \x\xs
append (sort; filter (gt x) xs); # all the items less than x
cons x; append (filter (eq x) xs); # all the items equal to x
sort; filter (lt x) xs # all the items greater than x
)
# (unique xs) is the ordered list of unique elements in list xs.
\unique==
(\xs
xs [] \x\xs
append (unique; filter (gt x) xs); # all the items less than x
cons x; # x itself
unique; filter (lt x) xs # all the items greater than x
)

View file

@ -0,0 +1,21 @@
: mid ( l r -- mid ) over - 2/ -cell and + ;
: exch ( addr1 addr2 -- ) dup @ >r over @ swap ! r> swap ! ;
: partition ( l r -- l r r2 l2 )
2dup mid @ >r ( r: pivot )
2dup begin
swap begin dup @ r@ < while cell+ repeat
swap begin r@ over @ < while cell- repeat
2dup <= if 2dup exch >r cell+ r> cell- then
2dup > until r> drop ;
: qsort ( l r -- )
partition swap rot
\ 2over 2over - + < if 2swap then
2dup < if recurse else 2drop then
2dup < if recurse else 2drop then ;
: sort ( array len -- )
dup 2 < if 2drop exit then
1- cells over + qsort ;

View file

@ -0,0 +1,100 @@
MODULE qsort_mod
IMPLICIT NONE
TYPE group
INTEGER :: order ! original order of unsorted data
REAL :: VALUE ! values to be sorted by
END TYPE group
CONTAINS
RECURSIVE SUBROUTINE QSort(a,na)
! DUMMY ARGUMENTS
INTEGER, INTENT(in) :: nA
TYPE (group), DIMENSION(nA), INTENT(in out) :: A
! LOCAL VARIABLES
INTEGER :: left, right
REAL :: random
REAL :: pivot
TYPE (group) :: temp
INTEGER :: marker
IF (nA > 1) THEN
CALL random_NUMBER(random)
pivot = A(INT(random*REAL(nA-1))+1)%VALUE ! Choice a random pivot (not best performance, but avoids worst-case)
left = 1
right = nA
! Partition loop
DO
IF (left >= right) EXIT
DO
IF (A(right)%VALUE <= pivot) EXIT
right = right - 1
END DO
DO
IF (A(left)%VALUE >= pivot) EXIT
left = left + 1
END DO
IF (left < right) THEN
temp = A(left)
A(left) = A(right)
A(right) = temp
END IF
END DO
IF (left == right) THEN
marker = left + 1
ELSE
marker = left
END IF
CALL QSort(A(:marker-1),marker-1)
CALL QSort(A(marker:),nA-marker+1)
END IF
END SUBROUTINE QSort
END MODULE qsort_mod
! Test Qsort Module
PROGRAM qsort_test
USE qsort_mod
IMPLICIT NONE
INTEGER, PARAMETER :: nl = 10, nc = 5, l = nc*nl, ns=33
TYPE (group), DIMENSION(l) :: A
INTEGER, DIMENSION(ns) :: seed
INTEGER :: i
REAL :: random
CHARACTER(LEN=80) :: fmt1, fmt2
! Using the Fibonacci sequence to initialize seed:
seed(1) = 1 ; seed(2) = 1
DO i = 3,ns
seed(i) = seed(i-1)+seed(i-2)
END DO
! Formats of the outputs
WRITE(fmt1,'(A,I2,A)') '(', nc, '(I5,2X,F6.2))'
WRITE(fmt2,'(A,I2,A)') '(3x', nc, '("Ord. Num.",3x))'
PRINT *, "Unsorted Values:"
PRINT fmt2,
CALL random_SEED(put = seed)
DO i = 1, l
CALL random_NUMBER(random)
A(i)%VALUE = NINT(1000*random)/10.0
A(i)%order = i
IF (MOD(i,nc) == 0) WRITE (*,fmt1) A(i-nc+1:i)
END DO
PRINT *
CALL QSort(A,l)
PRINT *, "Sorted Values:"
PRINT fmt2,
DO i = nc, l, nc
IF (MOD(i,nc) == 0) WRITE (*,fmt1) A(i-nc+1:i)
END DO
STOP
END PROGRAM qsort_test

View file

@ -0,0 +1,57 @@
' version 23-10-2016
' compile with: fbc -s console
' sort from lower bound to the highter bound
' array's can have subscript range from -2147483648 to +2147483647
Sub quicksort(qs() As Long, l As Long, r As Long)
Dim As ULong size = r - l +1
If size < 2 Then Exit Sub
Dim As Long i = l, j = r
Dim As Long pivot = qs(l + size \ 2)
Do
While qs(i) < pivot
i += 1
Wend
While pivot < qs(j)
j -= 1
Wend
If i <= j Then
Swap qs(i), qs(j)
i += 1
j -= 1
End If
Loop Until i > j
If l < j Then quicksort(qs(), l, j)
If i < r Then quicksort(qs(), i, r)
End Sub
' ------=< MAIN >=------
Dim As Long i, array(-7 To 7)
Dim As Long a = LBound(array), b = UBound(array)
Randomize Timer
For i = a To b : array(i) = i : Next
For i = a To b ' little shuffle
Swap array(i), array(Int(Rnd * (b - a +1)) + a)
Next
Print "unsorted ";
For i = a To b : Print Using "####"; array(i); : Next : Print
quicksort(array(), LBound(array), UBound(array))
Print " sorted ";
For i = a To b : Print Using "####"; array(i); : Next : Print
' empty keyboard buffer
While Inkey <> "" : Wend
Print : Print "hit any key to end program"
Sleep
End

View file

@ -0,0 +1,3 @@
def
qsort( [] ) = []
qsort( p:xs ) = qsort( xs.filter((< p)) ) + [p] + qsort( xs.filter((>= p)) )

View file

@ -0,0 +1,8 @@
def
qsort( [] ) = []
qsort( x:xs ) =
val (ys, zs) = xs.partition( (< x) )
qsort( ys ) + (x : qsort( zs ))
println( qsort([4, 2, 1, 3, 0, 2]) )
println( qsort(["Juan", "Daniel", "Miguel", "William", "Liam", "Ethan", "Jacob"]) )

View file

@ -0,0 +1,51 @@
include "NSLog.incl"
local fn Quicksort( qs as CFMutableArrayRef, l as NSInteger, r as NSInteger )
UInt64 size = r - l + 1
if size < 2 then exit fn
NSinteger i = l, j = r
NSinteger pivot = fn NumberIntegerValue( qs[l+size / 2] )
do
while fn NumberIntegerValue( qs[i] ) < pivot
i++
wend
while pivot < fn NumberIntegerValue( qs[j] )
j--
wend
if ( i <= j )
MutableArrayExchangeObjects( qs, i, j )
i++
j--
end if
until i > j
if l < j then fn Quicksort( qs, l, j )
if i < r then fn Quicksort( qs, i, r )
end fn
CFMutableArrayRef qs
CFArrayRef unsorted
NSUInteger i, amount
qs = fn MutableArrayWithCapacity(0)
for i = 0 to 25
if i mod 2 == 0 then amount = 100 else amount = 10000
MutableArrayInsertObjectAtIndex( qs, fn NumberWithInteger( rnd(amount) ), i )
next
unsorted = fn ArrayWithArray( qs )
fn QuickSort( qs, 0, len(qs) - 1 )
NSLog( @"\n-----------------\nUnsorted : Sorted\n-----------------" )
for i = 0 to 25
NSLog( @"%8ld : %-8ld", fn NumberIntegerValue( unsorted[i] ), fn NumberIntegerValue( qs[i] ) )
next
randomize
HandleEvents

View file

@ -0,0 +1,93 @@
package main
import "fmt"
func main() {
list := []int{31, 41, 59, 26, 53, 58, 97, 93, 23, 84}
fmt.Println("unsorted:", list)
quicksort(list)
fmt.Println("sorted! ", list)
}
func quicksort(a []int) {
var pex func(int, int)
pex = func(lower, upper int) {
for {
switch upper - lower {
case -1, 0: // 0 or 1 item in segment. nothing to do here!
return
case 1: // 2 items in segment
// < operator respects strict weak order
if a[upper] < a[lower] {
// a quick exchange and we're done.
a[upper], a[lower] = a[lower], a[upper]
}
return
// Hoare suggests optimized sort-3 or sort-4 algorithms here,
// but does not provide an algorithm.
}
// Hoare stresses picking a bound in a way to avoid worst case
// behavior, but offers no suggestions other than picking a
// random element. A function call to get a random number is
// relatively expensive, so the method used here is to simply
// choose the middle element. This at least avoids worst case
// behavior for the obvious common case of an already sorted list.
bx := (upper + lower) / 2
b := a[bx] // b = Hoare's "bound" (aka "pivot")
lp := lower // lp = Hoare's "lower pointer"
up := upper // up = Hoare's "upper pointer"
outer:
for {
// use < operator to respect strict weak order
for lp < upper && !(b < a[lp]) {
lp++
}
for {
if lp > up {
// "pointers crossed!"
break outer
}
// < operator for strict weak order
if a[up] < b {
break // inner
}
up--
}
// exchange
a[lp], a[up] = a[up], a[lp]
lp++
up--
}
// segment boundary is between up and lp, but lp-up might be
// 1 or 2, so just call segment boundary between lp-1 and lp.
if bx < lp {
// bound was in lower segment
if bx < lp-1 {
// exchange bx with lp-1
a[bx], a[lp-1] = a[lp-1], b
}
up = lp - 2
} else {
// bound was in upper segment
if bx > lp {
// exchange
a[bx], a[lp] = a[lp], b
}
up = lp - 1
lp++
}
// "postpone the larger of the two segments" = recurse on
// the smaller segment, then iterate on the remaining one.
if up-lower < upper-lp {
pex(lower, up)
lower = lp
} else {
pex(lp, upper)
upper = up
}
}
}
pex(0, len(a)-1)
}

View file

@ -0,0 +1,52 @@
package main
import (
"fmt"
"sort"
"math/rand"
)
func partition(a sort.Interface, first int, last int, pivotIndex int) int {
a.Swap(first, pivotIndex) // move it to beginning
left := first+1
right := last
for left <= right {
for left <= last && a.Less(left, first) {
left++
}
for right >= first && a.Less(first, right) {
right--
}
if left <= right {
a.Swap(left, right)
left++
right--
}
}
a.Swap(first, right) // swap into right place
return right
}
func quicksortHelper(a sort.Interface, first int, last int) {
if first >= last {
return
}
pivotIndex := partition(a, first, last, rand.Intn(last - first + 1) + first)
quicksortHelper(a, first, pivotIndex-1)
quicksortHelper(a, pivotIndex+1, last)
}
func quicksort(a sort.Interface) {
quicksortHelper(a, 0, a.Len()-1)
}
func main() {
a := []int{1, 3, 5, 7, 9, 8, 6, 4, 2}
fmt.Printf("Unsorted: %v\n", a)
quicksort(sort.IntSlice(a))
fmt.Printf("Sorted: %v\n", a)
b := []string{"Emil", "Peg", "Helen", "Juergen", "David", "Rick", "Barb", "Mike", "Tom"}
fmt.Printf("Unsorted: %v\n", b)
quicksort(sort.StringSlice(b))
fmt.Printf("Sorted: %v\n", b)
}

View file

@ -0,0 +1,2 @@
qsort [] = []
qsort (x:xs) = qsort [y | y <- xs, y < x] ++ [x] ++ qsort [y | y <- xs, y >= x]

View file

@ -0,0 +1,6 @@
import Data.List (partition)
qsort :: Ord a => [a] -> [a]
qsort [] = []
qsort (x:xs) = qsort ys ++ [x] ++ qsort zs where
(ys, zs) = partition (< x) xs

View file

@ -0,0 +1,5 @@
function qs, arr
if (count = n_elements(arr)) lt 2 then return,arr
pivot = total(arr) / count ; use the average for want of a better choice
return,[qs(arr[where(arr le pivot)]),qs(arr[where(arr gt pivot)])]
end

View file

@ -0,0 +1,37 @@
100 PROGRAM "QuickSrt.bas"
110 RANDOMIZE
120 NUMERIC A(5 TO 19)
130 CALL INIT(A)
140 CALL WRITE(A)
150 CALL QSORT(LBOUND(A),UBOUND(A))
160 CALL WRITE(A)
170 DEF INIT(REF A)
180 FOR I=LBOUND(A) TO UBOUND(A)
190 LET A(I)=RND(98)+1
200 NEXT
210 END DEF
220 DEF WRITE(REF A)
230 FOR I=LBOUND(A) TO UBOUND(A)
240 PRINT A(I);
250 NEXT
260 PRINT
270 END DEF
280 DEF QSORT(AH,FH)
290 NUMERIC E
300 LET E=AH:LET U=FH:LET K=A(E)
310 DO UNTIL E=U
320 DO UNTIL E=U OR A(U)<K
330 LET U=U-1
340 LOOP
350 IF E<U THEN
360 LET A(E)=A(U):LET E=E+1
370 DO UNTIL E=U OR A(E)>K
380 LET E=E+1
390 LOOP
400 IF E<U THEN LET A(U)=A(E):LET U=U-1
410 END IF
420 LOOP
430 LET A(E)=K
440 IF AH<E-1 THEN CALL QSORT(AH,E-1)
450 IF E+1<FH THEN CALL QSORT(E+1,FH)
460 END DEF

View file

@ -0,0 +1,46 @@
procedure main() #: demonstrate various ways to sort a list and string
demosort(quicksort,[3, 14, 1, 5, 9, 2, 6, 3],"qwerty")
end
procedure quicksort(X,op,lower,upper) #: return sorted list
local pivot,x
if /lower := 1 then { # top level call setup
upper := *X
op := sortop(op,X) # select how and what we sort
}
if upper - lower > 0 then {
every x := quickpartition(X,op,lower,upper) do # find a pivot and sort ...
/pivot | X := x # ... how to return 2 values w/o a structure
X := quicksort(X,op,lower,pivot-1) # ... left
X := quicksort(X,op,pivot,upper) # ... right
}
return X
end
procedure quickpartition(X,op,lower,upper) #: quicksort partitioner helper
local pivot
static pivotL
initial pivotL := list(3)
pivotL[1] := X[lower] # endpoints
pivotL[2] := X[upper] # ... and
pivotL[3] := X[lower+?(upper-lower)] # ... random midpoint
if op(pivotL[2],pivotL[1]) then pivotL[2] :=: pivotL[1] # mini-
if op(pivotL[3],pivotL[2]) then pivotL[3] :=: pivotL[2] # ... sort
pivot := pivotL[2] # median is pivot
lower -:= 1
upper +:= 1
while lower < upper do { # find values on wrong side of pivot ...
while op(pivot,X[upper -:= 1]) # ... rightmost
while op(X[lower +:=1],pivot) # ... leftmost
if lower < upper then # not crossed yet
X[lower] :=: X[upper] # ... swap
}
suspend lower # 1st return pivot point
suspend X # 2nd return modified X (in case immutable)
end

View file

@ -0,0 +1,6 @@
quicksort : Ord elem => List elem -> List elem
quicksort [] = []
quicksort (x :: xs) =
let lesser = filter (< x) xs
greater = filter(>= x) xs in
(quicksort lesser) ++ [x] ++ (quicksort greater)

View file

@ -0,0 +1,18 @@
List do(
quickSort := method(
if(size > 1) then(
pivot := at(size / 2 floor)
return select(x, x < pivot) quickSort appendSeq(
select(x, x == pivot) appendSeq(select(x, x > pivot) quickSort)
)
) else(return self)
)
quickSortInPlace := method(
copy(quickSort)
)
)
lst := list(5, -1, -4, 2, 9)
lst quickSort println # ==> list(-4, -1, 2, 5, 9)
lst quickSortInPlace println # ==> list(-4, -1, 2, 5, 9)

Some files were not shown because too many files have changed in this diff Show more