快速排序

部分内容转自坐在马桶上看算法:快速排序啊哈算法关于快速排序法为什么一定要从右边开始的原因

快速排序的思想是选一个基准数,然后找到这个基准数在数组里的位置,将大于它的放到它的右边,小于它的放到它的左边。

指针从两边向中间跑:

static void Main(string[] args)
{
    int[] a = { 45, 80, 55, 40, 42, 85 };
    quickSort(a, 0, a.Length - 1);
    foreach (var b in a)
    {
        Console.WriteLine(b.ToString());
    }
    Console.ReadLine();
}
static void quickSort(int[] array, int left, int right)
{
    int i, j, temp;
    if (left > right)
        return;
    temp = array[left];
    i = left;
    j = right;
    while (i != j)
    {
        while (array[j] >= array[left] && j > i)
            j--;
        while (array[i] <= array[left] && j > i)
            i++;
        temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
    temp = array[i];
    array[i] = array[left];
    array[left] = temp;
    quickSort(array, left, i - 1);
    quickSort(array, i + 1, right);
}

指针从左往右跑:

public static int Partition(int[] a, int p, int r)
{
    int x = a[r];
    int i = p;
    int temp;
    for (int j = p; j <= r; j++)
    {
        if (a[j] < x)
        {
            temp = a[j];
            a[j] = a[i];
            a[i] = temp;
            i++;
        }
    }
    temp = a[r];
    a[r] = a[i];
    a[i] = temp;
    return i;
}
public static void QuickSort(int[] a, int p, int r)
{
    if (p < r)
    {
        int q = Partition(a, p, r);
        QuickSort(a, p, q - 1);
        QuickSort(a, q + 1, r);
    }
}
static void Main(String[] args)
{
    int[] a = { 7, 10, 3, 5, 4, 6, 2, 8, 9, 9 };
    QuickSort(a, 0, 9);
    for (int i = 0; i < a.Length; i++)
        Console.WriteLine(a[i].ToString());
    Console.ReadLine();
}

快速排序详解:

关于为什么要让哨兵j先动:

while(arr[j]>=temp&&i<j){
   j--;
}
while(arr[i]<=temp&&i<j){
   i++;
}
这里两个while的顺序是不能改变的,想一想:
假设对如下进行排序:
如上图,6在左,9在右  我们将6作为基数。
假设从左边开始(与正确程序正好相反)
于是i 就会移动到现在的数字7那个位置停下来,而j原来在数字9那个位置 ,因为
while(arr[j]>=temp&&i<j)
于是,j 也会停留在数字7那个位置,于是问题来了。当你最后交换基数6与7时,不对呀!!。
问题在于当我们先从在边开始时,那么 i 所停留的那个位置肯定是大于基数6的,而在上述例子中,为了满足 i<j 于是 j也停留在7的位置
但最后交换回去的时候,7就到了左边,不行,因为我们原本 交换后数字6在边应该是全部小于6,右边全部大于6.但现在不行了。
于是,我们必须从右边开始,也就是从基数的对面开始。

 

posted @ 2018-02-26 17:45  双子牧场主  阅读(159)  评论(0)    收藏  举报