文章目录

  • 1.只申请一次内存,避免多次递归调用时反复的申请和释放内存,提高程序运行效率
  • 2.不申请内存,在原数组上直接排序
  • 优化比较总结

对链接中快速排序进行代码优化

https://blog.csdn.net/qq_21201267/article/details/80993672#t6

1.只申请一次内存,避免多次递归调用时反复的申请和释放内存,提高程序运行效率

/** 6-1-opti1.快速排序(best version)(三数取中基准+希尔排序+基准群)(opti1,只申请一次内存)* 对数组找出一个中间大小的合适哨兵,把小于哨兵的放左边,大于哨兵的放右边,中间是等于哨兵的* 分别对左右递归调用快排*/void partion1_opti1(int *arr, size_t left, size_t right, size_t &lessPnum, size_t &largePnum, int *temp)//数据分段
{selectmedianofthree1(arr,left,right);  //找出中间大小的哨兵,让分段尽量均匀,提高效率int pval = arr[left];  //中间大小的数赋值给哨兵int tempLindex=0, tempRindex = right-left;  //临时数组的首末位下标for(int i = left+1; i <= right; ++i){if(pval > arr[i]) //比哨兵小的放在左边,从左边首位往中间写入,记录下比哨兵小的有多少个{temp[tempLindex++] = arr[i];++lessPnum;}if(pval < arr[i])  比哨兵大的放在右边,从右边末位中间写入,记录下比哨兵大的有多少个{temp[tempRindex--] = arr[i];largePnum++;}}for( ; tempLindex <= tempRindex; ++tempLindex)//中间还未被写入的位置,写入哨兵(哨兵可能是多个相同的值){temp[tempLindex] = pval;}for(int i = left, j=0; i <= right; ++i){arr[i] = temp[j++]; //把分好段的数组写回原数组{[小于哨兵的],[等于哨兵的],[大于哨兵的]}}
}
void qsort1_opti1(int *arr, size_t left, size_t right, int deep, int *temp)
{if(left >= right){return;}else if(right-left == 1)//只有两个数直接比较交换(也可以设置长度小于X(比如10),调用其他排序,如归并,减少不必要的调用快排){if(arr[left]>arr[right]){swap(arr[left], arr[right]);}}else if(right-left > 1 && right-left < 20)  //数组长度较小时,调用希尔排序,减少调用快排{size_t len = right - left + 1;shellsort(len, &arr[left]); //数组首地址为&arr[left]}else{size_t lessPnum = 0, largePnum=0;partion1_opti1(arr,left,right,lessPnum,largePnum,temp);  //数据分段,{[小于哨兵],[等于哨兵],[大于哨兵]}size_t pl_index = left + lessPnum;  //首位哨兵的下标size_t pr_index = right - largePnum;  //末位哨兵的下标if(pr_index == right && pl_index != left)  //哨兵群位于数组最右边,且左边还有数据{qsort1_opti1(arr,left,pl_index-1,deep,temp); //只对左边非哨兵数据快排}else if(pl_index == left && pr_index != right)  //哨兵群位于数组最左边,且右边还有数据{qsort1_opti1(arr,pr_index+1,right,deep,temp);  //只对右边非哨兵数据快排}else if(pl_index == left && pr_index == right) //全部是哨兵,两侧无数据,退出{return;}else  //两侧都有非哨兵数据,对两侧调用快排{qsort1_opti1(arr,left,pl_index-1,deep,temp);qsort1_opti1(arr,pr_index+1,right,deep,temp);}}
}
void quicksort1_opti1(size_t dsize, int *arr)
{if(dsize <= 1)  //预防特殊情况下后面代码失效{return;}size_t left = 0, right = dsize-1;int deep = 0;  //可以打印显示出调用的层数int *temp = new int [dsize];  //一次性开辟堆空间存放临时数组qsort1_opti1(arr,left,right,deep,temp);delete [] temp; //释放临时数组temp = NULL;  //指针置空
}

运行比较: 优化1效率提升

2.不申请内存,在原数组上直接排序

