美文网首页
1.快速排序

1.快速排序

作者: 吴金君 | 来源:发表于2018-07-24 15:48 被阅读0次

1.快速排序

1.1快速排序的思想和复杂度

快排思想

  1. 快速排序是在数组中选一个数字,然后按照这个数字将数组分为前后两部分,前半部分都比这个数字小,后半部分都比这个数字大。
  2. 对第1步中的前半部分和后半部分分别作为一个独立的数组,按照第1步的规则进行切分。通过递归对整个数组排序。

用代码描述:

    void sort(vector<int> &vec)
    {
        sort(vec,0,vec.size()-1);
    }
    void sort(vector<int> &vec,int lo,int hi)
    {
        if(hi<=lo)return;
        int j=partition(vec,lo,hi); //选择切分数组的参考元素
        sort(vec,lo,j-1);
        sort(vec,j+1,hi);
    }

时间和复杂度

时间复杂度如表所示

算法 平均情况 最好情况 最差情况
快排 O(NlogN) O(NlogN) O(N^2)

空间复杂度:O(NlogN)

1.2快速排序的操作

假设有这样一个数组:

下标 0 1 2 3 4 5 6 7 8 9
数组 4 3 5 2 1 9 8 6 0 7

对这个数组进行快速排序,我们首先要选择一个数在做切分,基本的快速排序选择数组vec的第一个数字作切分,我们选择下标为0,数字为v=4的元素作为切分依据。随后,对数组进行前后两部分的切分操作。具体来说,需要从左到右扫描的同时从右向左扫描。从左到右扫描的指针设置为i,从右到左扫描的指针设置为j。

指针 i j
下标 0 1 2 3 4 5 6 7 8 9
数组 4 3 5 2 1 9 8 6 0 7

1. 从左向右搜索大于切分元素的元素

从左到右的扫描过程中如果指针i向右移动的时候,vec[i]比参考元素v=4小,那么就继续向右移动。如果vec[i]比参考元素v=4大,那么就记录下标i,需要将vec[i]这个数字从数组vec的前半部分丢到后半部分。这里就有个问题了,需要把vec[i]丢到后半部分的哪个位置呢?不要急,丢到哪里需要我们从右向左扫描的时候找出这个位置。

指针 i j
下标 0 1 2 3 4 5 6 7 8 9
数组 4 3 5 2 1 9 8 6 0 7

(Q:后半部分和前半部分如何定义和理解呢?A:假设我们已经完成了一次扫描,那么分别向左和向右移动的下标i和下标j会相遇。下标i扫描所覆盖的区域就是这次扫描的前半部分,下标j扫描所覆盖的区域就是后半部分,这里有个概念即可)

2. 从右向左搜索小于切分元素的元素

从右到左的扫描过程中如果指针j向左移动的时候,vec[j]比参考元素v=4大,那么就继续向左移动。如果vec[j]比参考元素v=4小,那么就记录下标j,需要将vec[j]这个数字从数组vec的后半部分丢到前半部分。现在,我们就找到了从左向后扫描时丢过来的数字该放到哪里了。我们通过交换vec[i]和vec[j]两个数字就完成了一次扫描中的交换。

需要交换的两个数字找到了

指针 i j
下标 0 1 2 3 4 5 6 7 8 9
数组 4 3 5 2 1 9 8 6 0 7

交换两个数字

指针 i j
下标 0 1 2 3 4 5 6 7 8 9
数组 4 3 0 2 1 9 8 6 5 7

3. 重复第1步和第2步

在一次扫描中,需要把前半部分和后半部分都扫描一遍,直到下标i和下标j相遇。在扫描过程中,需要不断地进行第1步和第2步。所以i==j是边界条件(a)(b),i>=j也是边界条件(c)。边界条件的逻辑是这样的:
(a)从左向右扫描,如果扫描到了最右端,那么达到边界条件,终止从左向右的扫描。
(b)从右向左扫描,如果扫描到了最左端,那么达到边界条件,终止从右向左的扫描。
(c)i从向左向右扫描,j从右向左扫描,i肯定小于j,如果相遇了那么就是i==j,终止这一次扫描。

4. 切分元素归位

完成一次扫描后,还需要将参考的数字v放在扫描完成的前半部分和后半部分的中间。

第一次扫描,交换了两个数字,最后把参考元素和前后两部分中间的元素互换

