数据结构之排序2(快速排序及其优化)
2018-03-10 19:58
393 查看
前面写了四个简单的排序算法,学习的时候也觉得很好理解,没有难度,可是,到快速排序我差点被打败,还好本宝挺了过来,现在觉得快排及其优化还是相当简单了,可能当时学习的时候不在状态吧!所以,现在的你是否也被快排倒的脑子一团糟,没关系,跟我的思路一起往下走。。。
一.快速排序的基本思想
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,以此达到整个数据变成有序序列。
整个过程可以递归也可以不递归,所以,快速排序可以分为两种,一种是递归的,一种是非递归的。
二.快速排序的三个步骤
(1)选择基准值:在待排序数中,按照某种方式挑出一个元素,作为 “基准”。
(2)分割操作:以该基准在序列中的实际位置,把序列分成两个子序列。此时,在基准值左边的元素都比该基准值小,在基准值右边的元素都比基准值大
(3)在基准值的左右两边不断重复(1)(2)步骤,直到整个数列有序为止。
三.选择基准值
根据快速排序的三个步骤你会有所疑问,就是到底基准值是怎么找到的,什么样的值才能称为基准值。。?
当然,基准值不是我想让它是它就是的,这个必须由我们程序根据不同的序列来确定,这里,我将给出三种基准值的选择方法。
1.固定位置
固定取序列的第一个或最后一个值为基准值,每次找到基准值的正确位置,不断重复完成排序。
如图所示,我给出一个序列,给出两个指向变量,分别指向arr数组的0号和len - 1 位置,再给出一个临时量tmp方便我们交换数据。固定位置选择基准是选择第一个或者最后一个数作为基准,这里我演示选择第一个数的情况。
经过这样一次,基准2已经在自己正确的位置,也就是说2的左边都小于2,右边的数都大于2。
我用代码实现一下固定选择基准的过程:
2.随机找基准
我们想,在待排序的部分已经部分有序的情况下,还这样固定位置选择基准会多排几次,多做几次无用功,导致效率降低,所以就引进了随机找基准的方法。
我们看下代码实现:
但是随即取基准值法也有一个缺点
3.三分取中法
与一般快速排序不同,三分取中法会选取最左值、中间值和最右值三个值中的中间值作为基准值,这样选取的基准值会降低最坏情况发生的几率。
经过这样交换之后,三个值中的中间值就会在start位置,再利用快速排序。
四.快速排序的优化
1.把和基准值相等的数靠近基准值
优化的时候我们这样想,把和基准值相等的数字都交换到基准值旁边,这样如果比较时和基准值相等就比较下一个,少去了很多比较的步骤。
四.题外话
http://blog.csdn.net/insistgogo/article/details/7785038
我觉得这个人写的超级好,本来我在努力好好写,后来发现了这篇博客,发现根本无法超越,大家如果看到这里,先谢谢你点开了这篇拙略的博客,然后推荐大家根据上面那篇博客学习。
一.快速排序的基本思想
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,以此达到整个数据变成有序序列。
整个过程可以递归也可以不递归,所以,快速排序可以分为两种,一种是递归的,一种是非递归的。
二.快速排序的三个步骤
(1)选择基准值:在待排序数中,按照某种方式挑出一个元素,作为 “基准”。
(2)分割操作:以该基准在序列中的实际位置,把序列分成两个子序列。此时,在基准值左边的元素都比该基准值小,在基准值右边的元素都比基准值大
(3)在基准值的左右两边不断重复(1)(2)步骤,直到整个数列有序为止。
三.选择基准值
根据快速排序的三个步骤你会有所疑问,就是到底基准值是怎么找到的,什么样的值才能称为基准值。。?
当然,基准值不是我想让它是它就是的,这个必须由我们程序根据不同的序列来确定,这里,我将给出三种基准值的选择方法。
1.固定位置
固定取序列的第一个或最后一个值为基准值,每次找到基准值的正确位置,不断重复完成排序。
如图所示,我给出一个序列,给出两个指向变量,分别指向arr数组的0号和len - 1 位置,再给出一个临时量tmp方便我们交换数据。固定位置选择基准是选择第一个或者最后一个数作为基准,这里我演示选择第一个数的情况。
经过这样一次,基准2已经在自己正确的位置,也就是说2的左边都小于2,右边的数都大于2。
我用代码实现一下固定选择基准的过程:
int Partion(int *arr, int low, int high)//快速排序寻找基准值 { int tmp=arr[low];//固定第一个值 while (low < high)//跳出while的条件是当low++,high--到相遇或者low>high { while (low < high && arr[high] >=tmp) //先用后边值和tmp比较,一直执行high--直到找到比tmp小的值,找到之后退出while循环 { high--; } if (low >= high)//退出while循环说明找到了比tmp小的值,这时判断一下low和high的位置,如果low<high说明这个值是在基准的右边比基准小,所以执行else { break; } else { arr[low] = arr[high];//把这时high的值放在空的low里 } while (low < high && arr[low] <= tmp) { low++; } if (low >= high) { break; } else { arr[high] = arr[low]; } } arr[low] = tmp; return low; }
2.随机找基准
我们想,在待排序的部分已经部分有序的情况下,还这样固定位置选择基准会多排几次,多做几次无用功,导致效率降低,所以就引进了随机找基准的方法。
我们看下代码实现:
/*随机选择枢轴的位置,区间在low和high之间*/ int SelectPivotRandom(int arr[],int low,int high) { //产生枢轴的位置 srand((unsigned)time(NULL)); int pivotPos = rand()%(high - low) + low; //把枢轴位置的元素和low位置元素互换,此时可以和普通的快排一样调用划分函数 swap(arr[pivotPos],arr[low]); return arr[low]; }
但是随即取基准值法也有一个缺点
3.三分取中法
与一般快速排序不同,三分取中法会选取最左值、中间值和最右值三个值中的中间值作为基准值,这样选取的基准值会降低最坏情况发生的几率。
void Swap(int *arr,int start,int end)//交换start和end { int tmp; tmp = arr[start]; arr[start] = arr[end]; arr[end] = tmp; } void Median_Of_Three(int *arr,int start,int mid,int end)//三分取中法 { //交换的目的是让arr[mid]<arr[start]<arr[end] if(arr[mid] > arr[end]) { Swap(arr,mid,end); } if(arr[mid] > arr[start]) { Swap(arr,mid,start); } if(arr[start] > arr[end]) { Swap(arr,start,end); } }
经过这样交换之后,三个值中的中间值就会在start位置,再利用快速排序。
四.快速排序的优化
1.把和基准值相等的数靠近基准值
优化的时候我们这样想,把和基准值相等的数字都交换到基准值旁边,这样如果比较时和基准值相等就比较下一个,少去了很多比较的步骤。
void Focus_Nums(int *arr,int par,int *left,int *right,int start,int end) { int LeftIndex = par - 1; int RightIndex = par + 1; for(int i = par - 1;i >=start;i--) { if(arr[i] == arr[par]) { if( i != LeftIndex) { Swap(arr,i,LeftIndex); LeftIndex--; } else { LeftIndex--; } } } *left = LeftIndex; for(int j = par + 1;j<=end;j++) { if(arr[j] == arr[par]) { if(j != RightIndex) { Swap(arr,RightIndex,j); RightIndex++; } else { RightIndex++; } } } *right = RightIndex; }
四.题外话
http://blog.csdn.net/insistgogo/article/details/7785038
我觉得这个人写的超级好,本来我在努力好好写,后来发现了这篇博客,发现根本无法超越,大家如果看到这里,先谢谢你点开了这篇拙略的博客,然后推荐大家根据上面那篇博客学习。
相关文章推荐
- 数据结构图文解析之:直接插入排序及其优化(二分插入排序)解析及C++实现
- [数据结构与算法]快速排序的优化实现(取中位数)
- 【数据结构之排序5】快速排序
- 看数据结构写代码(2) 选择排序 和 冒泡排序 算法优化
- 数据结构——选择排序、插入排序、冒泡排序、快速排序
- 数据结构(排序)--插入排序(未优化)
- sdutacm-数据结构实验之排序八:快速排序
- 数据结构实验之排序七:选课名单——快速排序
- 【数据结构与算法】内部排序之二:冒泡排序和选择排序(改进优化,附完整源码)
- 排序(6)——快速排序及其优化
- 【数据结构与算法基础】单链表及其应用基数排序 / Singly Linked List and radix sort
- 数据结构之交换排序之快速排序(参考整理严蔚敏数据结构)
- 程序员面试宝典之数据结构基础----排序之快速排序(简单快速排序与改进快速排序)总结
- java数据结构之排序(交换排序(冒泡泡排序、快速排序))
- 18. 数据结构进阶十八排序实现之快速排序
- 数据结构与算法——冒泡排序、选择排序和快速排序
- Hadoop链式MapReduce、多维排序、倒排索引、自连接算法、二次排序、Join性能优化、处理员工信息Join实战、URL流量分析、TopN及其排序、求平均值和最大最小值、数据清洗ETL、分析气
- java版排序算法简介及冒泡排序以及优化,选择排序,直接插入排序,希尔排序,堆排序,快速排序及其优化前言 2 分类 2 稳定性 3 时间复杂度 4 Java实现版本 5 1、冒泡排序 6 2、选择排序
- 【数据结构与算法】内部排序之一:插入排序和希尔排序的N中实现(不断优化,附完整源码)