最常用的排序:快速排序算法

###快速排序(QuickSort)是一种很高效的排序算法,但实际操作过程中不容易写出十分正确具有健壮性的代码,所以我想讲清这个问题,也能使自己理解更加深刻

算法思想

通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

算法的代码我参考了阿哈磊的代码:http://bbs.ahalei.com/thread-4419-1-1.html
讲的很透彻
给定一个序列5, 2, 8, 4, 22, 31, 0, 1, 9九个数字,来对九个数字排序

  • 第一步:找一个基准数(用来参考的数字),为了方便,就把第一个数字也就是5看成基准数

  • 第二步:一个小人从右往左找一个比基准数小的数字,然后另一个小人从左往右找一个比基准数大的数字(注意要先从右边找,至于为什么,后面再说)

  • 第二步完成后右边找到一个数字是1,左边找到一个数字是8,然后我们交换这两个数字
    序列就变成了5, 2, 1, 4, 22, 31, 0, 8, 9

  • 然后继续找 5, 2, 1, 4, 0, 31, 22, 8, 9
    当两个小人碰头,在0这个位置停下了,也就是两边查询的数组下标相等时,结束查找,我们发现0左边的数都是小于5的,右边的数都是大于5的,然后我们把碰头位置数字与基准数交换,分成两个序列
    左序列0,2,1,4,5
    右序列31,22,8,9
    然后继续上面相同的操作(这里是一个递归过程)

递归到最后,就能得到一个有序的序列

排序前序列:5 2 8 4 22 31 0 1 9
5 2 1 4 0 31 22 8 9
改变基准数:0 2 1 4 5 31 22 8 9
0 2 1 4 5 31 22 8 9
改变基准数:0 2 1 4 5 31 22 8 9
0 2 1 4 5 31 22 8 9
改变基准数:0 1 2 4 5 31 22 8 9
0 1 2 4 5 31 22 8 9
改变基准数:0 1 2 4 5 31 22 8 9
0 1 2 4 5 31 22 8 9
改变基准数:0 1 2 4 5 31 22 8 9
0 1 2 4 5 31 22 8 9
改变基准数:0 1 2 4 5 9 22 8 31
0 1 2 4 5 9 8 22 31
改变基准数:0 1 2 4 5 8 9 22 31
0 1 2 4 5 8 9 22 31
改变基准数:0 1 2 4 5 8 9 22 31
0 1 2 4 5 8 9 22 31
改变基准数:0 1 2 4 5 8 9 22 31
排序后序列:0 1 2 4 5 8 9 22 31

/*
快速排序算法:
*/
#include<cstdio>
#include<iostream>
using namespace std; 
int a[10] = {5, 2, 8, 4, 22, 31, 0, 1, 9};
void print() {
  for(int i = 0; i < 9; i++)
    cout << a[i] << " ";
  cout << "\n";
}
void QuickSort(int left, int right) {
  int temp = a[left], i, j;
  i = left;
  j = right;
  if(i > j) return ;
  while(i != j) {//循环到两个小人碰到为止 
    while(a[j] >= temp && i < j) j--;//右边开始找,找到比基准数小的数 
    while(a[i] <= temp && i < j) i++;
    if(i < j) swap(a[i], a[j]);//交换两个数 
  }  
  swap(a[left], a[i]);//改变基准数 
  print();
  QuickSort(left, i-1);  //递归过程
  QuickSort(i+1, right);
} 

int main() {
  print();
  QuickSort(0, 8);
  print();
} 

##为什么一定要先从右开始找?
不妨想想如果从左边找

while(a[i] <= temp && i < j) i++;
while(a[j] >= temp && i < j) j–;

考虑一种情况,当i停下来的时候,找到一个大于基准数的数
接着j开始向左走,企图寻找一个小于基准的数,但是存在i < j这个条件的限制,j有可能没找到小于基准的数时就被迫停下来了,此时i==j的位置与基准数交换位置,结果就会出现错误

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值