/** 6-1-opti2.快速排序(best version)(三数取中基准+希尔排序+基准群)(不申请内存)* 对数组找出一个中间大小的合适哨兵,把小于哨兵的放左边,大于哨兵的放右边,中间是等于哨兵的* 分别对左右递归调用快排*/
void partion1_opti2(int *arr, size_t left, size_t right, size_t &pl_index, size_t &pr_index)//数据分段
{selectmedianofthree1(arr,left,right);  //找出中间大小的哨兵,让分段尽量均匀,提高效率int pval = arr[left];  //中间大小的数赋值给哨兵size_t i = left, j = right;while(i < j){while(i < j && pval <= arr[j]) //把<=改成<,则哨兵群都在左边,下面相应代码可减少--j;swap(arr[i],arr[j]);while(i < j && pval >= arr[i])// =号至少有一个才行,一个等号,忽略下面半边集合哨兵代码是最高效的++i;swap(arr[i],arr[j]);}size_t pindex = i;size_t leftpnum = 0, rightpnum = 0; //左右跟哨兵相等的元素个数pl_index = pindex;//记得初始化!!!之前没有写,假如进不去for,没有初始化,就越界了pr_index = pindex;if(pindex != 0)//!!!如果pindex = 0,下面 i = pindex - 1 越界{for(i = pindex-1; i >= left; --i)//左边哨兵群向中间集合,哨兵都在右边,即可忽略以下代码{if(arr[i] == pval){++leftpnum;pl_index = pindex - leftpnum;swap(arr[i],arr[pl_index]);}if(i == left)    //size_t 做减法要小心越界break;}}for(i = pindex+1; i <= right; ++i)//右边哨兵群向中间集合,哨兵都在左边边,即可忽略以下代码{if(arr[i] == pval){++rightpnum;pr_index = pindex + rightpnum;swap(arr[i],arr[pr_index]);}}
}
void qsort1_opti2(int *arr, size_t left, size_t right, int deep)
{if(left >= right){return;}else if(right-left == 1)//只有两个数直接比较交换(也可以设置长度小于X(比如10),调用其他排序,如归并,减少不必要的调用快排){if(arr[left]>arr[right]){swap(arr[left], arr[right]);}}else if(right-left > 1 && right-left < 20)  //数组长度较小时,调用希尔排序,减少调用快排{size_t len = right - left + 1;shellsort(len, &arr[left]); //数组首地址为&arr[left]}else{size_t pl_index;  //首位哨兵的下标size_t pr_index;  //末位哨兵的下标partion1_opti2(arr,left,right,pl_index,pr_index); //数据分段{[小于哨兵][等于哨兵][大于哨兵]}if(pr_index == right && pl_index != left)  //哨兵群位于数组最右边,且左边还有数据{qsort1_opti2(arr,left,pl_index-1,deep); //只对左边非哨兵数据快排}else if(pl_index == left && pr_index != right)  //哨兵群位于数组最左边,且右边还有数据{qsort1_opti2(arr,pr_index+1,right,deep);  //只对右边非哨兵数据快排}else if(pl_index == left && pr_index == right) //全部是哨兵,两侧无数据,退出{return;}else  //两侧都有非哨兵数据,对两侧调用快排{qsort1_opti2(arr,left,pl_index-1,deep);qsort1_opti2(arr,pr_index+1,right,deep);}}
}
void quicksort1_opti2(size_t dsize, int *arr)
{if(dsize <= 1)  //预防特殊情况下后面代码失效{return;}size_t left = 0, right = dsize-1;int deep = 0;  //可以打印显示出调用的层数qsort1_opti2(arr,left,right,deep);
}

运行效率:

优化比较总结

以下数据为5次运行的平均数据

windows下效率提升:optimization1 -----6%----- optimization2 -----14%-----
linux 下效率提升:optimization1 -----2%----- optimization2 -----20%-----

测试程序运行时间shell脚本
https://blog.csdn.net/qq_21201267/article/details/81840299

最后特别感谢阿福同学的帮忙调试找BUG!!!

