第八章 线性时间排序
本章介绍了3种在线性时间内进行排序的算法,然而这几种算法存在诸多限制
1.计数排序
计数排序算法基于以下假设:输入的每一个元素都是介于0到k之间;k的值是n的线性函数;空间效率低下;
template <class T>
void CountSort(T* a,int n,int k)
{
int* c = new int[k + 1];
T* b = new T[n];
for (int i = 0; i <= k; ++i)
{
c[i] = 0;
}
for (int i = 0; i < n; ++i)
{
c[a[i]]++;
}
for (int i = 1; i <= k; ++i)
{
c[i] += c[i - 1];
}
for (int i = n - 1; i >= 0; --i)
{
b[c[a[i]] - 1] = a[i];
c[a[i]]--;
}
for (int i = 0; i < n; ++i)
{
a[i] = b[i];
}
if (b != NULL)
{
delete [] b;
b = NULL;
}
if (c)
{
delete [] c;
c = NULL;
}
}
2.基数排序算法
基数排序算法在输入元素在0到n^d次方时,拥有Θ(d*n)的时间复杂性,然而其并非本地排序,空间效率低下,而且常系数很大。
void RadixSort(int* a,int n,int k)
{
int *c = new int[k];
int *b = new int[n];
int divisor = 1;
int _max = a[0];
for (int i = 1; i < n;++i)
{
if (_max < a[i])
{
_max = a[i];
}
}
int d = (float)log((float)_max)/log((float)k) + 1;
for (int j = 0; j < d; ++j)
{
for (int i = 0; i < k; ++i)
{
c[i] = 0;
}
for (int i = 0; i < n; ++i)
{
c[(a[i]/divisor)%k]++;
}
for (int i = 1; i < k; ++i)
{
c[i] += c[i - 1];
}
for (int i = n - 1; i >= 0; --i)
{
b[c[(a[i]/divisor)%k] - 1] = a[i];
c[(a[i]/divisor)%k]--;
}
for (int i = 0; i < n; ++i)
{
a[i] = b[i];
}
divisor *=k;
}
if (c != NULL)
{
delete [] c;
c = NULL;
}
if (b != NULL)
{
delete [] b;
b = NULL;
}
}
3.桶排序
桶排序的平均时间复杂性可以达到线性,然而其最坏运行时间依赖于对桶中数据的排序算法;同时空间效率也很低。
void BucketSort(int *a,int n)
{
vector<list<int> > b(n);
int _min,_max;
_min = _max = a[0];
for (int i = 1; i < n; ++i)
{
if (a[i] > _max)
{
_max = a[i];
}else if(a[i] < _min)
{
_min = a[i];
}
}
for (int i = 0; i < n; ++i)
{
b[(int)((a[i] - _min)*(n-1)/(_max - _min))].push_back(a[i]);
}
int j = 0;
for (int i = 0; i < n; ++i)
{
if (b[i].size() > 0)
{
b[i].sort();
while(!b[i].empty())
{
a[j] = b[i].front();
j++;
b[i].pop_front();
}
}
}