随机快速排序(内嵌插入排)
来源:互联网 发布:小学生笔顺软件下载 编辑:程序博客网 时间:2024/06/05 19:01
1.思路
在快速排序算法的递归实现中,存在一种不太好的现象:随着递归层层深入,大量数据被分割成了小数组;快排对于大数组的划分可以迅速地将元素移动到它正确位置的附近,比如说对1024进行一次均等划分,那么某个元素可能会移动数百个单位位置,若进行4次均等划分,元素在正确位置上的概率就从1/1024骤升到1/64,考虑到64与1024的绝对数值,这是相当高的效率;然而对于小数组,快速排序的效率就不那么理想了,对于16个元素的数组,快速排序也要划分4次才能把它移动到正确的位置上,相对于之前几百个位置的移动,小数组排序一次只能移动几个单位的位置。
换句话说,快速排序对少量数据的划分远不如它对大量数据的划分这么划算,当排序进入到小数组阶段后,它将多次因为这些小数组而频繁调用自身,但获得的收益并不大。我姑且把这种现象叫做“小数组的边际效益“
因此,在待排序数组长度小于某一阈值K时(代码中K = 3),用插入排序替代快速排序,取长补短让代码效率达到最高,其中任然选用随即快速排序。
2.完整代码
#include <iostream>#include <ctime>using namespace std;const int K = 3;void InitArr(int *nArr, int nLen) { //初始化数组 //srand(time(NULL)); for(int i = 0; i < nLen; ++i) { //nArr[i] = rand() % 100; nArr[i] = i; }}void PrintArr(int *nArr, int nLen) { for(int i = 0; i < nLen; ++i) { cout << nArr[i] << " "; } cout << endl;}void Swape(int *p1, int *p2) { int nTmp = *p1; *p1 = *p2; *p2 = nTmp;}void RandomSort(int *nArr, int nLen) { srand(time(NULL)); for(int i = 0; i < nLen; ++i) { int nIndex = rand() % nLen; Swape(&nArr[i], &nArr[nIndex]); //Sleep(2000); //等待2s,更新随机种子 }}//递增排序int PartitionUp(int *nArr, int nLeft, int nRight) { int nKey = nArr[nRight]; int i = nLeft - 1; for(int j = nLeft; j < nRight; ++j) { if(nArr[j] < nKey) { //反正不稳定,就用<代替≤,省取相等情况下多余的交换运行时间 i++; Swape(&nArr[j], &nArr[i]); //不稳定排序的原因 eg:1 5 8 8 6 11 7 } } Swape(&nArr[i + 1], &nArr[nRight]); //将主元素插入到中间 return i + 1;}//递减排序int PartitionDown(int *nArr, int nLeft, int nRight) { int nKey = nArr[nRight]; int i = nLeft - 1; for(int j = nLeft; j < nRight; ++j) { if(nArr[j] > nKey) { ++i; Swape(&nArr[i], &nArr[j]); //不稳定排序的原因 } } Swape(&nArr[i + 1], &nArr[nRight]); //将主元素插入到中间 return i + 1;}int RandomPartition(int *nArr, int nLeft, int nRight) { srand(time(NULL)); int nKey = rand() % (nRight - nLeft + 1) + nLeft; //随机选择【nLeft, nRight】内的某一个数 Swape(&nArr[nKey], &nArr[nRight]); //将选择的数与nArr[nRight]交换,即将选择的数作为Key值进行排序 return PartitionUp(nArr, nLeft, nRight);}void InsertSort(int *nArr, int nLeft, int nRight) { for(int i = nLeft + 1; i <= nRight; ++i) { int nTmp = nArr[i]; int j; for(j = i - 1; j >= nLeft && nArr[j] > nTmp; --j) { nArr[j + 1] = nArr[j]; } nArr[j + 1] = nTmp; }}void QuickSort(int *nArr, int nLeft, int nRight) { if(nLeft < nRight) { //分解 int nTmpPos = PartitionUp(nArr, nLeft, nRight); //解决、合并 QuickSort(nArr, nLeft, nTmpPos - 1); QuickSort(nArr, nTmpPos + 1, nRight); }}void QuickSortRandom(int *nArr, int nLeft, int nRight) { if(nLeft < nRight) { int nTmpPos = RandomPartition(nArr, nLeft, nRight); QuickSortRandom(nArr, nLeft, nTmpPos - 1); QuickSortRandom(nArr, nTmpPos + 1, nRight); }}void QuickInsertSortRandom(int *nArr, int nLeft, int nRight) { //主要代码 if(nLeft < nRight) { if(nRight - nLeft > K) { int nTmpPos = RandomPartition(nArr, nLeft, nRight); QuickInsertSortRandom(nArr, nLeft, nTmpPos - 1); QuickInsertSortRandom(nArr, nTmpPos + 1, nRight); } else { InsertSort(nArr, nLeft, nRight); //换用插入排序 } }}int main() { int Arr[1000]; int Len = 20; InitArr(Arr, Len);// PrintArr(Arr, Len); RandomSort(Arr, Len); PrintArr(Arr, Len);// QuickSort(Arr, 0, Len - 1); QuickInsertSortRandom(Arr, 0, Len - 1);// InsertSort(Arr, 0, Len - 1); PrintArr(Arr, Len); return 0;}
3.运行结果与算法效率同前文。
阅读全文
0 0
- 随机快速排序(内嵌插入排)
- 快速排序(Java随机位置快排实现)
- 快速排序 & 随机数的生成方法 & 随机快排
- python内排序算法(冒泡 插入 选择 堆 归并 快排)
- 内排序(插入排序、冒泡排序、选择排序、shell排序、快速排序、归并排序、堆排序)
- 快速排序(随机版)
- 排序(冒泡,选择,插入,快排,堆排)
- java 合并排序算法、冒泡排序算法、选择排序算法、插入排序算法、快速排
- 排序 quick_sort 快排 算法 随机函数 rand() 快速排序的随机化版本
- 快排 快速排序
- 内排序-插入排序
- 排序(插入,希尔,选择,堆排序,归并,快排)
- 直接插入排序、快排 AND归并排序(图)
- 排序算法(直接插入,堆排,归并排序)
- 快速排序的插排随机主元三数取中优化C语言实现
- 排序(冒泡、直接插入、快速排序)
- 插入排序与快排
- 插入排序与快排
- Play2 for Java(六:数据访问DabaBase)
- js方法集
- Python 小技巧:Python3 表示最大整数值和浮点数值
- Cassandra操作
- chromdriver的安装和更新
- 随机快速排序(内嵌插入排)
- Android使用Ice进行数据请求
- 向量绕轴旋转
- 使用Spring boot基于Redis快速搭建分布式Session缓存方案
- source, ~/.bashrc, ~/.bash_profile详解
- 开发一个基于React Native的简易demo--源码
- JavaScript语言精粹经典实例(整理篇)
- 1050. 螺旋矩阵(25) PAT乙级真题
- http://blog.csdn.net/kobebryantlin0/article/details/54880933