快速排序

快速排序(Quicksort)是对冒泡排序的一种改进。它的核心思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

快速排序一趟算法思想:

如果要对某含有n个元素的序列A进行排序。

快速排序的一趟算法思想是:

1.设置两个变量 i , j ,令 i = 0 ; j = n - 1 ;

2.以第一个数组元素作为关键数据,赋值给key,即 key = A[0];

3.从 j 开始向前搜索,即由后开始向前搜索(j - -),找到第一个小于key的值A[j],将A[j]和A[i]互换;

4.从 i 开始向后搜索,即由前开始向后搜索(i + +),找到第一个大于key的值A[i],将A[i]和A[j]互换;

5.重复第3、4步,直到 i = j 结束。

快速排序举例:

我们将以序列A:{ 6, 2, 7, 3, 8, 9, 5, 4 } 为例子,叙述一遍快速排序的排序算法流程。按照上述每一趟的算法思想,我们设置两个变量 i , j ,显而得知 序列长度 n = 8 , i = 0,j = 7

第一趟:

首先,取该序列的第一个元素 A[0]为关键元素,赋值为key,key = 6。

1.1:从 j = 7开始往前寻找,此时A[j]=4,小于key,符合要求,则交换A[i]和A[j],那么此时 i=0,j=7,序列A:{ 4, 2, 7, 3, 8, 9, 5, 6 }

1.2:从 i = 0开始往后寻找,此时A[i]=4,小于key,不符合要求

1.3:i ++,i = 1,A[i]=2,小于key,不符合要求

1.4:i ++,i = 2,A[i]=7,大于key,符合要求,则交换A[i]和A[j],那么此时 i=2,j=7,序列A:{ 4, 2, 6, 3, 8, 9, 5, 7 }

1.5:j = 7 ,A[j]=7,大于key,不符合要求

1.6:j - -,j = 6,A[j]=5,小于key,符合要求,交换A[i]和A[j],那么此时 i=2 ,j=6,序列A:{ 4, 2, 5, 3, 8, 9, 6, 7 }

1.7:i = 2,A[i]=5,小于key,不符合要求

1.8:i ++,i = 3,A[i]=3,小于key,不符合要求

1.9:i ++,i = 4,A[i]=8,大于key,符合要求,交换A[i]和A[j],那么此时 i=4,j=6,序列A:{ 4, 2, 5, 3, 6, 9, 8, 7 }

1.10:j=6,A[j]=8,大于key,不符合要求

1.11:j - -,j = 5,A[j]=9,大于key,不符合要求

1.12:j - -,j = 4,此时 i = j = 4 ,一趟终于结束了!!!

细心的朋友一定发现了一个规律,我们选择 key = 6,结果,大于key的元素,都跑到了key的右边,小于key的元素,都跑到了key的左边。。

没错,这就是次算法的核心思想。

第二趟:

此时,第一趟走完后,key左边是一个序列,我们称为A1:{ 4, 2, 5, 3 },key右边是一个序列,我们成为A2:{ 9, 8, 7 },此时分别对这两个序列进行快速排序,那么第一个序列的关键数据 key = A1[0] = 4,

第二个序列的关键数据 key = A2[0] = 9,然后递归调用一趟的算法流程。

第3,4 ...... n-1 趟:

此后,每趟结束都会产生新的序列,继续递归。

第 n 趟(最后一趟):

继续分组到无法分组为止。这里的无法分组就是,每个组都是一个元素,也就是 i = j = 1。

快速排序代码实现:

#include<stdio.h>

//输出数组
void printArr(int a[], int n)
{
    for (int i = 0; i < n; i++)
    {
        printf("%d--", a[i]);
    }
    printf("
");
}

//快速排序
void QuickSort(int a[], int left, int right)
{
    if (left >= right) {
        return;
    }

    // 定义两个标识
    int i = left;
    int j = right;
    int key = a[left];//将序列的第一个元素设为基数
    int temp;

    while (i < j)
    {
        while (i < j && a[j] >= key)
        {
            j--;
        }
        if (i != j)//如果i j没有相遇,交换位置
        {
            temp = a[i];
            a[i] = a[j];
            a[j] = temp;
        }
        while (i < j && a[i] <= key)
        {
            i++;
        }
        if (i != j)//如果i j没有相遇,交换位置
        {
            temp = a[i];
            a[i] = a[j];
            a[j] = temp;
        }
        else
        {
            printArr(a, 8);
        }
    }

    QuickSort(a, left, i - 1);
    QuickSort(a, i + 1, right);

}

void main()
{

    int a1[8] = { 6, 2, 7, 3, 8, 9, 5, 4 };
    QuickSort(a1, 0, 7);

    getchar();
}

运行结果:

 

从结果中可以看出,这个序列共需要5趟,其中第一趟所得结果与我们上述演算结果{ 4, 2, 5, 3, 6, 9, 8, 7 }一致。

时间复杂度:

最坏情况:O(n^2)

最优情况:O(nlogn)

平均情况:O(nlogn)

稳定性:

快速排序是一种不稳定的排序算法。

原文地址:https://www.cnblogs.com/zh1996/p/8351801.html