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

文章目录

    • 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!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/480582.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在深度学习顶会ICLR 2020上,Transformer模型有什么新进展?

一只小狐狸带你解锁炼丹术&NLP秘籍大数据文摘出品来源&#xff1a;medium编译&#xff1a;一一、AndyICLR是机器学习社群最喜爱的会议平台之一。如今&#xff0c;机器学习领域的会议已成为预印本里论文质量的标志和焦点。但即使这样&#xff0c;论文的发表数量还是越来越庞…

领域应用 | 人工智能+知识图谱:如何规整海量金融大数据?

本文转载自公众号&#xff1a;恒生技术之眼。21世纪以来&#xff0c;人类社会信息资源的开发范围持续扩大&#xff0c;经济、社会信息随着经济活动加剧得到空前的开发&#xff0c;信息资源总量呈爆炸式增长&#xff0c;我们从最初的“信息匮乏”一步踏入到“信息过量”时代。个…

神经网络不应视为模型,推理过程当为机器学习问题一等公民

首发于论智关注专栏写文章神经网络不应视为模型&#xff0c;推理过程当为机器学习问题一等公民编者按&#xff1a;Microsoft Semantic Machines资深研究科学家、UC Berkeley计算机科学博士Jacob Andreas指出&#xff0c;神经网络不应视为模型&#xff0c;因为神经网络的模型和推…

2019最全BAT资深Java面试题答案合集,建议收藏~

马上进入求职招聘高峰&#xff0c;总结了一份BAT&#xff08;阿里、百度等&#xff09;资深Java相关的面试题答案合集给到大家。 该板块的各面试章节&#xff0c;后续会持续迭代更新最新一线互联网公司的面试题目&#xff0c;建议收藏该页面&#xff0c;不定期更新查看~ Java…

中国古代诗词文本挖掘项目

PoemMining 项目地址&#xff1a;https://github.com/liuhuanyong/PoemMining Chinese Classic Poem Mining Project including corpus buiding by spyder and content analysis by nlp methods, 基于爬虫与nlp的中国古代诗词文本挖掘项目 项目介绍 中国古代诗词文化无疑是…

推荐系统的价值观

一只小狐狸带你解锁炼丹术&NLP秘籍 前言 推荐系统作为满足人类不确定性需求的一种有效工具&#xff0c;是具有极大价值的&#xff0c;这种价值既体现在提升用户体验上&#xff0c;又体现在获取商业利润上。对绝大多数公司来说&#xff0c;提升用户体验的最终目标也是为了获…

POJ1003/1004/1005/1207/3299/2159/1083/3094/2388解题(刷一波水题)

POJ 1003 题目链接 http://poj.org/problem?id1003 大意&#xff1a;长度1/21/3…1/n&#xff0c;给定长度值&#xff0c;求n #include<iostream> using namespace std; int main() {float len 0,sum;int n;while(cin >> len && len ! 0){for(n2,sum0;s…

论文浅尝 | 远程监督关系抽取的生成式对抗训练

动机远程监督关系抽取方法虽然可以使用知识库对齐文本的方法得到大量标注数据&#xff0c;但是其中噪声太多&#xff0c;影响模型的训练效果。基于 bag 建模比基于句子建模能够减少噪声的影响&#xff0c;但是仍然无法克服 bag 全部是错误标注的情形。为了换机噪声标注&#xf…

谷歌最强NLP模型BERT官方代码来了!GitHub一天3000星

新智元报道 来源&#xff1a;GitHub 作者&#xff1a;Google Research 编辑&#xff1a;肖琴 【新智元导读】谷歌AI团队终于开源了最强NLP模型BERT的代码和预训练模型。从论文发布以来&#xff0c;BERT在NLP业内引起巨大反响&#xff0c;被认为开启了NLP的新时代。 BERT的官方…

Java经典基础与高级面试36题和答案

