快速排序 改进快排的方法
快速排序法事应用最广泛的排序算法之一,最佳情况下时间复杂度是 O(nlogn)。但是最坏情况下可能达到O(n^2)。说明快速排序达到最坏情况的原因。并提出改善方案并实现之。
答:
改进方案:改进选取枢轴的方法
1、选取随机数作为枢轴。
但是随机数的生成本身是一种代价,根本减少不了算法其余部分的平均运行时间。
2、使用左端,右端和中心的中值做为枢轴元。
经验得知,选取左端,右端,中心元素的中值会减少了快排大约 14%的比较。
3、每次选取数据集中的中位数做枢轴。
选取中位数的可以在 O(n)时间内完成。(证明见《算法导论(第二版) 》) P111 第九章中位数
和顺序统计学:在平均情况下,任何顺序统计量(特别是中位数)都可以在线性时间内得到。
快排的分割策略:
第一步是通过将枢轴元与最后一个元素交换使得枢轴元离开要被分割的数据段;i 从第一个
元素开始而 j 从倒数第二个元素开始。当 i 在 j 左边时,我们将 i 右移,移过那些小于枢轴
元的元素,并将 j 左移,移过那些大于枢轴元的元素。当 i 和 j 停止时,i 指向的是大元素,
j指向的是小元素。如果 i 在 j 左边,那么将这两个元素互换。 如果此时 i 和 j 已经交错即 i>j
所以不交换。此时把枢轴元与 i 所指的元素交换。
实例演示:
其他可以改进的地方(网络搜集) :
1、 快速排序在处理小规模数据时的表现不好.
这个时候可以改用插入排序。
当数据规模小于一定程度时,改用插入排序。具体小到何种规模时,采用插入排序,这个理
论上还不解,一些文章中说是 5 到 25 之间。SGI STL 中的快速排序采用的值是 10.
2、对于一个每个元素都完全相同的一个序列来讲,快速排序也会退化到 O(n^2)。
要将这种情况避免到,可以这样做:
在分区的时候,将序列分为 3 堆,一堆小于中轴元素,一堆等于中轴元素,一堆大于中轴元
素,下次递归调用快速排序的时候,只需对小于和大于中轴元素的两堆数据进行排序,中间
等于中轴元素的一堆已经放好
#include<stdio.h>
#include<stdlib.h>
//选取枢轴,将所有元素小于它的移到它的左边,大于它的移到它的右边,返回它的位置.
int partition(int A[],int low,inthigh)
{
if(A == NULL || low< 0 || high < 0 || low > high) //m>f>l
{
throw std::exception("invalidParameters!");
}
//选取枢轴位置,取首元素,中间元素和末尾元素的中值作为枢轴
int mid = low+(high -low) >> 1;
int firstElem = A[low];
int lastElem = A[high];
int midElem =A[mid];
int index = GetMiddleValue(A,low,high);//中位数的位置
//将枢轴元素放在第一个位置
if(index != low)//交换
{
int temp =A[index];
A[index]= firstElem;
A[low]= temp;
}
//定义两个标记,一个负责向后扫描,一个负责向前扫描
//向后每遇到一个比它大的就交换,向前扫描每遇到一个比它小的就交换
int x = A[low];//枢轴元素
int flagL =low;
int flagH =high;
while(flagL <flagH)
{
while(A[flagH] >= x &&flagL < flagH)//找到第一个比枢轴小的元素,放到当前flagL的位置
flagH--;
if(flagL < flagH)
A[flagL++] =A[flagH];
else
break;
while(A[flagL] <= x &&flagL < flagH)//找到第一个比枢轴大的元素,放到当前flagH的位置
flagL++;
if(flagL <flagH)
A[flagH--] =A[flagL];
else
break;
}
A[flagL]= x;
return flagL;
}
void qsort(int A[],intlow,int high)
{
if(low <high)
{
int k =partition(A,low,high);
qsort(A,low,k-1);
qsort(A,k+1,high);
}
}
int main()
{
int A[] ={0, 10, -5, 7, 8, -18, 33};
qsort(A,0,sizeof(A)/sizeof(int)-1);
for(int i=0;i<sizeof(A)/sizeof(int);i++)
printf("%d ",A[i]);
return 0;
}
//3值取中值
intGetMiddleValue(int A[],int low,int high)
{
int mid=low+(high-low)>>1;
int y1=A[low]>A[mid]?low:mid;
int y2=A[low]>A[high]?low:high;
int y3=A[mid]>A[high]?mid:high;
if (y1==y2)
{
return y3;
}
else
return A[y1]>A[y2]?y2:y1;
}
或
a + b + c - (a > b ? a > c ? a : c : b > c ? b : c) - (a < b ? a < c ? a : c : b < c ? b : c)
快速排序 改进快排的方法相关推荐
- 使用Java泛型实现快速排序(快排,Quicksort)
原文:https://my.oschina.net/u/1382972/blog/169747 还可以参考:http://blog.csdn.net/stushan/article/details/5 ...
- 快速排序、快排的优化 及Java实现
一.快速排序的思想 选取一个比较的基准,将待排序数据分为独立的两个部分,左侧都是小于或等于基准,右侧都是大于或等于基准,然后分别对左侧部分和右侧部分重复前面的过程,也就是左侧部分又选择一个基准,又分为 ...
- 快速排序—三路快排 vs 双基准
快速排序被公认为是本世纪最重要的算法之一,这已经不是什么新闻了.对很多语言来说是实际系统排序,包括在Java中的Arrays.sort. 那么快速排序有什么新进展呢? 好吧,就像我刚才提到的那样(Ja ...
- 八大排序算法之快速排序(下篇)(快排的优化+非递归快排的实现)
目录 一.前言 1.快速排序的实现: 快速排序的单趟排序(排升序)(快慢指针法实现): 2.未经优化的快排的缺陷 二.快速排序的优化 1.三数取中优化 优化思路: 2. 小区间插入排序优化 小区间插 ...
- Java实现快速排序(快排)
快速排序是冒泡排序的改进版,也是最好的一种内排序,在很多面试题中都会出现,也是作为程序员必须掌握的一种排序方法. 快速排序由C. A. R. Hoare在1962年提出.它的基本思想是:通过一趟排序将 ...
- 手动编写快排(快速排序),实现从小到大和从大到小排序
快排的方法类 package com.hcc.util;public class QuickSort {/*** * @param arr 存放数据的数组* @param left 需要排序的开始下标 ...
- python写快排_python 实现快速排序
Python排序算法之快速排序 快速排序(quickSort) 快排的思想:首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这 ...
- 快排Quick Sort到底有多快?
大师级的文章,总是能够使你更接近于事物的本质. 最近看了pongba的数学之美番外篇:快排为什么那么快.文中提到了Mackay的一篇文章(这里是译文),里面提到了使用信息论来解释快排与堆排的速度差 ...
- C语言实现稳定的快排
关于这种稳定的快排的思路,请看我之前的这篇文章: <对数器&Python实现稳定快排> 下面是实现代码: #include<stdio.h> #include<s ...
最新文章
- Linux服务名重命名
- 此文一出,从此无需再熬夜等待
- ASP.NET 2.0+Atlas编写鼠标拖放程序(2)
- N个数中选择M个数的组合(1MN)
- unity鼠标控制镜头旋转_Unity Camera教程之 摄像机跟随鼠标移动而旋转
- MySQL 使用Node.js异步查询结果为undefined的简单处理办法
- mysql 14.12_MySQL必知必会12-14 汇总 分组 子查询
- c#开源消息队列中间件EQueue 教程
- 服务器宕机可能的原因以及服务器宕机解决办法
- css3简记,了解一下?
- 百度云 java私塾_JAVA私塾-百度云
- 深入理解JVM虚拟机读书笔记——垃圾回收器
- moodle4.04无法上传中文文件名
- linux 开山(尚硅谷)--听课笔记-
- php家乡介绍网页,家乡网站设计与实现.doc
- 用MinIO对象存储构建企业数据集中备份系统
- 计算机桌面整洁,想让你的桌面变得整洁干净,这几款桌面整理软件别错过
- SWUST大二周赛 之农夫山泉有点甜
- 漏洞取证_使用Linux文件系统取证进行漏洞检测
- 学习 《电路》(尼尔森著,第十版)第一章笔记(电流)