#include <stdio.h>

 void print(int *a, int start , int end);

 void quick_sort(int *a, int start, int end) {
if (start + >= end) return;
int pv = a[start];
int p = start, q = end;
for (;;) {
while (++p < end && a[p] < pv);
while (--q > start && a[q] > pv);
if (p > q) {
break;
}
int t = a[p];
a[p] = a[q];
a[q] = t;
} a[start] = a[p-];
a[p-] = pv; // print(a, start, end); quick_sort(a, start, p-);
quick_sort(a, p, end);
} void print(int *a, int start , int end) {
for (int i=start; i<end; i++) {
printf("%d ", a[i]);
}
printf("\n");
} int main() {
int a[] = {}; int len = sizeof(a) / sizeof(int);
quick_sort(a, , len); for (int i=; i<len; i++) {
printf("%d ", a[i]);
}
return ;
}

快排还是很容易写错的,记得编程珠玑上说,在提出后的十几年时间少有正确的实现,不断尝试感觉这个实现可以作为自己的模板了,或许可以再加上一个随机化选择的过程。

函数对a[start, end)范围内的数进行一个非降序排序,这个界限划分符合STL的习惯,发现这种半开区间的表示方法确实非常好用

先选取a[start]作为一个哨兵,对剩下的a(start, end)范围内数进行一个比较交换工作,这样从前到后和从后到前的过程就对称了(现在都是开边界了)

设 p = start, q=end为初始状态

在交换过程中

while (++p < end && a[p] < pv);
while (--q > start && a[q] > pv);

首先对下标进行一个自增/自减,这里每次检测都进行这个过程(即使&&后面的条件不满足,防止两个下标在等值处不能移动造成死循环)

当退出循环时,可以确定p指向的是第一个比哨兵值(a[start])大的元素的下标(有可能这个下标是end,但我们不会直接用它来取值,所以没关系),因而a[p-1]肯定比哨兵值来的小,于是把哨兵值和a[p-1]做一个交换。此时原来的数组已经以a[p-1]为界限被划分成了两部分,a[start, p-1) < a[p-1] < a[p, end)。这样进行一个递归调用即可。

quick_sort(a, start, p-1);
quick_sort(a, p, end);

今天是8月6日,一晃,一年过去了。虽然说上面的方法比较快(采用了双指针),但是练习理解的话还是参照《算法导论》里讲快排的那部分来的比较容易

size_t partition(vector<int>& nums, size_t start, size_t end) {
if (start >= end) {
return start;
} int pv = nums[end - ];
size_t div = start; for (size_t i=start; i<end - ; i++) {
if (nums[i] < pv) {

swap(nums[i], nums[div++]);

        }
}
swap(nums[end - ], nums[div]);
return div;
} void quick_sort(vector<int>& nums, size_t start, size_t end) {
if (start >= end) {
return;
}
size_t div = partition(nums, start, end);
quick_sort(nums, start, div);
quick_sort(nums, div+, end);
}

partition 函数中[start,div)区间是比pv小的,[div,i)区间是大于等于pv的,[i, end-1)部分是未知大小的(如果区间截止未知大于等于开始未知,则认为这个区间为空),只要记住这个就可以非常稳定的写出代码,不会如第一种要注意太多细节问题。

最新文章

  1. [源码]NumberToUpper 数字转中文
  2. Webbrowser控件判断网页加载完毕的简单方法 (转)
  3. vb.net Linq 筛选(像 select distinct) DateTable 日期数据中的年份
  4. php删除html标签的三种解决方法
  5. Linux用户级线程和内核级线程区别
  6. vga|9针串口|网口测试方法
  7. Delphi 实现Ini文件参数与TEdit和TCheckBox绑定(TSimpleParam)
  8. 数组、链表、Hash(转)
  9. emacs format
  10. iOS开发之使程序在后台运行
  11. 微信小程序picker组件关于objectArray数据类型绑定
  12. Docker配置镜像加速
  13. python学习:for循环
  14. 前端面试题整理—ES6篇
  15. springcloud的Zuul配置重试和fallback
  16. 深入剖析GPU Early Z优化
  17. bzoj1477: 青蛙的约会(exgcd)
  18. OSGI企业应用开发(二)Eclipse中搭建Felix运行环境
  19. AddHandler php5-script .php\AddType text/html .php和AddType application/x-httpd-php .php的区别?
  20. 命令行模式和python交互模式

热门文章

  1. Unity---动画系统学习(6)---Avatar Mask动画融合、Layers动画分层、IK反向动力学
  2. 使用SWig出现调用异常的情况
  3. jQuery 遍历 - closest() 方法
  4. UVA - 11404
  5. SPOJ - DISUBSTR 求串中子串的个数
  6. vue点击tab跳转页面,给点击的tab添加样式,且解决刷新以后点击的tab样式消失问题
  7. mac 系统配置(一)
  8. android 无线调试 [无需数据线][无需root]
  9. Knime读取Jason数据
  10. CenctOS6 and CenctOS7 多种姿势解决忘记密码