比较器与桶排序

比较器

前面介绍的选择排序、冒泡排序、插入排序、归并排序、堆排序以及快速排序,还有选择排序的变种希尔排序、鸡尾酒排序,这些都是基于比较的排序。对于这些基于比较的排序,可以通过修改比较器,来达到比较其他非基本数据类型的比较。

如下图是一个比较器的实现:

比较器与桶排序

如果返回一个负数,认为第一个参数应该排在前面;若返回正数,则第二个参数排在前面。所以我们经常可以看到下面的写法:

比较器与桶排序

这里实现的是由大到小排序。

在C++中,比较器的实现就是重载运算符。

下面在举一个例子,将学生按年龄大小的顺序由小到大排序,如果年龄相同,按学号由小到大排列:

比较器与桶排序

我们知道优先级队列的底层结构是小根堆,现在我们想要将其改为大根堆,也可以通过比较器实现。

比较器与桶排序

但有一点需要注意,因为选择器是由我们自己实现的,要注意不能在比较的过程冲形成环,即自己设置的比较策略应该具有传递性。

如有a、b、c存在,设置a>b,b>c,c>a,该种比较策略是错误的。

桶排序

桶排序不是基于比较的排序,它只能用于对基本数据类型进行排序,只与具体业务有关。

1. 计数排序

某公司有员工10人,员工的年龄在20到50之间,请对员工的年龄进行排序。

用计数排序对员工进行排序:

1. 创建容器数组arr[50 - 20 + 1];

2. 依次统计每个年龄有多少人,即arr[0]储存20岁的员工有多少人,arr[1]存储21岁有多少人。。。。。。

按照数组arr的顺序依次输出每个年龄。

该算法的时间复杂度为O(N),额外空间复杂度为O(M)。

但需要注意的是,这里的要求是对员工的年龄进行排序,所以可以用计数排序。如果题目的要求是请依据年龄对员工进行排序,则不能使用计数排序。因为使用桶排序的前提是需要构造出容器来存储要排序的数据类型。

另外,如果要排序的数字的最小值与最大值之间相差太大,也不适合使用桶排序。

2. 基数排序

使用基数排序的算法进行排序时,需要经过以下几个步骤:

1. 选出最大的一个数字,判断它是几位数,并将其余数字补至最高位。

2. 准备10个桶[0 ,9]。

3.根据各位数字个位的值依次将每个数字装入桶中。

4. 从左到右依次将桶中的数字倒出。

5.根据各位数字十位的值依次将每个数字装入桶中。

6.重复上述过程,直到最高位。

基数排序的时间复杂度应为O(N*K),其中k是最大数字的位数,一般k的数值不会很大,所以可以将该算法的时间复杂度看作O(N)。