快速排序

快速排序,没什么可说的,直接看代码:

先来看 Lua 的,代码取自 Lua5.1.4 的 test 目录的 sort.lua

-- extracted from Programming Pearls, page 110
function qsort(x,l,u,f)
 if l<u then
  local m=math.random(u-(l-1))+l-1    -- choose a random pivot in range l..u
  x[l],x[m]=x[m],x[l]    -- swap pivot to first position
  local t=x[l]    -- pivot value
  m=l
  local i=l+1
  while i<=u do
    -- invariant: x[l+1..m] < t <= x[m+1..i-1]
    if f(x[i],t) then
      m=m+1
      x[m],x[i]=x[i],x[m]    -- swap x[i] and x[m]
    end
    i=i+1
  end
  x[l],x[m]=x[m],x[l]    -- swap pivot to a valid place
  -- x[l+1..m-1] < x[m] <= x[m+1..u]
  qsort(x,l,m-1,f)
  qsort(x,m+1,u,f)
 end
end

再来看 C 的,长得差不多,代码来自维基百科。

#include <stdio.h>
//交换位置
void swap(int *a, int *b)
{
        int  tmp = *a;
        *a = *b;
        *b = tmp;
}
//分治
int partition(int *ary, int len, int pivot_i)
{
        int i = 0;
        int small_len = pivot_i;
        int pivot = ary[pivot_i];
        swap(&ary[pivot_i], &ary[pivot_i + (len - 1)]);
        for (; i < len; i++)
        {
                if (ary[pivot_i + i]<pivot)
                {
                        swap(&ary[pivot_i + i], &ary[small_len]);
                        small_len++;
                }
        }
        swap(&ary[pivot_i + len - 1], &ary[small_len]);
        return small_len;
}
void quick_sort(int *ary, int len)
{
        if (len == 0 || len == 1)
                return;
        int small_len = partition(ary, len, 0);
        quick_sort(ary, small_len);
        quick_sort(&ary[small_len + 1], len - small_len - 1);
}
int main(void) {
        int ary[] = { 2, 4, 2, 5, 3, 5, 3, 1, 7, 6 };
        int len = sizeof(ary) / sizeof(ary[0]);
        quick_sort(ary, len);
        return 0;
}

再来看一个 C# 的,这也是比较常见的快排的写法:

static int Partition(int[] array, int left, int right)
{
    int pivot = array[left];
    while (left < right)
    {
        while (left < right && array[right] > pivot) right--;
        array[left] = array[right];
        while (left < right && array[left] <= pivot) left++;
        array[right] = array[left];
    }
    array[left] = pivot;
    return left;
}
static void QuickSort(int[] array, int left, int right)
{
    if (left >= right) return;
    int index = Partition(array, left, right);
    QuickSort(array, left, index - 1);
    QuickSort(array, index + 1, right);
}

主要注意的地方是,在分治的时候两个 while 里比较大小的时候,小于用的是小于等于,大于用的是大于。
也就是分治的结果是左边小于等于 pivot , 右边大于 pivot 。

最后看来维基百科里的这个很漂亮的 C# 实现:

public static void Sort(int[] numbers)
{
    Sort(numbers, 0, numbers.Length - 1);
}
private static void Sort(int[] numbers, int left, int right)
{
    if (left < right)
    {
        int middle = numbers[(left + right) / 2];
        int i = left - 1;
        int j = right + 1;
        while (true)
        {
            while (numbers[++i] < middle) ;
            while (numbers[--j] > middle) ;
            if (i >= j)
                break;
            Swap(numbers, i, j);
        }
        Sort(numbers, left, i - 1);
        Sort(numbers, j + 1, right);
    }
}
private static void Swap(int[] numbers, int i, int j)
{
    int number = numbers[i];
    numbers[i] = numbers[j];
    numbers[j] = number;
}

注意它是如何找 pivot 的,及如何 while 里的递增(减),交换的。
漂亮!

关于快排的其它语言实现,可以参见维基百科。
另,这里有一篇刘未鹏的博文 "快排为什么那样快" ,链接
http://mindhacks.cn/2008/06/13/why-is-quicksort-so-quick/

你可能感兴趣的:(快速排序)