快速排序

快速排序有多种分割方法。

填坑法

start指针指向开始,end指针指向结束。以a[start]为基准,目的是把数组从基准分开,左边都是小于等于基准的,右边都是大于基准的。先把基准保存,从左右指针互相填坑,遇到不符合规矩的数交换,所以start左边都是小于基准的,end右边都是大于基准的,这样一步一步缩小[start,end]范围,基准肯定位于start,end中间,最后start==end,将基准放这儿。
举个例子,[5,4,6,7,8,9],基准为5,左右指针开始分别位于5,9,右指针先走,寻找第一个小于5的数,找到了4,于是填坑[4,4,6,7,8,9],注意开始已经将5保存了,5的位置是一个坑,现在start=5,end=4,start继续走寻找大于5的,到了4,不能大于end所以结束了,start,end都在4(索引为1),把基准放进去。结束。

#include <iostream>
using namespace std;void qs(int a[], int start, int end){if(start>=end)return;int l=start,r=end;int p = a[l];while(l < r){while(a[r] >= p && l < r) r--;a[l] = a[r];while(a[l] <= p && l < r) l++;a[r] = a[l];}a[l] = p;qs(a,start,l-1);qs(a,l+1,end);
}int main(){//    freopen("input.txt","r",stdin);int t[]={4,2,2,6,9,9,1,3};int len= sizeof(t)/ sizeof(int); qs(t,0,len-1);for (int i = 0; i < len; ++i) {cout<<t[i];}
}

加一个包装函数,就是这样的