快速排序quicksort算法细节优化(一次申请内存/无额外内存排序)相关推荐

  1. 快速排序(quicksort)算法实现

     快速排序(quicksort)是分治法的典型例子,它的主要思想是将一个待排序的数组以数组的某一个元素X为轴,使这个轴的左侧元素都比X大,而右侧元素都比X小(从大到小排序).然后以这个X在变换后数组的 ...

  2. 快速排序quicksort算法优化

    1.基本想想 快速排序使用分治的思想 通过一趟排序将待排序列分割成两部分,其中一部分所有元素均比基准大,另一部分均比基准小 分别对这两部分元素继续进行排序,以达到整个序列有序 2.快排的步骤 1.选择 ...

  3. quicksort算法_QuickSort算法–用C,Java,Python实现

    quicksort算法 介绍 (Introduction) Quicksort algorithm is one of the fastest internal sorting algorithms ...

  4. 快速排序(QuickSort)算法介绍

    算法简介 快速排序(Quicksort)是对冒泡排序的一种改进算法.由C. A. R. Hoare在1960年提出.该算法使用广泛.效率很高,是最重要的排序算法之一. 该算法的实现基本可分为以下几步: ...

  5. 快速排序(Quick-Sort)及优化

    文章目录 前置基础知识 随机算法与快速排序 再来看快速排序 从C++STL 学习快速排序 算法题实战 排序数组 排序链表 盛水最多的容器 最小K个数 剑指offer21 调整数组顺序使奇数位偶数前面 ...

  6. 快速排序的三个优化思路

    前言 本文主要是介绍关于快速排序的三种优化思路,所以是基于读者已经掌握快速排序算法思想以及最基本的实现的前提,遂有关于快速排序原理方面,这里就不多赘述了. 下面是快速排序最简单的实现版本,即每次选取待 ...

  7. 算法基础-十大排序算法及其优化(文末有抽奖福利哦)

    算法基础-十大排序算法及其优化 算法基础-十大排序算法及其优化 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Kw1LA5Q4-1607527572080)(/uplo ...

  8. YUV图像实时去雾算法的优化与改进

    YUV图像实时去雾算法的优化与改进 2016-03-02 21:04 摘要:针对已有的基于DSP的实时去雾算法出现的问题进行优化和改进.在降采样倍数过大时,去雾效果会出现一些副作用,包括纹理细节丢失. ...

  9. 【Android 内存优化】内存抖动 ( 垃圾回收算法总结 | 分代收集算法补充 | 内存抖动排查 | 内存抖动操作 | 集合选择 )

    文章目录 一. 垃圾回收算法总结 二. 分代收集算法补充 三. 查看 Java 虚拟机 四. 获取 Android 应用可使用最大内存 五. 内存抖动标志 六. 排查内存抖动 七. 常见的造成内存抖动 ...

最新文章

  1. OpenStack在dashboard界面点击管理员网络,服务器页面出错
  2. 用JQUERY实现给当前页面导航一个CSS
  3. 美国密西西比州立大学招收机器学习、数据挖掘方向全奖博士生
  4. extjs window js引入问题
  5. BZOJ3170: [Tjoi2013]松鼠聚会 - 暴力
  6. vue click事件_Vue.js---实现前后端分离架构中前端页面搭建(二)
  7. IDEA中Debug的使用
  8. JavaScript(JS)--基础2(基本语法、字面量和变量、标识符、强制类型转换)
  9. linux系统下安装摄像头,Linux下安装摄像头驱动程序的三种方法
  10. [hive 报错]:FAILED:SemanticException [Error 10025] Expression not in GROUP BY key
  11. ICIAR2018数据集下载
  12. 【程序人生】跟小伙伴们聊聊我有趣的大学生活和我那两个好基友!
  13. 路由算法之——ECMP算法的改进方向
  14. ORA-10456 ORA-01219
  15. npm ERR! code E404 npm ERR! 404 Not Found - GET https://registry.npmjs.com/address-pares - Not found
  16. 2021年茶艺师(中级)最新解析及茶艺师(中级)考试总结
  17. keepalived配置(lvs+NAT+直连+TUN隧道+服务切换企业微信邮件告警)
  18. 工业物联网的开放语义框架
  19. 【JY】ETABS弹塑性时程分析的性能校核
  20. python操作word的入门教程_Python操作Word的入门教程

热门文章

  1. coreData mapView #include
  2. linux软件依赖库,【Linux】ubuntu系统安装及软件依赖库
  3. 获取系统信息2——linux中使用随机数
  4. 《团队名称》第八次团队作业:Alpha冲刺day5
  5. linq中给字段添加别名
  6. 设置停靠模式,切割设置星级图标
  7. C# 转繁体转简体转拼音,超级文本大转换
  8. [导入][导入][c#]Web开发中Tag的开发技巧
  9. [导入]设计模式初学者系列-工厂方法
  10. 1万字30张图说清TCP协议