排序算法 快速排序【详细步骤图解】

1 篇文章 0 订阅
订阅专栏

快速排序

给定一个序列:22 33 49 47 33' 12 68 29

进行快速排序

主要思想

  • 从序列中,任选一个记录k作为轴值 pivot

    选择策略:

    • 第一个元素
    • 最后一个元素
    • 中间元素
    • 随机选择
  • 将剩余的元素,分割成 左子序列 L右子序列 R

  • L 中所有元素都 < k, R 中所有元素都 > k

  • 对 L 和 R递归进行快排,直到子序列中有 0 个 或者 1 个元素,退出

图解

初始数组:

选定47为轴值pivot

image-20200522200024944

pivot与最后一个值29进行交换(pivot放到最后面

image-20200522200152016

接下来,以pivot=47为界,分成左子序列 L和右子序列 R

47大的都放在右边,比47小的都放在左边(用的交换)

遍历数组

  • 两个指针leftright
  • left != right的时候
    • arr[left]的,小于等于pivot,且left < right的时候,left右移
      • 如果leftright未相遇,把left的值赋给right对应的值
      • arr[right] = arr[left]
      • left指针停止移动,轮到right移动
    • arr[right]的值,大于等于pivot,且right > left的时候,right左移
      • 如果leftright未相遇。把right的值赋给left对应的值
      • arr[left] = arr[right]
      • right指针停止移动,轮到left移动
  • 注意:轴值用pivot保存

第一轮分割序列

image-20200522213014584
pivot=47和最后一个值互换

image-20200522205447912

22 <= 47left向右移动

image-20200522205623534

33 <= 47left向右移动

image-20200522205648022

49 > 47,不满足arr[left] <= pivot

left的值赋给right

arr[right] = arr[left]

image-20200522210144784

赋值过后,left不动,right向左移动

image-20200522211704648

68 >= 47,right向左移动

image-20200522211823993

12 < 47,不满足arr[right] >= pivot

right的值赋给left

arr[left] = arr[right]

image-20200522211941103

赋值过后,right不动,left向右移动

image-20200522212237784

29 < 47left向右移动

image-20200522212313112

33' < 47left向右移动

image-20200522215707618

向右移动后,left == right,退出循环

pivot赋给arr[left]

image-20200522215538138

至此,第一轮分割序列完成

第二轮分割序列 — 左子序列

经过第一轮分割,47左边的是左子序列,右边是右子序列

第二轮对左子序列分割,选择中间值作为pivot

image-20200522223949257

12和33'进行交换

image-20200522220137128

22 > 12,不满足arr[left] <= pivot

arr[left]赋给arr[right]

arr[right] = arr[left]

image-20200522220327264

赋值过后,left不动,right向左移动

29、33'、33都比12大,所以right一直移动到下图位置

image-20200522220446889

33 > 12,right继续向左移动

image-20200522220515361

此时right == left,终止循环

pivot赋给arr[left]

image-20200522220557616

至此,左子序列1也分割完成了

小结

快排就是一个递归的过程,分割得到左子序列

再对左子序列进行快排分割,得到左子序列的左子序列…

处理完左边,再去处理右边的右子序列

第三轮分割序列 — 右子序列

右子序列只有47、68、49,选择48作为轴值 pivot

image-20200522220854832

pivot和最后一个值交换

image-20200522221012928

47、49都比pivot=68小,left一直向右移动,直到left == right

image-20200522221104705

分割之后,只剩下左子序列:47、49

47、49,选49作为轴值,得到左子序列47

子序列只剩下一个元素47,就不必排序了,右边排序结束

结果:47、49、68

C++实现

选择中间的值作为轴值

#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>
#include <unordered_set>
#include <string>
#include <stack>
#include <cmath>
#include <map>

using namespace std;


/**
 *
 * @param arr   待分割的序列
 * @param left  左边界
 * @param right 右边界
 * @return      分割后轴值的位置
 */

template<class T>
int PartitionArr(vector<T>& arr, int left, int right) {
    T temp = arr[right];
    while (left != right) {
        while (arr[left] <= temp && left < right) {
            left++;
        }
        if (left < right) {
            arr[right] = arr[left];
            // 赋值后,left不动,right向左移
            right--;
        }
        while (arr[right] >= temp && right > left) {
            right--;
        }
        if (left < right) {
            arr[left] = arr[right];
            // 赋值后,right不动,left向右移
            left++;
        }
    }
    // 当left == right,把轴值放回left上
    arr[left] = temp;
    return left;
}

/**
 *
 * @param arr   待排序数组
 * @param left  左边界
 * @param right 右边界
 */
template<class T>
void quickSort(vector<T>& arr, int left, int right) {
    // 子序列剩下0或1个元素,排序结束
    if (right <= left) {
        return;
    }

    //  选择数组中间作为轴值
    int pivot = (left + right) / 2;
    // 把轴值放到数组最后面
    swap(arr[right], arr[pivot]);
    // 分割后轴值的位置
    // 分割后,左边值 < 轴值 < 右边值
    pivot = PartitionArr(arr, left, right);
    quickSort(arr, left, pivot - 1);
    quickSort(arr, pivot + 1, right);
}


int main() {
    vector<int> arr = { 22,33,49,47,33,12,68,29 };
    for (auto& i : arr) {
        cout << i << ' ';
    }

    cout << endl << endl;

    quickSort(arr, 0, arr.size() - 1);

    for (auto& i : arr) {
        cout << i << ' ';
    }

    cout << endl << endl;
    system("pause");
    return 0;
}

image-20200522223306345

总结

  • 快排是不稳定的排序算法

    • 33 33'排序后可能变成33' 33
  • 时间复杂度:

    • 平均: O ( N l o g N ) O(Nlog_N) O(NlogN)
    • 最差: O ( N 2 ) O(N^2) O(N2),退化为冒泡排序
  • 空间复杂度:

    • 递归调用消耗栈空间
    • 最优: O ( l o g N ) O(log_N) O(logN)
    • 最差: O ( N ) O(N) O(N),退化为冒泡排序

如有错漏不实之处,欢迎补充纠正。

快速排序法(详解)
小白的博客
07-01 58万+
假设对以下10个数进行快速排序: 6 1 2 7 9 3 4 5 10 8 我们先模拟快速排序的过程:首先,在这个序列中随便找一个数作为基准数,通常为了方便,以第一个数作为基准数。 6 1 2 7 9 3 4 5 10 8 在初始状态下,数字6在序列的第1位。我们的目标是将6挪到序列中间的某个位...
C语言实现快速排序算法(含实现步骤
12-21
快速排序是一种非常高效的排序算法,它的基本原理是采用分治策略。以下是快速排序的原理和实现步骤: 原理: 1、选择一个基准值。 2、通过一趟排序将待排序的序列分割成独立的两部分,其中一部分的所有数据都比另一...
数据结构:先进排序方法之快速排序
tydo达令的博客
02-05 3554
数据结构:先进排序方法之快速排序
最近对问题
最新发布
emmmm的博客
04-07 610
问题:最近对问题 /* 第一种方法:蛮力法解决的最近对问题 */ C++代码如下: #include&lt;iostream&gt; using namespace std; #define N 1005 int x[N],y[N]; int ClosestPoints(int x[],int y[],int n) { int index1,index2;//记录点...
排序算法——快速排序图解+代码)
qq_22108657的博客
11-05 6268
快速排序 定义数组的头部为一个基准,首先从基准的右边比较,交换基准数字;然后从基准的右边比较,交换基准数字。 使基准的左右两边分别都是比基准小和比基准大的数字,完成一次排序。 然后从左右两边分别重新定义新的基准,继续比较排序。 持续减少比较长度,直至左右两边均剩余一个数字,此时完成整个数组的排序。 从小到大进行排序 时间复杂度O( nlog2n ) 空间复杂度O( log2n ),不稳定(数据跳跃) 1. 图解选择排序 一次快速排序的过程 1、定义一个基准tmp,每次都将下标low的值即arr[l
快速排序,实现第一趟排序
lunei
11-26 5929
//快速排序 //快速排序,实现第一趟排序 //Auther: //Data:2019/11/26 关键字序列{24,19,32,43,38,6,13,22} 取基数(轴)(24) //算法原理: 将比基数大的数放到基数右边,小于或等于基数的数放在它的左边 第一趟排序结果:22,19,13,6,24,38,43,32 ...
快速排序算法图解+代码)
weixin_57332950的博客
11-16 1345
快速排序是效率最高的排序算法,它的基本思想是分治法,也是一种交换类的排序算法
排序算法快速排序
12-22
1.快速排序的思想 先从数列中取出一个数作为基准数(简单起见就选第一个数) 分区过程:将比这个数大的数全放到他的右边,比他小的数全放到他的左边(分治) 再对左右两边的区重复第一步和第二部操作,直到各区间...
快速排序算法C++描述
01-02
数据结构快速排序
【算法图解】——快速排序改进
01-07
文章目录快速排序思路注意!!!!!错误代码正确代码代码优化 快速排序 思路 如果列表为空或者只有一个元素则不用排序 选择首元素为基准值 创建两个列表:小于基准值的less=[ ]和大于基准值的high=[ ] 遍历整个列表...
c++ 快速排序算法【过程图解
08-30
下面小编就为大家带来一篇c++ 快速排序算法【过程图解】。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
(含动图演示)搞懂快速排序
一切随缘的博客
10-01 2185
当我们求解某些问题时,由于这些问题要处理的数据相当多,或求解过程相当复杂,使得直接求解法在时间上相当长,或者根本无法直接求出。快速排序的时间复杂度:最好O(N * logN),最坏O(N^2),平均时间复杂度,求一个概率累加:O(N * logN)快速排序的额外空间复杂度:最好O(logN),最坏O(N),平均的额外空间复杂度,求一个概率累加:O(logN)这里额外的空间主要指:递归的时候,我们要记录下每一次的分界点,这样递归完左边部分,才知道右边部分递归哪里。最坏:每次分界点都取到最大值或者最小值。
快速排序算法实验
m0_51246527的博客
12-22 2796
通过尝试多种方法,对基本的快速排序算法进行优化,在比较之中寻找更优秀的算法。
排序算法快速排序(C语言)
热门推荐
weixin_52811588的博客
08-20 3万+
快速排序算法是八大排序算法中实用性最高的算法之一,这里详细介绍了快速排序的递归实现和非递归实现,以及单趟排序的多种方法,还有选择key值的三个方法,并附有完整代码和优化后的代码详解,希望能帮助到大家
快速排序算法
qq_56043285的博客
03-27 1886
1.将一个数组从中间划分,分为左和右两部分,对左侧进行划分排序,对右侧进行划分排序, 将结果合并。 划分进行排是利用递归的方法。 难点在于怎样将划分出来求得的结果合并。
快速排序quicksort算法详细图解附代码实现(C++)
Xavier_97的博客
05-25 1134
快速排序的思想我就不讲了,下面直接上流程图 下面是快速排序的函数声明,可以看到这里的代码思路是接受两个迭代器来完成的,lp迭代器指向的是数组的第一个元素,rp迭代器指向的是数组最后一个元素(注意是vector.end()-1,而非vector.end()) void quicksort(vector<int>::iterator lp, vector<int>::iterator rp) 使用数组的第一个元素作为pivot(基准数)进行快排 void quicksort(vect
第一次了解快速排序
if_else1的博客
08-23 231
初始化数组 int[] arrays={45,80,55,40,42,85}; arrays[0]为基数 快速排序第一次 从后先向前 找比基数小的交换位置 42 80 55 40 45 85 从前先向后 找比基数大的交换位置 42 45 55 40 80 85 ...
十种经典排序算法总结
天瑕的博客
04-06 1万+
如果面试时让你写排序算法,除了说一句Arrays.sort你还会啥?
一文详解快速排序到底是怎么排的
su_bao的博客
07-04 1万+
1、快速排序精髓     一、先从数列中取出一个数作为基准数     二、分区,将比这个数大的数全放到它的右边,小于或等于它的数全部放到它的右边     三、对左右区间重复步骤(二),直到各区间只有一个数为止2、详解排序过程     假设一下数列     12 30 17 9 8 20 3     我们选取第一个数12为基准数,第一回合,从后往前找出一个比基准数12小的数,是3,所以我们将3和基准...
快速排序算法的核心思路和实现详细步骤
06-13
快速排序算法的核心思路是分治法,它将一个大的问题分成两个较小的子问题,递归地解决这些子问题,最后将子问题的解合并起来得到原问题的解。 具体实现步骤如下: 1. 选取一个基准元素pivot,一般选取待排序数组的第一个元素。 2. 将待排序数组分成两个部分,左边部分的所有元素都小于等于pivot,右边部分的所有元素都大于pivot。这里可以使用双指针法实现。 3. 对左右两个部分递归调用快速排序算法,直到不能再分。 4. 将左右两个部分的排序结果合并起来,即得到最终结果。 伪代码如下: ``` quicksort(array) if array.length <= 1 return array else pivot = array[0] left_array = [] right_array = [] for i = 1 to array.length-1 if array[i] <= pivot add array[i] to left_array else add array[i] to right_array sorted_left_array = quicksort(left_array) sorted_right_array = quicksort(right_array) return sorted_left_array + [pivot] + sorted_right_array ``` 快速排序算法的时间复杂度为O(nlogn),空间复杂度为O(nlogn)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
写文章

热门文章

  • 排序算法 快速排序【详细步骤图解】 4133

分类专栏

  • 排序 1篇

您愿意向朋友推荐“博客详情页”吗?

  • 强烈不推荐
  • 不推荐
  • 一般般
  • 推荐
  • 强烈推荐
提交

最新文章

2020年1篇

目录

目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

两个鬼故事杜宾犬起名字起台球厅名字伯克天赐领域宝宝起名字大全100分马凡舒泳装掉落欧尔勒中国移动积分怎么兑换话费开广告公司起名大全夏末秋初起名2020年起名鼠宝宝起名比较好的网国势txt贾字取名起名大全女孩最好用的起名软件起古风名字股票模拟软件公司取名起名大全 易经周起名字起名专用字典独角兽寓意是什么意思鞍山起名馆首选善缘堂姓包的起名字男孩姓何女孩起名字大全大地春回金牛座男人专业起名软件下载方氏男宝宝起名电商公司起名童姓起名字吗少年生前被连续抽血16次?多部门介入两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”淀粉肠小王子日销售额涨超10倍高中生被打伤下体休学 邯郸通报单亲妈妈陷入热恋 14岁儿子报警何赛飞追着代拍打雅江山火三名扑火人员牺牲系谣言张家界的山上“长”满了韩国人?男孩8年未见母亲被告知被遗忘中国拥有亿元资产的家庭达13.3万户19岁小伙救下5人后溺亡 多方发声315晚会后胖东来又人满为患了张立群任西安交通大学校长“重生之我在北大当嫡校长”男子被猫抓伤后确诊“猫抓病”测试车高速逃费 小米:已补缴周杰伦一审败诉网易网友洛杉矶偶遇贾玲今日春分倪萍分享减重40斤方法七年后宇文玥被薅头发捞上岸许家印被限制高消费萧美琴窜访捷克 外交部回应联合利华开始重组专访95后高颜值猪保姆胖东来员工每周单休无小长假男子被流浪猫绊倒 投喂者赔24万小米汽车超级工厂正式揭幕黑马情侣提车了西双版纳热带植物园回应蜉蝣大爆发当地回应沈阳致3死车祸车主疑毒驾恒大被罚41.75亿到底怎么缴妈妈回应孩子在校撞护栏坠楼外国人感慨凌晨的中国很安全杨倩无缘巴黎奥运校方回应护栏损坏小学生课间坠楼房客欠租失踪 房东直发愁专家建议不必谈骨泥色变王树国卸任西安交大校长 师生送别手机成瘾是影响睡眠质量重要因素国产伟哥去年销售近13亿阿根廷将发行1万与2万面值的纸币兔狲“狲大娘”因病死亡遭遇山火的松茸之乡“开封王婆”爆火:促成四五十对奥巴马现身唐宁街 黑色着装引猜测考生莫言也上北大硕士复试名单了德国打算提及普京时仅用姓名天水麻辣烫把捣辣椒大爷累坏了

两个鬼故事 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化