在Java面试的首轮&#xff0c;经常会问很多关于Java面试基础以及高级的问题&#xff0c;今天收集相关Java面试36题和答案分享出来。 1.”static”关键字是什么意思&#xff1f;Java中是否可以覆盖&#xff08;override&#xff09;一个private或者是static的方法&#xff1f; …

论文浅尝 | 问题生成(QG)与答案生成(QA)的结合

本文转载自公众号&#xff1a;徐阿衡。梳理一下 MSRA 3 篇关于 QG 的 paper&#xff1a;Two-Stage Synthesis Networks for Transfer Learning in Machine ComprehensionQuestion Answering and Question Generation as Dual TasksA Joint Model for Question Answering and Qu…

卖萌屋算法岗面试手册上线!通往面试自由之路

一只小狐狸带你解锁 炼丹术&NLP 秘籍作为算法工程师&#xff0c;基础知识的重要性自然不必多说。虽然在有些项目中比较难感受到基础的作用&#xff0c;但扎实的coding能力&#xff0c;对算法本质和适用情况的理解&#xff0c;始终是决定工作效率与未来发展的重要feature。这…

2019头条抖音Java 3面真题,含面试题答案!

一面&#xff1a; hashmap&#xff0c;怎么扩容&#xff0c;怎么处理数据冲突&#xff1f;怎么高效率的实现数据迁移&#xff1f; Linux的共享内存如何实现&#xff0c;大概说了一下。 socket网络编程&#xff0c;说一下TCP的三次握手和四次挥手 同步IO和异步IO的区别&#…

深入理解XGBoost

本文的主要内容概览&#xff1a;1 XGBoost简介XGBoost的全称是eXtreme Gradient Boosting&#xff0c;它是经过优化的分布式梯度提升库&#xff0c;旨在高效、灵活且可移植。XGBoost是大规模并行boosting tree的工具&#xff0c;它是目前最快最好的开源 boosting tree工具包&am…

会议 | ESWC2018 见闻

本文转载自公众号&#xff1a;南大Websoft 。 ESWC2018于2018年6月2日在希腊克里特岛上的伊拉克利翁举行。会议包括两天的前会(workshops, tutorials) 和三天的正会&#xff0c;参会人数约300人。KeynotesKeynote1: Structural S…

POJ 1804 逆序数 解题(归并排序)

文章目录解法1&#xff1a;直接双重循环求解&#xff0c;n*n复杂度解法2&#xff1a;采用归并排序求解&#xff0c;复杂度nlgn题目链接 http://poj.org/problem?id1804题目大意&#xff1a;让一串无序数&#xff0c;在只能相邻数字交换的前提下&#xff0c;最短的次数变成有序…

史上最全memcached面试26题和答案

Memcached是什么&#xff0c;有什么作用&#xff1f; Memcached是一个开源的&#xff0c;高性能的内存绶存软件&#xff0c;从名称上看Mem就是内存的意思&#xff0c;而Cache就是缓存的意思。Memcached的作用&#xff1a;通过在事先规划好的内存空间中临时绶存数据库中的各类数…

深度学习笔记(六):Encoder-Decoder模型和Attention模型

版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。 https://blog.csdn.net/u014595019/article/details/52826423 </div><link rel"stylesheet" href"https://csdnimg.cn/release/phoenix/template/css/ck_h…

会议 | 2018年全国知识图谱与语义计算大会(CCKS 2018)

2018年全国知识图谱与语义计算大会China Conference on Knowledge Graph and Semantic Computing (CCKS 2018)2018年8月14日-17日&#xff0c;天津征稿截止: 2018年5月18日全国知识图谱与语义计算大会&#xff08;CCKS: China Conference on Knowledge Graph and Semantic Comp…

C++ Primer 第11章 泛型算法 学习总结

文章目录11.2 算法11.2.1 只读算法**1.find函数****2.accumulate函数****3.find_first_of 函数**11.2.2 写容器元素算法1.fill函数2.fill_n函数3.back_inserter插入迭代器4.copy函数5.算法的 _copy 版本11.2.3 排序算法sort&#xff08;起始&#xff0c;结束&#xff09;&#…