快速排序
来源:互联网 发布:数控车螺纹编程 编辑:程序博客网 时间:2024/05/19 04:05
快速排序
名副其实,它在排序中以“快”而闻名。它是处理大数据最快的排序算法之一
基本思想:
通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
算法的具体实现:
虽然网上介绍快速排序的文章很多,但是具体怎么实现每一步的讲解却很少,对于大多数初学者很去难弄懂里面的关键。下面我来详细介绍一下每一步的实现过程。
快速排序分成两步,①一趟排序,②递归调用
数组:arr=[5,6,22,1,7,2];
一趟排序的实现过程:
i表示左边“↑”的坐标,指左边下一次等待比较的位置
j表示右边“↑”的坐标,指右边下一次等待比较的位置
X表示基准数,当前我们选取左边第一个数5作为基准数。
目标:小于等于基准数的放在基准数的左边,大于基准数的放到基准数的右边。
完成条件:i>=j
初始状态:
第一次:从右j开始进行比较,如果arr[j]<X=5
,则与基准数的位置进行交换;
更新j的位置*。在这里是2与X进行了交换。
第二次:从左i开始进行比较,如果arr[i]>X=5
,则与基准数的位置进行交换;
更新i的位置*。在这里是X与6进行了交换。
第三次:从右j开始进行比较,如果arr[j]X=5
,则与基准数的位置进行交换;
更新j的位置。在这里是1与X进行了交换。
第四次:从左i开始进行比较,如果arr[i]>=X=5
,则与基准数的位置进行交换;
更新i的位置。在这里是X与22进行了交换。
第五次:从右j开始进行比较;更新j的位置,达成判断条件i>=j。
将X替换成5,完成一趟排序*。
排序结果:
注释*:
i和j位置的更新规则:
如果arr[i]<=X=5
,则i++
;重复上述过程,直到arr[i]>=X=5
,或者是i>=j
;
如果arr[j]>X=5
,则j--
;重复上述过程,直到arr[j]<X=5
,或者是i>=j
;
一趟排序中基准数(X)的替换规则:
由于基准数是需要不断被替换的,所以在实际代码中,我们并不需要反复地将基准数与目标数进行替换。
在这里我们采用了挖空填数法。即将把基准数放置到X中,这样的话基准数就可以所在的位置就可以随意被填充(挖坑)。
等到一趟排序结束之后,我们再将X放回到坑中(填数),这样就提高了代码的效率。
一趟排序的代码实现:
function quickSort(a, begin, end) { //确保开始和结束的数正确 var begin = typeof begin != 'number' ? 0 : begin, end = typeof end != 'number' ? a.length - 1 : end; if (end - begin <= 1) return; //结束循环的条件 var x = a[begin], //默认选择第一个数的为基准数 p1 = begin, //左边“↑”的位置 p2 = end, //右边“↑”的位置 flag, //本次比较是否发生数组交换 dr = true; //比较的方向,默认true时为从右到左开始判断 while (p1 < p2) { flag = false; //默认数组没有发生交换 if (dr) {//从右到左开始判断 for (var i = p2; i >= p1; i--) { if (a[i] <= x) {//如果a[i]小于等于基准数 a[p1] = a[i]; // 则将a[i]赋给a[p1] p1++; // 从左边下一个开始比较 p2 = i; // 从右边上一个开始比较 dr = !dr; //更改比较方向 flag = true; //本次发生了数组交换 break; //退出循环 } }// 如果for循环没有发现满足条件的元素,则说明X的位置本身就是正确的,不需要改变 if (!flag) { //如果没有发生数组交换,则说明一趟排序已经完成 p2 = p1; // 跳出while } } else {//从左到右开始判断 for (var j = p1; j < p2; j++) { if (a[j] > x) { a[p2] = a[j]; p2--; p1 = j; dr = !dr; flag = true; break; } } if (!flag) { p1 = p2; } } } a[p1] = x;//一趟排序已经完成,将基准数代入到a[p1]中 }
递归调用
实现简述:
通过一趟排序,我们可以把数组分成两个部分,一部分小于等于基准数,另一部分大于基准数。前者我称为前基,后者我称为后基。
对于前基,我们也进行一趟排序,也可以分成两个部分……重复这个过程,直到前基每一个部分都只有一个数或者是为空,这就说明前基就已经排好;对于后基也是如此。
递归的实现:
function quickSort(a, begin, end){ //前面代码不变 a[p1] = x;//一趟排序已经完成,将基准数代入到a[p1]中 //在上行代码后插入这两行代码 quickSort(a,begin,p1-1); quickSort(a,p1+1,end);}
参考资料:
[1]http://blog.csdn.net/morewindows/article/details/6684558 (非常好的文章,本文就是采用了“挖坑填数+分治法”的代码实现)
小尾巴吐槽:原本以为CSDN中html编辑器中的表格不好用(边框颜色和背景颜色重叠了),结果用了Markdown中的表格之后才知道,什么才是真正难用……
- 快速排序
- 快速排序
- 快速排序
- 快速排序!
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 各种效果
- 【JVM】线程安全与锁优化
- Android:手把手带你深入剖析 Retrofit 2.0 源码
- 类和对象
- Java基础2
- 快速排序
- 数据结构之Trie树
- 使用JavaScript的数组实现数据结构中的队列与堆栈
- UWA 六月直播季 | 6.22 Unity中动画系统性能优化方案回顾
- Ubuntu 16 释放显存的方法
- layui 弹出层的表单提交
- 欢迎使用CSDN-markdown编辑器
- 为什么中国民居喜欢坐北朝南?
- (4)gsoap方法:软件开发时如何使用webservice接口