算法学习 - 快速排序相关
来源:互联网 发布:js插件和组件的区别 编辑:程序博客网 时间:2024/05/21 11:41
1. 划分
快速排序中最重要的步骤就是划分,即选择一个元素(很多地方称为枢纽元素),将序列划分成两部分,比枢纽元素大的放在枢纽元素的右边,比枢纽元素小的放在枢纽元素的左边。
划分函数的思想:
1. 选择一个枢纽元素(以选择序列的第一个元素为例),暂存到临时变量中
2. 从序列的右边向左查找,找到一个比枢纽元素小的值。若找到,则将这个值填入到枢纽元素的位置
3. 从序列的左边向右查找,找到一个比枢纽元素大的值。若找到,则将这个值填入到step 2中那个比枢纽元素小的元素的位置。
4. 重复step2, step3,直到向右查找的“指针”(索引)和向左查找的“指针”(索引)碰到一起。表明一次划分就完成了。
按照上述思想实现代码如下:
int partition(int *arr, int l, int r){int i = l, j = r;int key = arr[l];//枢纽元素while (i < j){while (i < j && arr[j] >= key) j--;//从右往左找到一个比枢纽小的if (i < j){arr[i] = arr[j];i++;}while (i < j && arr[i] < key) i++;//从右往左找到一个比枢纽大的if (i < j){arr[j] = arr[i];j--;}}arr[i] = key;return i;}
2. 递归快排
递归的方式是最常见的方式,因为递归的写法代码简短。
算法思想:对元素进行划分,划分一次之后分别对两个子序列进行划分。直到子序列的元素个数变成1为止。
void QuickSort(int *arr, int l, int r){if (l < r){int par = partition(arr, l, r);QuickSort(arr, l, par - 1);QuickSort(arr, par + 1, r);}}
3. 使用栈作为辅助空间的快排
递归的过程其实就可以理解为一个栈,因为递归是依靠函数调用压栈的方式实现的。所以我们可以手动将中间过程保留,来进行快排。
算法思想:
1. 对序列进行一次划分,划分后的两个子序列头尾都压入栈中。
2. 在栈非空的情况下,从栈中取出两个元素(子序列的头尾位置)。对子序列进行划分。
3. 同样,对子序列进行划分的时候也将划分后的序列头尾压入栈中。
4. 重复step2 step3,知道栈为空为止。
void QuickSort2(int *arr, int l, int r){stack<int> tmp;//临时栈if (l < r)//{int par = partition(arr, l, r);//if (l < par - 1)//{tmp.push(l);//tmp.push(par - 1);}if (par + 1 < r){tmp.push(par + 1);tmp.push(r);}while (!tmp.empty()){r = tmp.top(); tmp.pop();l = tmp.top(); tmp.pop();par = partition(arr, l, r);if (l < par - 1){tmp.push(l); tmp.push(par - 1);}if (par + 1 < r){tmp.push(par + 1); tmp.push(r);}}}}
4. 使用队列作为辅助空间的快排
这个实现其实和用栈作为辅助空间的思想是相同的,无非就是将存储中间结果的辅助空间换成了队列。
void QuickSort3(int *arr, int l, int r){queue<int> tmp;//临时队列if (l < r){int mid = partition(arr, l, r);//一次划分if (l < mid - 1)//划分中间结果入队列{tmp.push(l);tmp.push(mid - 1);}if (mid + 1 < r){tmp.push(mid + 1);tmp.push(r);}while (!tmp.empty()){l = tmp.front(); tmp.pop();r = tmp.front();tmp.pop();mid = partition(arr, l, r);if (l < mid - 1){tmp.push(l); tmp.push(mid - 1);}if (mid + 1 < r){tmp.push(mid + 1);tmp.push(r);}}}}
5. 快排什么时候适合使用,什么时候不适合使用?
快排是基于划分的,最好的情况就是每次划分恰好都是在序列的中间,这样算法的复杂度就是O(n*lgn)。所以说枢纽元素的选择会直接影像到排序的效率。
随机序列快排:枢纽元素的选择也将是随机的,这时候的划分不会导致出现最差的结果。
已序序列快排:假设采用枢纽元素总是选择第一个元素的方式,很明显,每次划分都只能排序一个元素,这时候排序的效率就是最差的(也就是严重的不平衡树)。此时效率为O(n^2)。
那么对于这种已序的序列什么排序比较适合呢?插入排序!!对于插入排序,若序列是已序的表明序列不需要作很多的移动,此时效率为O(n)。
这也就可以联系到STL中sort函数的实现:
STL中的sort(),在数据量大时,采用quicksort,分段递归排序;一旦分段后的数量小于某个门限值,改用Insertion sort,避免quicksort深度递归带来的过大的额外负担,如果递归层次过深,还会改用heapsort。
- 算法学习 - 快速排序相关
- 快速排序算法相关
- 排序算法--快速排序相关
- 算法学习,快速排序
- 算法学习--快速排序
- 算法学习:快速排序
- 算法学习---快速排序
- 快速排序算法学习
- 快速排序算法学习
- 排序算法学习- 快速排序
- 排序算法学习:快速排序
- 算法学习之排序算法:快速排序
- 【算法学习】排序算法-快速排序
- 算法学习之排序:快速排序算法
- 排序算法学习之快速排序算法
- 算法学习系列-快速排序
- 算法学习笔记----快速排序
- 算法学习笔记----快速排序
- 多路温度采集控制系统(8)网页界面
- ubuntu 中文改英文
- 控制台屏蔽键盘消息事件
- 关于android6.0权限的问题
- NodeJS安装web框架模块 express报错处理
- 算法学习 - 快速排序相关
- 你是溪边杨柳
- C语言基础学习基本数据类型-浮点型
- WINDOSW编程学习笔记 - 关机
- BN(Batch Normalization)总结--Accelerating Deep Network Training by Reducing Internal Covariate Shift
- Java29道经典面试题
- java中的操作符
- HTML5之SVG 2D入门10 - 滤镜
- iOS应用中打开另一个应用