关于快速排序的N种实现方法

快速排序思路

设要排序的 数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。值得注意的是,快速排序不是一种稳定的 排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。
一趟快速排序的算法是:
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; (3,4步中,没找到符合条件的值,即3中A[j]不小于 key,4中A[i]不大于 key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。

实现方法

快速排序解法一(剑指offer 80页)

以data[end]为基准进行快速排序(原书上是随机选择一个位置index,将data[index]与data[end]元素调换位置,再以end为基准进行排序,此处为了对比清晰,直接以data[end]为基准),指针small=start-1、index=start,index指针从头开始遍历直到index>=end。遍历时,每次判断data[index]是否小于data[end],若是,small指针也往前一步,然后判断一下index与small是否相等,若不等(说明出现大于data[end]的数,把它往右移,如9和3,4,5互换),交换data[index]和data[small]。直到index遍历结束,small往前一步(因为当前data[small]是比data[end]小的数,所以需要往前一步,使得与data[end]交换之后,比data[end]小的数都在它左边),交换data[small]和data[end]。以small位置为中心,再以同样步骤递归(start,small-1)和(small+1,end)部分。


#include <iostream>
#include <stdio.h>
#include  <stdexcept>
#include <time.h>
#include<stdlib.h>


void Swap(int*a, int*b)
{
    int temp;
    temp = *a;
    *a = *b;
    *b = temp;
}

int Partition(int data[], int length, int start, int end)
{
    if (data == nullptr || length <= 0 || start < 0 || end >= length)
        throw "invalid parameters";


    int small = start - 1;
    for (int index = start; index < end; ++index)
    {
        if (data[index] < data[end])
        {
            ++small;
            if (small != index)
                Swap(&data[index], &data[small]);
        }
    }
    ++small;
    Swap(&data[small], &data[end]);

    return small;
}

void QuickSort(int data[], int length, int start, int end)
{
    if (start == end)
        return;
    int index = Partition(data, length, start, end);
    if (index > start)
        QuickSort(data, length, start, index -1);
    if (index < end)
        QuickSort(data, length, index + 1, end);
}

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

    for (int i = 0; i < 10;i++)
    {
        printf("%4d",data[i]);
    }
}

快速排序解法二(数据结构274页 严蔚敏版

以data[first]为基准,last先从后向前搜索,发现比基准小的,data[first]=data[last];first从前向后搜索,发现比基准大的,data[last]=data[first];直到first与last重逢,将key赋值给data[first]。以first为中心,递归(low,first-1)和(first+1,high)。


#include <iostream>

using namespace std;

void Qsort(int a[], int low, int high)
{
    if(low >= high)
    {
        return;
    }
    int first = low;
    int last = high;
    int key = a[first];/*用字表的第一个记录作为枢轴*/

    while(first < last)
    {
        while(first < last && a[last] >= key)
        {
            --last;
        }

        a[first] = a[last];/*将比第一个小的移到低端*/

        while(first < last && a[first] <= key)
        {
            ++first;
        }

        a[last] = a[first];
/*将比第一个大的移到高端*/
    }
    a[first] = key;/*枢轴记录到位*/
    Qsort(a, low, first-1);
    Qsort(a, first+1, high);
}
int main()
{
    int a[] = {6,1,2,7,9,3,4,5,10,8};

    Qsort(a, 0, sizeof(a) / sizeof(a[0]) - 1);/*这里原文第三个参数要减1否则内存越界*/

    for(int i = 0; i < sizeof(a) / sizeof(a[0]); i++)
    {
        cout << a[i] << " ";
    }

    return 0;
}/*参考数据结构p274(清华大学出版社,严蔚敏)*/

快速排序解法三(链接

以data[first]为基准,last先从后向前搜索,发现比基准小的,停下;first从前向后搜索,发现比基准大的,停下,交换data[last]和data[first];直到first与last重逢。以first为中心,递归(low,first-1)和(first+1,high)。


快速排序解法四(链接

以data[first]为基准,last先从后向前搜索,发现比基准小的,交换data[last]和data[first];first从前向后搜索,发现比基准大的,交换data[last]和data[first];直到first与last重逢。以first为中心,递归(low,first-1)和(first+1,high)。

#include <iostream>

using namespace std;

void Swap(int*a, int*b)
{
    int temp;
    temp = *a;
    *a = *b;
    *b = temp;
}

void Qsort(int a[], int low, int high)
{
    if(low >= high)
    {
        return;
    }
    int first = low;
    int last = high;
    int key = a[first];/*用字表的第一个记录作为枢轴*/

    while(first < last)
    {
        while(first < last && a[last] >= key)
        {
            --last;
        }

        Swap(&a[first], &a[last]);

        while(first < last && a[first] <= key)
        {
            ++first;
        }

        Swap(&a[first], &a[last]);

    }
    Qsort(a, low, first-1);
    Qsort(a, first+1, high);
}
int main()
{
    int a[] = {6,1,2,7,9,3,4,5,10,8};

    Qsort(a, 0, sizeof(a) / sizeof(a[0]) - 1);

    for(int i = 0; i < sizeof(a) / sizeof(a[0]); i++)
    {
        cout << a[i] << " ";
    }

    return 0;
}

四种方法的比较

1、剑指offer  采用两个指针,寻找比基准大的数,往后移,快排的思想不够直接。
2、数据结构严蔚敏 与4类似,但它不是交换,而是赋值,把小的赋值给data[first](从后往前),大的赋值给data[end](从前往后)
3、博客1 与4类似,但它是从后往前找到小于基准的数后,停下不做任何操作,等从前往后找到大于基准的数后,交换data[first]和data[end]
4、博客2

与2类似,它是直接交换data[first]和data[end](两个方向都是

与3类似,它不管从前往后、从后往前,每次寻找到符合要求的数后,交换data[first]和data[end]

猜你喜欢

转载自blog.csdn.net/qq_23142123/article/details/80440920
今日推荐