快速排序的优化1: 选取中间值或随机值作为基准,C语言实现
我们考虑一个问题。如果要排序的数组本身就是有序的,例如:1, 2, 3, 4, 5。用上面的方法排序会发生什么情况?
基准数是1,东东从右边开始往左边走,结果一直走到最左边,遇到了虫虫才停止,这个过程中,虫虫根本没有机会移动。也就是说这个基准数本来就在正确的位置。这时这个数组只能被分为两部分,而不是希望的三部分。除了基准数之外,剩下的一部分仅仅比原数组少了一个元素。而这个过程的时间复杂度为O(N),接下去继续,结果发现每次得到的新数组都仅仅比原先少一个元素,所以一共需要进行N次。这个过程与冒泡排序的运行过程是一样的。也就是说快速排序在遇到有序的数组时会退化成冒泡排序,所以时间复杂度为O(N2)。遇到这样的问题,我们该怎么办呢?
如果不管三七二十一,我们先把这个数组的最左边的元素与中间元素进行交换,得到一个新数组:3, 1, 2, 4, 5。这时再用上面的方法进行排序,就可以把数组分成三段。时间复杂度可以重新回到O(N * logN)。
这是改进后的快速排序,与原始的快速排序代码相比,仅仅多了两行代码:
void quickSort(int arr[], int low, int high)
{if(low > high) //递归的出口{return;}//如果要排序的数组是有序的。用原始的快速排序方法会导致退化成冒泡排序 //这时如果把中间的元素跟low的元素交换,则每次都能把数组分成几乎相等的两份//增加这两行代码后就可以把时间复杂度重新变为O(N * logN)了。int middle = low + (high - low) / 2; //求中间元素的下标,不要写成 (low + high) / 2swap(middle, low);int num = arr[low];int i = low; //虫虫在最左边 int j = high; //东东在最右边 while(i < j) //虫虫和东东没有相遇的时候继续走 {//虫虫是哥哥,要让着弟弟,所以每次都是东东先走。 while(i < j && num <= arr[j]) //没有相遇,且右边的元素比基准大 {j--; //东东往左走一步 }while(i < j && num >= arr[i]) //没有相遇,且左边的元素比基准大{i++; //虫虫往右走一步}if(i < j) //两个小朋友都停止的时候,如果他们还没有相遇 {swap(i, j); //说明还没有到家,两个元素交换一下。虫虫和东东没有交换哦 }}//i==j时,虫虫和东东帮基准元素找到家了 //交换一下基准和家里的元素,也就是让基准元素回家,把家里的元素放到最前面 swap(low, i); //递归函数的等价关系式:用同样的方法帮左边和右边的两段数据排序 quickSort(arr, low, i-1); //左边一段数组继续排序 quickSort(arr, i+1, high); //右边一段数组继续排序
}
选择中间的元素作为基准,或者随机选择一个元素作为基准,这个方法就能解决待排序的数组有序 (升序和降序均可) 时算法退化的问题了。但是这个改进仍然不能解决所有数据都相同时,算法成冒泡排序的问题。下一节,我们将解决这个问题。
快速排序的优化1: 选取中间值或随机值作为基准,C语言实现相关推荐
- 快速排序及优化(Java实现)
一. 普通快速排序 找一个基准值base,然后一趟排序后让base左边的数都小于base,base右边的数都大于等于base.再分为两个子数组的排序.如此递归下去. public class Quic ...
- 快速排序深度优化详解
正如它的名字所体现,快速排序是在实践中最快的已知排序算法,平均运行时间为O(NlogN),最坏的运行时间为O(N^2).算法的基本思想很简单,然而想要写出一个高效的快速排序算法并不是那么简单.基准的选 ...
- 三种快速排序以及快速排序的优化
1.快速排序的基本思想: 快速排序使用分治的思想,通过一趟排序将待排序列分割成两部分,其中一部分记录的关键字均比另一部分记录的关键字小.之后分别对这两部分记录继续进行排序,以达到整个序列有序的目的. ...
- java版排序算法简介及冒泡排序以及优化,选择排序,直接插入排序,希尔排序,堆排序,快速排序及其优化前言 2 分类 2 稳定性 3 时间复杂度 4 Java实现版本 5 1、冒泡排序 6 2、选择排序
好吧 ~~csdn太难用了....尼玛...写了半天的也无法弄进去...lz正在找更好地博客,or放在github上打算.. 下边是lz自己的有道云分享,大概内容是 http://note.youda ...
- C++基础知识(二)--左值右值--逻辑表达式求值优化--逗号运算符与表示式--输入输出格式控制...
:一.C++左值右值概念 左值:c++将变量名代表的单元称为左值,而将变量的值称为右值,左值必须是内存中可以访问且可以合法修改的对象,因此只能是变量名,而不能是常量或表达式.即左值可以寻址. 右值:将 ...
- 八十一、最快最优的快速排序和优化
@Author:Runsen 编程的本质来源于算法,而算法的本质来源于数学,编程只不过将数学题进行代码化. ---- Runsen 快速排序 不久前,我在牛客中看到这样一个笑话,面试官让他写一个快速排 ...
- 当前方法的代码已经过优化,因此无法计算表达式的值
当前方法的代码已经过优化,因此无法计算表达式的值 /************************************************************************** ...
- 单目标应用:白鲸优化算法(Beluga whale optimization,BWO)优化双向长短时记忆BiLSTM的权值和阈值(提供MATLAB代码)
一.算法简介 白鲸优化算法(Beluga whale optimization,BWO)由Changting Zhong等人于2022年提出,该算法模拟了白鲸游泳,觅食和"鲸鱼坠落" ...
- seo优化怎样选取网站关键词?关键词如何设置?
我们知道,seo优化是网站推广的方式之一,其主要形式来源于网站关键词排名,什么是关键词排名这里不多说,已经聊过了.那么,这个关键词是什么样的关键词,大家理所应当的想到,自己的产品自己的服务自己的牌子呗 ...
最新文章
- 引用 提高开发水平的几项必备技术
- 广东海洋大学计算机科学与技术排名,最新排名!广东高校22个学科位居全球前50位...
- 嵌入式闪存您了解多少?听听专家怎么说!
- 微信小程序,你的场景呢?
- Spring Cloud sleuth with zipkin over RabbitMQ教程
- 运行数据区②---堆
- 实现图片打乱_2020 回顾 | 25张图片,记录潮州的这一年
- 在没人相信的时候,你的坚持才真正可贵
- 快速迁移数据中心:华为云数据库SQL Server实践案例技术解析
- 多对多关联映射(双向关联)见项目:me_many_to_many
- webpack教程——css的加载
- android焦点动画,Android编程中PopupWindow的用法分析【位置、动画、焦点】
- linux下通过伪造udp包来实现指定网卡发送数据
- 在地图上点击一下,在图层上画一个点,并显示相关的信息
- 求助:ATI HD3200 LINUX驱动
- 手把手教你安装Sketch破解版和measure插件
- phpspider 的简单使用
- 3dmax如何删除多余的时间帧
- PyQt5 小工具:Excel数据分组汇总器...
- 人民币对美元汇率中间价报6.7472元 上调469个基点