查看: 7483| 回复: 33
跳转到指定楼层
上一主题 下一主题
收起左侧

[二分/排序/搜索] 最简洁的快速排序

🔗
afc | 只看该作者 |倒序浏览
全局:

注册一亩三分地论坛,查看更多干货!

您需要 登录 才可以下载或查看附件。没有帐号?注册账号

x
本帖最后由 afc 于 2013-11-15 16:16 编辑

最简洁的快速排序
直接上代码
  1. void a_swap(int *a, int *b)
  2. {
  3.         int tmp = *a;
  4.         *a = *b;
  5.         *b = tmp;
  6. }
  7. int a_partition(int a[], int p, int r)
  8. {
  9.         int i = p-1;
  10.         for(int j=p; j<=r-1; j++){
  11.                 if(a[j] < a[r]){
  12.                         i ++;
  13.                         a_swap(&a[i], &a[j]);
  14.                 }
  15.         }
  16.         a_swap(&a[i+1], &a[r]);
  17.         return i+1;
  18. }

  19. void a_qsort(int a[], int p, int r)
  20. {
  21.         if(p >= r){
  22.                 return;
  23.         }
  24.         int q = a_partition(a, p, r);
  25.         a_qsort(a, p, q-1);
  26.         a_qsort(a, q+1, r);
  27. }
复制代码


若需要对数组a[n]进行排序,则只需调用
a_qsort(a, 0, n-1);

1.
void a_qsort(int a[], int p, int r);
对数组a的[p, r]闭区间范围内的元素进行排序。

2.
int a_partition(int a[], int p, int r)
以a[r]为pivot,对数组a的[p, r]闭区间范围内的元素进行分区,返回值为pivot所在的位置
该函数首先将[p, r]划分为四个子区间
[p, i]: 该区间内所有的元素都小于pivot
[i+1, j]: 该区间内所有的元素都大于于pivot
[j+1, r-1]: 该区间内的元素尚未被划分
[r, r]: pivot
循环结束后有 j=r, 此时[j+1, r-1]区间为空,即所有的元素都已经完成划分。此时,只需要交换a[r]与a[i+1],就可以保证所有小于pivot的元素都在其左边,大于pivot的元素都在其右边。

此版本的分区默认采用尾元素为pivot,并可以轻松扩展为其他方式,只需要在函数开始前,将pivot交换到尾部即可

以上程序参考自《算法导论》,个人认为是最简洁的快排实现了。



上一篇:编程竞赛常用算法模板详细代码实现合集
下一篇:Additive Number
推荐
北美农民 2013-11-10 05:17:47 | 只看该作者
全局:
本帖最后由 北美农民 于 2013-11-9 16:24 编辑
elfandi 发表于 2013-11-9 16:01
swap不用异或?- -

LZ这里可以用, 但建议不要用。 因为很多时候不知道swap会不会是针对同一个引用进行, 这样就变0 了。比如用了类似我的版本的partitioning的快排就不能了

另外包括这种swap也是。 如果a,b是同一个引用就废了。如果之前加一个判断还不如用经典的呢。
a = a + b
b = a - b;
a = a - b;
回复

使用道具 举报

全局:
yabirthday 发表于 2020-5-3 15:58
[mw_shl_code=cpp,true]int partion(vector& nums, int left, int right) {
    int pivot = nums[left],  ...

挑个小刺,partition拼错了~
回复

使用道具 举报

推荐
北美农民 2013-11-10 04:12:55 | 只看该作者
全局:
本帖最后由 北美农民 于 2013-11-9 15:39 编辑

快排什么版本都见过, 我就写这种。 不见得比我简洁吧.


  1. private void qsort(int[] a, int start, int end) {   
  2.    if (end <= start) return; // 其实这句可有可无, 只要调用的时候不故意出错
  3.   
  4.    int left = start;
  5.    int right = end;
  6.    int pivot = a[left + (right - left) / 2];

  7.    // selection
  8.    while (left <= right) {
  9.        while (a[left] < pivot) left ++;
  10.        while (a[right] > pivot) right --;
  11.        if (left <= right) {
  12.          int tmp = a[left];
  13.          a[left] = a[right];
  14.          a[right] = tmp;
  15.          left ++;
  16.          right --;
  17.        }
  18.    }

  19.    // divide
  20.    if (left < end) qsort(a, left, end);
  21.    if (right > start) qsort(a, start, right);
  22. }
复制代码


评分

参与人数 2大米 +5 收起 理由
逆风局局长i + 2 确实 我也只有这种能写对了
austurela + 3 这个版本确实好啊

查看全部评分

回复

使用道具 举报

🔗
ygnhzeus 2013-11-9 15:42:39 | 只看该作者
全局:
同ls,敢问这代码跑过么
回复

使用道具 举报

🔗
ytsr 2013-11-9 16:18:50 | 只看该作者
全局:
这种编程风格,我是面试官,我肯定把你挂了。变量名都是单个字母,看都看晕了。
回复

使用道具 举报

🔗
EroicaCMCS 2013-11-9 19:45:15 | 只看该作者
全局:
ytsr 发表于 2013-11-9 16:18
这种编程风格,我是面试官,我肯定把你挂了。变量名都是单个字母,看都看晕了。

效率和可读性之间要取舍啊,最近也很犹豫这个问题。。
据说业界先写成可读性高的代码,然后改写,把长的变量名还有缩进什么的全部去掉。。
回复

使用道具 举报

🔗
ytsr 2013-11-10 03:55:10 | 只看该作者
全局:
EroicaCMCS 发表于 2013-11-9 19:45
效率和可读性之间要取舍啊,最近也很犹豫这个问题。。
据说业界先写成可读性高的代码,然后改写,把长的 ...

变量名和效率没啥关系,最多是多打几个字罢了。
也不用太长,比如这里的p,r 至少也得换成 begin,end   head,tail   front, tail 之类的吧。
回复

使用道具 举报

🔗
elfandi 2013-11-10 05:01:08 | 只看该作者
全局:
swap不用异或?- -
回复

使用道具 举报

🔗
ytsr 2013-11-10 06:00:43 | 只看该作者
全局:
北美农民 发表于 2013-11-10 05:17
LZ这里可以用, 但建议不要用。 因为很多时候不知道swap会不会是针对同一个引用进行, 这样就变0 了。比如 ...

赞        
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表