排序算法——快速排序【代码实现】

伪代码

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)

ActionScript

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));
}

BASIC

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

C

#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);
}

C++

#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>());
}

C#

//
// 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
}

Dart

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"));
}

Go

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)
}

Java

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());
    }
}

JavaScript

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());
};

Julia

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

Kotlin

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))
}

MATLAB

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

Perl

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";

Perl 6

# 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)
 }

PHP

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);

PowerShell

方法一

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)"

Python

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)

R

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)

Ruby

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

Rust

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
}

Scala

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))
      }
    }
  }

Swift

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))
}

TypeScript

/**
  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);
  }
}

更多代码,持续更新!
整理自网络。

你可能感兴趣的:(代码实现,算法)