一般我们使用的堆排序,归并排序都是属于比较排序,也就是通过比较元素的大小来进行排序,可以通过决策树分析出比较排序的时间下界是O(nlgn),堆排序和归并排序都是渐进最优的比较排序算法。还有其他的排序方法不是通过比较,下面总结一下:
一:计数排序
大致思路是将数组中所有元素对应小于这个元素的个数存储起来,这样我们可以直接知道这个元素的位置,因为可能出现相同的元素,所以我们从后面输出(为了稳定性)而且每次找到一个元素的位置后要把对应的小于x的个数减一,这样再次输出时就被会放到前一个位置上。最后的时间很好是O(n),但是要开三个数组,而且其中一个数组要开从0到所有比较的数中最大的数,所以是典型的空间换时间,如果比较的元素中有一些非常大就没有办法进行排序。
#include<iostream>
#include<algorithm>
using namespace std;
const int maxnum = 0xffff;
const int maxsize = 0xff;
int length;
void CounterSort(int a[], int b[], const int k)
{
int c[maxnum];
int i;
for (i = 0; i <= k; i++)
c[i] = 0;
for (i = 1; i <= length; i++)//统计a中不同的数分别出现的个数
c[a[i]]++;
for (i = 1; i <= k; i++) //将c[i]现在代表有几个数小于或等于i
c[i] = c[i] + c[i - 1];
for (i = length; i >= 1; i--)
{
b[c[a[i]]] = a[i];
c[a[i]]--; //对相同元素的个数减一
}
}
int main()
{
int a[maxsize], b[maxsize];
cin >> length;
int max = -1;
for (int i = 1; i <= length; i++)
{
cin >> a[i];
if (max < a[i])
max = a[i];
}
CounterSort(a, b, max);
for (int i = 1; i <= length; i++)
cout << b[i] << " ";
cout << endl;
return 0;
}
二:基数排序
大致思路是对于一个位数有限的数,假设位数最高为d,此时从最低位开始排序到最高位就可以完成排序,由于每一位是0-9的数字我们可以在O(n)的时间内完成排序,因此总体的时间复杂度为O(n)。
三、桶排序(Bucket Sort)
桶排序(Bucket Sort)的思想是将数组分到有限数量的桶子里。每个桶子再个别排序(有可能再使用别的排序算法),由于每个桶里面的元素比较少,只需要有限次的操作。当要被排序的数组内的数值是均匀分配的时候,桶排序可以以线性时间运行。桶排序过程动画演示:Bucket Sort,桶排序原理图如下: