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)
通过交换数组中的元素,以避免更多数组的内存分配,以获得更高效的快速排序算法。
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)
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; })));
}
更快的方式
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));
}
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
#include
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);
}
#include
#include // for std::partition
#include // 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>());
}
//
// 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 Sort {
using System;
using System.Diagnostics;
class QuickSort<T> where T : IComparable {
#region Constants
private const Int32 INSERTION_LIMIT_DEFAULT = 12;
#endregion
#region Properties
public Int32 InsertionLimit { get; set; }
private Random Random { get; set; }
private T Median { get; set; }
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(Int32 insertionLimit, Random random) {
this.InsertionLimit = insertionLimit;
this.Random = random;
}
public QuickSort(Int32 insertionLimit)
: this(insertionLimit, new Random()) {
}
public QuickSort()
: this(INSERTION_LIMIT_DEFAULT) {
}
#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;
pivot(entries);
partition(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;
}
}
}
private void pivot(T[] entries) {
//
// An odd sample size is chosen based on the log of the interval size.
// The median of a randomly chosen set of samples is then returned as
// an estimate of the true median.
//
var length = Right + 1 - Left;
var logLen = (Int32)Math.Log10(length);
var pivotSamples = 2 * logLen + 1;
var sampleSize = Math.Min(pivotSamples, length);
var last = Left + sampleSize - 1;
// Sample without replacement
for (var first = Left; first <= last; first++) {
// Random sampling avoids pathological cases
var random = Random.Next(first, Right + 1);
Swap(entries, first, random);
}
InsertionSort<T>.Sort(entries, Left, last);
Median = entries[Left + sampleSize / 2];
}
private void partition(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(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[] 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--);
}
public static void Swap(T[] entries, Int32 index1, Int32 index2) {
if (index1 != index2) {
var entry = entries[index1];
entries[index1] = entries[index2];
entries[index2] = entry;
}
}
#endregion
}
#region Insertion Sort
static class InsertionSort<T> where T : IComparable {
public static void Sort(T[] entries, Int32 first, Int32 last) {
for (var index = first + 1; index <= last; index++)
insert(entries, first, index);
}
private static void insert(T[] entries, Int32 first, Int32 index) {
var entry = entries[index];
while (index > first && entries[index - 1].CompareTo(entry) > 0)
entries[index] = entries[--index];
entries[index] = entry;
}
}
#endregion
}
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"));
}
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)
}
public static <E extends Comparable<? super E>> List<E> quickSort(List<E> arr) {
if (arr.isEmpty())
return arr;
else {
E pivot = arr.get(0);
List<E> less = new LinkedList<E>();
List<E> pivotList = new LinkedList<E>();
List<E> more = new LinkedList<E>();
// Partition
for (E i: arr) {
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;
}
}
实用版
public static <E extends Comparable<E>> List<E> sort(List<E> col) {
if (col == null || col.isEmpty())
return Collections.emptyList();
else {
E pivot = col.get(0);
Map<Integer, List<E>> grouped = col.stream()
.collect(Collectors.groupingBy(pivot::compareTo));
return Stream.of(sort(grouped.get(1)), grouped.get(0), sort(grouped.get(-1)))
.flatMap(Collection::stream).collect(Collectors.toList());
}
}
function sort(array, less) {
function swap(i, j) {
var t = array[i];
array[i] = array[j];
array[j] = t;
}
function quicksort(left, right) {
if (left < right) {
var pivot = array[left + Math.floor((right - left) / 2)],
left_new = left,
right_new = right;
do {
while (less(array[left_new], pivot)) {
left_new += 1;
}
while (less(pivot, array[right_new])) {
right_new -= 1;
}
if (left_new <= right_new) {
swap(left_new, right_new);
left_new += 1;
right_new -= 1;
}
} while (left_new <= right_new);
quicksort(left, right_new);
quicksort(left_new, right);
}
}
quicksort(0, array.length - 1);
return array;
}
实用版
//ES5
(function () {
'use strict';
// quickSort :: (Ord a) => [a] -> [a]
function quickSort(xs) {
if (xs.length) {
var h = xs[0],
t = xs.slice(1),
lessMore = partition(function (x) {
return x <= h;
}, t),
less = lessMore[0],
more = lessMore[1];
return [].concat.apply(
[], [quickSort(less), h, quickSort(more)]
);
} else return [];
}
// partition :: Predicate -> List -> (Matches, nonMatches)
// partition :: (a -> Bool) -> [a] -> ([a], [a])
function partition(p, xs) {
return xs.reduce(function (a, x) {
return (
a[p(x) ? 0 : 1].push(x),
a
);
}, [[], []]);
}
return quickSort([11.8, 14.1, 21.3, 8.5, 16.7, 5.7])
})();
//ES6
Array.prototype.quick_sort = function () {
if (this.length < 2) { return this; }
var pivot = this[Math.round(this.length / 2)];
return this.filter(x => x < pivot)
.quick_sort()
.concat(this.filter(x => x == pivot))
.concat(this.filter(x => x > pivot).quick_sort());
};
function quicksort!(A,i=1,j=length(A))
if j > i
pivot = A[rand(i:j)] # random element of A
left, right = i, j
while left <= right
while A[left] < pivot
left += 1
end
while A[right] > pivot
right -= 1
end
if left <= right
A[left], A[right] = A[right], A[left]
left += 1
right -= 1
end
end
quicksort!(A,i,right)
quicksort!(A,left,j)
end
return A
end
import java.util.*
import java.util.Comparator
fun <T> quickSort(a: List<T>, c: Comparator<T>): ArrayList<T> {
if (a.isEmpty()) return ArrayList(a)
val boxes = Array(3, { ArrayList<T>() })
fun normalise(i: Int) = i / Math.max(1, Math.abs(i))
a.forEach { boxes[normalise(c.compare(it, a[0])) + 1].add(it) }
arrayOf(0, 2).forEach { boxes[it] = quickSort(boxes[it], c) }
return boxes.flatMapTo(ArrayList<T>()) { it }
}
其他版本
fun <T : Comparable<T>> quicksort(list: List<T>): List<T> {
if (list.isEmpty()) return emptyList()
val head = list.first()
val tail = list.takeLast(list.size - 1)
val (less, high) = tail.partition { it < head }
return less + head + high
}
fun main(args: Array<String>) {
val nums = listOf(9, 7, 9, 8, 1, 2, 3, 4, 1, 9, 8, 9, 2, 4, 2, 4, 6, 3)
println(quicksort(nums))
}
function sortedArray = quickSort(array)
if numel(array) <= 1 %If the array has 1 element then it can't be sorted
sortedArray = array;
return
end
pivot = array(end);
array(end) = [];
%Create two new arrays which contain the elements that are less than or
%equal to the pivot called "less" and greater than the pivot called
%"greater"
less = array( array <= pivot );
greater = array( array > pivot );
%The sorted array is the concatenation of the sorted "less" array, the
%pivot and the sorted "greater" array in that order
sortedArray = [quickSort(less) pivot quickSort(greater)];
end
sub quick_sort {
return @_ if @_ < 2;
my $p = splice @_, int rand @_, 1;
quick_sort(grep $_ < $p, @_), $p, quick_sort(grep $_ >= $p, @_);
}
my @a = (4, 65, 2, -31, 0, 99, 83, 782, 1);
@a = quick_sort @a;
print "@a\n";
# Empty list sorts to the empty list
multi quicksort([]) { () }
# Otherwise, extract first item as pivot...
multi quicksort([$pivot, *@rest]) {
# Partition.
my $before := @rest.grep(* before $pivot);
my $after := @rest.grep(* !before $pivot);
# Sort the partitions.
flat quicksort($before), $pivot, quicksort($after)
}
function quicksort($arr){
$lte = $gt = array();
if(count($arr) < 2){
return $arr;
}
$pivot_key = key($arr);
$pivot = array_shift($arr);
foreach($arr as $val){
if($val <= $pivot){
$lte[] = $val;
} else {
$gt[] = $val;
}
}
return array_merge(quicksort($lte),array($pivot_key=>$pivot),quicksort($gt));
}
$arr = array(1, 3, 5, 7, 9, 8, 6, 4, 2);
$arr = quicksort($arr);
echo implode(',',$arr);
方法一
Function SortThree( [Array] $data )
{
if( $data[ 0 ] -gt $data[ 1 ] )
{
if( $data[ 0 ] -lt $data[ 2 ] )
{
$data = $data[ 1, 0, 2 ]
} elseif ( $data[ 1 ] -lt $data[ 2 ] ){
$data = $data[ 1, 2, 0 ]
} else {
$data = $data[ 2, 1, 0 ]
}
} else {
if( $data[ 0 ] -gt $data[ 2 ] )
{
$data = $data[ 2, 0, 1 ]
} elseif( $data[ 1 ] -gt $data[ 2 ] ) {
$data = $data[ 0, 2, 1 ]
}
}
$data
}
Function QuickSort( [Array] $data, $rand = ( New-Object Random ) )
{
$datal = $data.length
if( $datal -gt 3 )
{
[void] $datal--
$median = ( SortThree $data[ 0, ( $rand.Next( 1, $datal - 1 ) ), -1 ] )[ 1 ]
$lt = @()
$eq = @()
$gt = @()
$data | ForEach-Object { if( $_ -lt $median ) { $lt += $_ } elseif( $_ -eq $median ) { $eq += $_ } else { $gt += $_ } }
$lt = ( QuickSort $lt $rand )
$gt = ( QuickSort $gt $rand )
$data = @($lt) + $eq + $gt
} elseif( $datal -eq 3 ) {
$data = SortThree( $data )
} elseif( $datal -eq 2 ) {
if( $data[ 0 ] -gt $data[ 1 ] )
{
$data = $data[ 1, 0 ]
}
}
$data
}
QuickSort 5,3,1,2,4
QuickSort 'e','c','a','b','d'
QuickSort 0.5,0.3,0.1,0.2,0.4
$l = 100; QuickSort ( 1..$l | ForEach-Object { $Rand = New-Object Random }{ $Rand.Next( 0, $l - 1 ) } )
方法二
function quicksort($array) {
$less, $equal, $greater = @(), @(), @()
if( $array.Count -gt 1 ) {
$pivot = $array[0]
foreach( $x in $array) {
if($x -lt $pivot) { $less += @($x) }
elseif ($x -eq $pivot) { $equal += @($x)}
else { $greater += @($x) }
}
$array = (@(quicksort $less) + @($equal) + @(quicksort $greater))
}
$array
}
$array = @(60, 21, 19, 36, 63, 8, 100, 80, 3, 87, 11)
"$(quicksort $array)"
def quickSort(arr):
less = []
pivotList = []
more = []
if len(arr) <= 1:
return arr
else:
pivot = arr[0]
for i in arr:
if i < pivot:
less.append(i)
elif i > pivot:
more.append(i)
else:
pivotList.append(i)
less = quickSort(less)
more = quickSort(more)
return less + pivotList + more
a = [4, 65, 2, -31, 0, 99, 83, 782, 1]
a = quickSort(a)
qsort <- function(v) {
if ( length(v) > 1 )
{
pivot <- (min(v) + max(v))/2.0 # Could also use pivot <- median(v)
c(qsort(v[v < pivot]), v[v == pivot], qsort(v[v > pivot]))
} else v
}
N <- 100
vs <- runif(N)
system.time(u <- qsort(vs))
print(u)
class Array
def quick_sort
return self if length <= 1
pivot = self[0]
less, greatereq = self[1..-1].partition { |x| x < pivot }
less.quick_sort + [pivot] + greatereq.quick_sort
end
end
或
class Array
def quick_sort
return self if length <= 1
pivot = sample
group = group_by{ |x| x <=> pivot }
group.default = []
group[-1].quick_sort + group[0] + group[1].quick_sort
end
end
或
class Array
def quick_sort
h, *t = self
h ? t.partition { |e| e < h }.inject { |l, r| l.quick_sort + [h] + r.quick_sort } : []
end
end
fn main() {
println!("Sort numbers in descending order");
let mut numbers = [4, 65, 2, -31, 0, 99, 2, 83, 782, 1];
println!("Before: {:?}", numbers);
quick_sort(&mut numbers, &|x,y| x > y);
println!("After: {:?}\n", numbers);
println!("Sort strings alphabetically");
let mut strings = ["beach", "hotel", "airplane", "car", "house", "art"];
println!("Before: {:?}", strings);
quick_sort(&mut strings, &|x,y| x < y);
println!("After: {:?}\n", strings);
println!("Sort strings by length");
println!("Before: {:?}", strings);
quick_sort(&mut strings, &|x,y| x.len() < y.len());
println!("After: {:?}", strings);
}
fn quick_sort(v: &mut [T], f: &F)
where F: Fn(&T,&T) -> bool
{
let len = v.len();
if len >= 2 {
let pivot_index = partition(v, f);
quick_sort(&mut v[0..pivot_index], f);
quick_sort(&mut v[pivot_index + 1..len], f);
}
}
fn partition(v: &mut [T], f: &F) -> usize
where F: Fn(&T,&T) -> bool
{
let len = v.len();
let pivot_index = len / 2;
v.swap(pivot_index, len - 1);
let mut store_index = 0;
for i in 0..len - 1 {
if f(&v[i], &v[len - 1]) {
v.swap(i, store_index);
store_index += 1;
}
}
v.swap(store_index, len - 1);
store_index
}
def sort(xs: List[Int]): List[Int] = {
xs match {
case Nil => Nil
case x :: xx => {
// Arbitrarily partition list in two
val (lo, hi) = xx.partition(_ < x)
// Sort each half
sort(lo) ++ (x :: sort(hi))
}
}
}
func quicksort<T where T : Comparable>(inout elements: [T], range: Range<Int>) {
if (range.endIndex - range.startIndex > 1) {
let pivotIndex = partition(&elements, range)
quicksort(&elements, range.startIndex ..< pivotIndex)
quicksort(&elements, pivotIndex+1 ..< range.endIndex)
}
}
func quicksort<T where T : Comparable>(inout elements: [T]) {
quicksort(&elements, indices(elements))
}
/**
Generic quicksort function using typescript generics.
Follows quicksort as done in CLRS.
*/
export type Comparator = (o1: T, o2: T) => number;
export function quickSort(array: T[], compare: Comparator) {
if (array.length <= 1 || array == null) {
return;
}
sort(array, compare, 0, array.length - 1);
}
function sort(
array: T[], compare: Comparator, low: number, high: number) {
if (low < high) {
const partIndex = partition(array, compare, low, high);
sort(array, compare, low, partIndex - 1);
sort(array, compare, partIndex + 1, high);
}
}
function partition(
array: T[], compare: Comparator, low: number, high: number): number {
const pivot: T = array[high];
let i: number = low - 1;
for (let j = low; j <= high - 1; j++) {
if (compare(array[j], pivot) == -1) {
i = i + 1;
swap(array, i, j)
}
}
if (compare(array[high], array[i + 1]) == -1) {
swap(array, i + 1, high);
}
return i + 1;
}
function swap(array: T[], i: number, j: number) {
const newJ: T = array[i];
array[i] = array[j];
array[j] = newJ;
}
export function testQuickSort(): void {
function numberComparator(o1: number, o2: number): number {
if (o1 < o2) {
return -1;
} else if (o1 == o2) {
return 0;
}
return 1;
}
let tests: number[][] = [
[], [1], [2, 1], [-1, 2, -3], [3, 16, 8, -5, 6, 4], [1, 2, 3, 4, 5, 6],
[1, 2, 3, 4, 5]
];
for (let testArray of tests) {
quickSort(testArray, numberComparator);
console.log(testArray);
}
}
更多代码,持续更新!
整理自网络。