从快速排序开始
2017-11-13 22:11
701 查看
起步
打算重新学习下算法记录到博客,只为整理下自己的思路、备忘,所以内容难免存在很多主观看法和不严谨的地方。如果有幸被检索到,内容好坏还请大家自己甄别,有问题的地方,也可以能够提出来大家共同学习。
快速排序
从快速排序和归并排序开始,因为对于算法学习来讲,这两个排序是理解递归的一个很好的切入点。概要
快排思想:就是把数组首位数字v放入数组有序时它该处的位置,同时使其左右数据满足如下描述性质:[|v|..................] ==> [....<v....|v|....>v.....]
这个步骤称之为partition.
可以发现经过一次partition,v的序列位定下来了,同时其他的数据虽然没有排好序,但是至少处在它该处的区间。然后对 <v 和 >v 左右区间再次进行同样的操作(递归),可以预见区间被划分得越来越多也越来越小,数据被分割得越来越接近排序的位置。最后完全停留在它的序列位上,此时整个数组有序。理解了大体流程以,就可以写出快排的伪代码:
int _partition(int a[], int lo, int hi); void _quicksort(int a[], int lo, int hi){ if (lo >= hi) return; int j = _partition(a, lo, hi); _quicksort(a, lo, j - 1); _quicksort(a, j + 1, hi); }
类似于二分法,此数组理想情况下被分割的次数是logN,每次分割后,遍历数据量为N,时间复杂度NlogN。
partition分割函数
快排的核心就是partition + 递归。partition的过程
先入为主,partition流程,数组将一直处于以下状态:[(v, lo) | .....<v..... | i......j | .....>v.....hi]
毕竟要用代码来实现算法,所以这里必须加入控制流的两个参数i、j,以下明确参数含义:
i:正在向右遍历的指针;
j:正在向左遍历的指针;
遇到i > v、j < v的时候,用swap(a[i],
a[j])来使数组满足以上规律,之后继续遍历;
所以当刚开始遍历i、j时,这两个参数应该满足:[lo+1, i) < v、(j,
hi] > v;
这两个区间在初始的时候长度都必须为0,由此也可以确定出i、j的初始值应该是i == lo+1,j==hi
partition的终点
[(v, lo) | .....<v..... j |i .....>v.....hi]正是由于i、j两个指针不断的遍历和交换,将数组规划为左右两段,j刚好是最后一个<v的数字,当然要与lo进行交换,交换后就是:
[j | .....<v..... v|i .....>v.....hi]
其实就是之前概要提到的partition的最终执行结果:
[....<v....|v|....>v.....]
partition的起点
最后忘记一个关键点,partition中i、j的初始值如何确定?(上面好像已经提及过),参考如下的数组[(v, lo,i) | .............hi] j
这里i==lo,j==hi+1,为什么给这样的初值(不应该是i == lo+1,j==hi吗)其实这里partition循环代码中使用的是前置+,所以还未进入循环的时候,应该把初始值设置为初始位置的上一个位置。当然i
== lo+1,j==hi的初始值也可以,不过partition循环代码中的前置+就要改为后置+,个人觉得在逻辑上会更繁杂一些,不容易调通。
代码
int _partition(int a[], int lo, int hi){ int i = lo; //各参数初始值 int j = hi + 1; int v = a[lo]; while(true){ while(a[++i] < v){ if (i >= hi) break; //退出条件 } while(a[--j] > v){ if (j <= lo) break; //退出条件 } if (i >= j) // ">=" 还是 ">" ? break; swap(a[i], a[j]); } swap(a[lo], a[j]); return j; } void quicksort(int a[], int n){ _quicksort(a, 0, n - 1); }
相关文章推荐
- 从快速排序开始的代码演化
- 快速排序里的学问:从猜数字开始
- 开始重新拾回我的算法思维之--快速排序
- 快速排序里的学问:从猜数字开始 猜数字里的算法思想
- 开始学数据结构——(六):快速排序
- 算法-快速排序(为什么每次都要从右边开始)
- 【从头开始学算法】快速排序
- 开始玩舌头:看看你的舌头等级
- 第01篇:C#星夜拾遗之如何开始C#学习
- 有意思的排序算法-快速排序
- 开始学习PHP之开发环境搭建(Apache+Mysql+Php)
- 时隔很久,要重新开始编程。今天试了下从头开始在ORACLE中建用户记录下遇到的问题,以备将来可查。
- 暑假已开始,读书也开始
- "愣头愣脑,欲望强烈",我的版本开始了
- 从壹开始微服务 [ DDD ] 之三 ║ 简单说说:领域、子域、限界上下文
- 1-2 一切由跑马灯开始
- 快速排序(递归版本)
- STP基础,从概念开始入门
- 从头开始学Java--第一课