书接上文,上次讲到了双路快速排序,双路快速排序是将等于v(标志数)的数也进行交换,从而避免了在处理有大量重复数据的数组分组时的不平衡。而三路快速排序则是将等于v的数也分成一组,同样可以解决上述问题。其原理如下:
1、采用随机排序的方法将某个数作为分割数,放在数组开头,该数定义为v。将小于v的一段数组开头的数索引定义为lt,将需要遍历的数组的索引定义为i,将小于v的一段数组的索引定义为gt,数组的开头和结尾的索引分别为l和r。原理图如下:
2、对索引i进行维护,逐个比较索引i对应的数与v的关系。如果arr[i]<v,那么将arr[i]和arr[lt+1]交换,之后将索引i和lt分别向后移动一位。如下图蓝色的e和灰绿色的那块相交换
3、如果arr[i]=v,则将arr[i]纳入等于v的那一部分,之后将索引i向后移动一位
4、如果arr[i]>v,则将arr[i]与arr[gt-1]交换位置,之后将索引gt向前移动一位,但是要注意,这时,索引i不需要移动,因为交换过来的数不知道大小,下一步还需要接着判断。
5、按照这个流程,gt会和i重合,则结束比较的过程
6、最后,不要忘了将arr[l]和arr[lt]交换位置,注意:这里交换位置的是arr[lt]。排序完成
代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
#ifndef QUICKSORT3_H
#define QUICKSORT3_H
//三路快速排序算法
#include <iostream>
#include <stdlib.h>
using namespace std;
template < typename T>
void __QuickSort3way(T *arr, int l, int r)
{
//递归的终止条件
if (l>=r)
{
return ;
}
else
{
//随机快速排序选取的随机值,为了避免在整体大致有序的情况下产生分组不平衡现象,使算法退化
int RAND = ( rand () % (r - l) + l);
swap(arr[l], arr[RAND]);
T v = arr[l];
//小于v的分组的初始索引
int lt = l;
//大于v的分组的初始索引
int gt = r + 1;
//等于v的分组的初始索引,并且,此索引是数组遍历值的索引
int i = l + 1;
while (i<gt)
{
//如果遍历的数据小于v
if (arr[i]<v)
{
//将该数组与第一个等于v的数据交换
swap(arr[lt + 1], arr[i]);
//维护小于v的索引和待遍历的数据的索引
lt++;
i++;
}
//如果数据大于v
else if (arr[i]>v)
{
//交换该数与大于v的第一个数,但是在这里不需要维护i的索引
swap(arr[i], arr[gt - 1]);
gt--;
}
else //arr[i]==v
{
i++; //直接维护i的索引
}
}
//最后将数组第一个数v和小于v的最后一个数互换
swap(arr[l],arr[lt]);
__QuickSort3way(arr,l,lt);
__QuickSort3way(arr,gt,r);
}
}
template < typename T>
void QuickSort3way(T *arr, int n)
{
__QuickSort3way(arr, 0, n - 1);
}
#endif // !QUICKSORT3_H
|
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/weixin_43862688/article/details/90299742