#include <iostream>
using namespace std;int partition(int a[], int start, int end){int p = a[start];while(start < end){//判断条件也可以为start!=end,因为最终start==endwhile(a[end] >= p && start < end) end--;//从右向左第一个小于p的,这里>=不能改为>,否则会不能处理重复元素情况a[start] = a[end];while(a[start] <= p && start < end) start++;//从左向右第一个大于p的a[end] = a[start];}a[start] = p;return start;
}void qs(int a[], int start, int end){if(start<end){int mid = partition(a, start, end);qs(a, start, mid-1);qs(a, mid+1, end);}}int main(){//    freopen("input.txt","r",stdin);int t[]={4,2,2,6,9,9,1,3};int len= sizeof(t)/ sizeof(int);qs(t,0,len-1);for (int i = 0; i < len; ++i) {cout<<t[i];}
}

这个循环还有另一种形式

    while(l < r){while(a[r] > p && l < r) r--;if(l<r)a[l++] = a[r];while(a[l] < p && l < r) l++;if(l<r)a[r--] = a[l];}

填坑了需要前进一步,上面那种形式不需要前进是因为自循环里面的判断条件是a[r]>=pa[l]<=p,下一次循环会接着往前走,有一种常见的错误是写成这样的。

错误示范
    while(l < r){while(a[r] > p && l < r) r--;a[l] = a[r];while(a[l] < p && l < r) l++;a[r] = a[l];}

这种形式的分割,遇到重复元素会出错,比如排序[1,1],基准元素是1,j寻找小于等于基准元素,发现不用动,本来的位置就满足,然后i向后移动,寻找大于等于基准的元素,发现也不用动,本来的位置就满足,陷入了死循环

填坑法两种分割函数
一:
    while(l < r){while(a[r] >= p && l < r) r--;a[l] = a[r];while(a[l] <= p && l < r) l++;a[r] = a[l];}
二:
    while(l < r){while(a[r] > p && l < r) r--;if(l<r)a[l++] = a[r];while(a[l] < p && l < r) l++;if(l<r)a[r--] = a[l];}

交换法

交换法和填坑法原理差不多,注意最后有一个和基准元素交换的过程,

假设我们i,j元素分别到了4和9,j继续向左移动,发现了3(比基准元素6小)停下来,i也继续向右移动,i和j相遇了,结束。此时i和j相遇的位置一定比基准元素小,为什么呢,我们分析一下,相遇有两种情况,1是j移动过程发现了比基准小的元素停下来,然后i继续前进遇到了j,这种情况,j的位置肯定比基准元素小,最后的位置的左右边分别是小于基准和大于基准的,把基准元素放这肯定也没问题;2是j移动过程中没有遇到比基准小的元素,而是直接遇到了i,以前面为例子,如果中间不是3而是12,

那么j向左移动与i相遇于4这里,i肯定也是小于基准的。所以我们最后需要将基准位置和ij相遇位置的元素互换。

注意:这里每层的两个while循环判断必须用<=

#include <iostream>
using namespace std;void qs(int *a,int start,int end){if(start>=end)return;int l=start,r=end;int p=a[l];while (l!=r){while (a[r]>=p&&l<r)r--;//找到小于基准的元素while (a[l]<=p&&l<r)l++;//找到大于基准的元素if(l<r) {//最后如果是l==r就没必要交换swap(a[l], a[r]);}}swap(a[l],a[start]);qs(a,start,l-1);qs(a,l+1,end);
}
int main(){//    freopen("input.txt","r",stdin);int t[]={4,2,2,6,9,9,1,3};int len= sizeof(t)/ sizeof(int);qs(t,0,len-1);for (int i = 0; i < len; ++i) {cout<<t[i];}
}

参考:
填坑法参考: https://blog.csdn.net/a4118000113209/article/details/51923095
交换法参考:http://wiki.jikexueyuan.com/project/easy-learn-algorithm/fast-sort.html

快速排序(填坑法的两种写法以及交换法)相关推荐

  1. 20210408:力扣(二分查找法的两种写法以及变体题目)

    二分查找法的两种写法以及变体题目 写在前面 题目 思路与算法 代码实现 写在最后 写在前面 关于二分查找,真的是一个非常实用的查找算法,主要有两种写法,今天在总结时再次碰到,再次整理,方便后续查看复习 ...

  2. python装饰器带参数函数_python带参数装饰器的两种写法

    python带参数装饰器的两种写法 前言 最近在实现一个装饰器的过程中发现了一个很有意思的地方,在博客里面分享出来 不同的写法 三层函数嵌套,实现了可传参数的一个装饰器. import logging ...

  3. 两种写法的效果一样,那么到底哪一种更好呢?

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 有时候,我们在写一些循环逻辑的时候,并不是按执行次数等作 ...

  4. Model层的两种写法

    Model层的两种写法 第一种写法 namespace MyMVC.Models {public class Child{ //属性private int id;public int Id{get { ...

  5. controller 有两种写法,讨论一下两种写法的区别:

    controller 有两种写法,讨论一下两种写法的区别: 写法 1: app.controller('myCtrl', function($scope, $location) { $scope.my ...

  6. Sql语句中 case when .. 的两种写法

    在 SQL查询语句中, case 语句的两种写法(SqlServer 2005 下测试通过): 1. select (case 字段1  when a then 0  when b then 1  e ...

  7. sum 去重_总结leetcode上【排列问题】【组合问题】【子集问题】回溯算法去重的两种写法!...

    本周小结!(回溯算法系列三)续集 在 本周小结!(回溯算法系列三) 中一位录友对 整颗树的本层和同一节点的本层有疑问,也让我重新思考了一下,发现这里确实有问题,所以专门写一篇来纠正,感谢录友们的积极交 ...

  8. Vue2基础-el与data的两种写法(HTML版)

    目录 一.el的2种写法 二.data的2种写法 三. 一个重要的原则 Vue2基础全套教程合集:点击跳转        Vue2高级全套教程合集:点击跳转 一.el的2种写法 new Vue时候配置 ...

  9. vue的axios两种写法(不知道对不对,仅供参考)

    vue的axios两种写法(不知道对不对,仅供参考) `methods () {     getHomeInfo () {         axios.get ('/api/index.json') ...

  10. Mybatis中的大于、小于、大于等于、小于等于、不等于的两种写法

    Mybatis中的大于.小于.大于等于.小于等于.不等于的两种写法 在Mybatis的使用中,会使用到xml进行sql的编写,当遇到需要比较的时候,会发现直接使用 > 是不可行的,那么就需要使用 ...

最新文章

  1. 推出第一个免费工具CCT
  2. 不容错过的8个持续集成工具
  3. 深度学习笔记第一门课第一周:深度学习引言
  4. 启明云端分享|在使用sigmastar SSD201/SSD202D核心板时,应该注意的事项
  5. 超详细前端开发案例:品优购商场项目(一)
  6. EmguCV学习遇到的问题记录
  7. 关于主函数main(int argc,char *argv[])
  8. 坐标下降法和交替最小二乘法的区别是什么?
  9. smartq ten3 android4.2 v1.1,全线升级Android 4.2 智器平板新体验
  10. Qt学习之路之启动浏览器
  11. 亚马逊AWS学习——EC2实例无法正确加载EBS卷问题的解决
  12. 编写一个程序对Largest函数进行测试,找出一组数据的最大值
  13. 让洁净煤保障群众温暖过冬
  14. 微信公众号平台如何批量给粉丝自动打标签分组
  15. Windows注册表内容详解(转载)
  16. 一个屌丝程序猿的人生(八十)
  17. 使用ffmpeg的调色板对图片压缩
  18. [赤域吧]最小内存的影视APP【U5影视】版本V1.10
  19. 中大计算机考研复试刷人太狠,来!看看这些院校复试刷人刷的有多厉害
  20. 专精特新中小企业的政策依据

热门文章

  1. 增加虚拟android内存,SD卡变RAM 增加虚拟内存方法
  2. Unity 将3D物体的世界坐标转换为对应的屏幕坐标
  3. 湖南科技大学计算机考研资料汇总
  4. 60.(leaflet篇)leaflet虚线
  5. WebEx 播放 器 ,电脑有外音,耳机没声音
  6. 2021年美国大学生数学建模竞赛助力
  7. Java爬虫爬取网页数据
  8. OSChina 周日乱弹 —— 这二叉树长得,标致!
  9. oracle18c卸载方法,Oracle 18c Sharding 删除catalog 步骤
  10. 一万年很长,所以只争朝夕