您的位置:首页 > 财经 > 产业 > 湘潭关键词优化报价_关键词推广网站_单页网站制作教程_惠州百度推广排名

湘潭关键词优化报价_关键词推广网站_单页网站制作教程_惠州百度推广排名

2025/2/26 19:34:12 来源:https://blog.csdn.net/2301_79633555/article/details/143129581  浏览:    关键词:湘潭关键词优化报价_关键词推广网站_单页网站制作教程_惠州百度推广排名
湘潭关键词优化报价_关键词推广网站_单页网站制作教程_惠州百度推广排名

目录

一、前言

二、 快排性能的关键点分析

三、 三路划分基本思想

四、 思路分析

五、提醒

六、代码实现


一、前言

继续对快速排序的深入优化进行探讨

二、 快排性能的关键点分析

决定快排性能的关键点是每次单趟排序后,key对数组的分割。

如果每次选key都能做到基本二分居中,那么快排的递归树就是棵均匀的满二叉树,性能最佳。虽然实践中不能做到每次都二分居中,但是性能也还是可控的。

但如果每次选到最大值/最小值,划分0个和n-1的子问题时,时间复杂度就为O(N^2),当数组序列有序时就会出现这样的问题。前面已经用三数取中or随机选key解决了该问题。

但是,有些场景下hoae和lomuto(前后指针法)还是适应的不是很好,就是当数组中有大量重复数据时,该场景下性能是有些退化的。

针对数组中有大量重复数据的问题,我们采用三路划分的方式来解决。

三、 三路划分基本思想

那什么是三路划分呢?

在之前快排是排完序把key放在中间,左边比key值小,右边比key大,跟key相等的值在哪里并没有规定,跟key相等的值可以在左边,也可以在右边。

三路划分的基本思想是将数组分为三个部分:

当面对有大量跟key相同的值时,三路划分的核心思想类似hoare的左右指针和lomuto的前后指针的结合。核心思想是把数组中的数据分为三段:

小于基准元素key的放在左边

等于基准元素key的全部放在中间

大于基准元素key的放在右边

所以叫做三路划分算法。

通过三路划分的方式,可以避免在数组中有大量重复元素时出现的性能问题。

四、 思路分析

基本思路如下:

这里跟lomuto的前后指针法相结合(排升序)

  • key默认取left位置的值
  • left指向区间第一个元素位置,right指向区间最后一个元素位置,cur指向left+1的位置
  • 对cur进行判断
  1. 如果cur<key,cur指向的值与left位置的值进行交换,然后left++,cur++
  2. 如果cur>key,cur指向的值与right位置的值进行交换,然后right--
  3. 如果cur==key,cur++
  • 直到cur>right结束,排完单趟

结合图进行分析:

五、提醒

为什么cur==right要继续呢?

因为假如cur没有遇见比key大的值,right没有--,那么cur与right在相同位置时,并不能确定right所指向的值是否小于key。

例如下图的情况:

六、代码实现

//交换算法
void swap(int* a, int* b)
{int tmp = *a;*a = *b;*b = tmp;
}//三数取中
int GetMidi(int* a, int left, int right)
{int midi = (left + right) / 2;if (a[left] > a[right]){if (a[left] < a[midi]){return left;}else if (a[midi] < a[right]){return right;}else{return midi;}}else{if (a[right] < a[midi]){return right;}else if (a[midi] < a[left]){return left;}else{return midi;}}
}//三路划分算法
void QuickSort_Three_Way_Partition(int* a, int left, int right) //参数为数组下标
{if (left >= right){return;}int midi = GetMidi(a, left, right);swap(&a[left], &a[midi]);int begin = left;int end = right;int key = a[left];int cur = left + 1;while (cur <= end){if (a[cur] < key){swap(&a[cur], &a[begin]);begin++;cur++;}else if (a[cur] > key){swap(&a[cur], &a[end]);end--;}else if (a[cur] == key){cur++;}}		//递归左右区间QuickSort_Three_Way_Partition(a, left,begin-1);QuickSort_Three_Way_Partition(a, end+1, right);
}int main()
{int arr[] = {7,13,6,2,7,7,23,7,7,98,11,6,9,1,66,21,5};int sz = sizeof(arr) / sizeof(arr[0]);QuickSort_Three_Way_Partition(arr,0,sz-1);return 0;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com