指针 i j
下标 0 1 2 3 4 5 6 7 8 9
数组 4 3 0 2 1 9 5 6 5 7
数组 1 3 0 2 4 9 8 6 5 7

OK, 可以上代码了。

1.3 C++代码

#include <iostream>
#include <vector>
using namespace std;

class Sort
{
public:
    void sort(vector<int> &vec)
    {
        sort(vec,0,vec.size()-1);
    }
    void sort(vector<int> &vec,int lo,int hi)
    {
        if(hi<=lo)return;
        int j=partition(vec,lo,hi);
        sort(vec,lo,j-1);
        sort(vec,j+1,hi);

    }
    void show(vector<int> &vec)
    {
        for(int i=0;i<vec.size();i++)
        {
            cout << vec[i] << " ";
        }
        cout << endl;
    }
    vector<int> init()
    {
        vector<int> vec;
        int arr[10]={4,3,5,2,1,9,8,6,0,7};
        vec.insert(vec.begin(),arr,arr+10);
        cout <<"ori:"<<endl;
        show(vec);
        return vec;
    }
    bool checkorder(vector<int> &vec)
    {
        for(int i=0;i<vec.size()-1;i++)
        {
            if(vec[i]>vec[i+1])return false;
        }
        return true;
    }
private:
    void exch(vector<int> &vec,int a,int b)
    {
        int tmp;
        tmp=vec[a];
        vec[a]=vec[b];
        vec[b]=tmp;
    }
    int partition(vector<int> &vec,int lo,int hi)
    {
        int v=vec[lo];
        int i=lo,j=hi+1;
        cout <<"scan round, before scan:"<<endl;
        show(vec);
        while(true)
        {
            while(vec[++i]<v){if(i==hi)break;}
            while(v<vec[--j]){if(j==lo)break;}
            if(i>=j)break;
            exch(vec,i,j);
        }
        cout <<"scan round, after scan:"<<endl;
        show(vec);
        exch(vec,lo,j);
        cout <<"scan round, exchange reference values:"<<endl;
        show(vec);
        cout <<"-----------------------"<<endl;
        return j;
    }
};

int main()
{
    Sort sortob;
    vector<int> mvec=sortob.init();
    sortob.sort(mvec);
    sortob.show(mvec);
    cout <<"--------result-------"<<endl;
    if(sortob.checkorder(mvec))
        sortob.show(mvec);
    else
    {
        cout << sortob.checkorder(mvec);
    }
    return 0;
}

输出结果:

image.png

相关文章

  • 常见的排序算法(2)

    要点 快速排序 归并排序 1.快速排序 2.归并排序

  • 1.快速排序

    1.快速排序 1.1快速排序的思想和复杂度 快排思想 快速排序是在数组中选一个数字,然后按照这个数字将数组分为前后...

  • [算法导论]-第七章-快速排序

    本章重点 1.快速排序 2.冒泡排序 3.希尔排序 1.快速排序 2.冒泡排序 3.希尔排序 希尔排序,也称递减增...

  • 排序方法

    1.选择排序 2.插入排序 3.冒泡排序 归并排序归并排序5.快速排序快速排序

  • Datawhale | 编程第6期 Test 3

    排序 1.实现归并排序、快速排序、插入排序、冒泡排序、选择排序、堆排序(选做) 归并排序 快速排序 插入排序 冒泡...

  • 冒泡排序与快速排序

    1.冒泡排序 2.快速排序

  • 手撕代码 之 快速排序

    1.实现快速排序算法 问题描述给定一个无序数组int[ ] a,使用快速排序算法进行排序。 解题思路对于快速排序,...

  • 快速排序算法(OC实现)

    1.快速排序的意义:快速排序是一种优雅的排序算法,快速排序使用分而治之的策略。(一种递归式问题解决方法),快速排序...

  • java快速学习排序---快排算法

    一、快速排序是(挖坑法)是挖坑填数 + 分治来实现。 1.快速排序的基本思想: 2.快速排序的图示: 3.快速排序的算法

  • 算法

    一. 排序算法 1.快速排序 快速排序是对冒泡排序的一种改进. 快速排序: 对于给定的一组数据, 选定其中的一个(...

网友评论

      本文标题:1.快速排序

      本文链接:https://www.haomeiwen.com/subject/mrfymftx.html