这章刚开始证明了基于比较的排序的算法在最坏情况下,都需要做nlgn次比较。
由此可以推出合并排序快速排序都是渐进最优的比较排序算法。
线性时间排序:
1.计数排序
计数排序假设N个输入元素中的每一个都是介于0~k之间的整数,此处K为某个整数。当k=O(n)时,计数排序的运行时间为O(n)。
计数排序的思想是对每个元素x找出小于x的元素个数,有了这个信息最后把它直接插入到最终输出数组相应的位置即可。比如比它大的有三个则它就应该在第四个位置。
实现代码:
void count_sort(int a[],int b[],int k)
{
int c[MAX]={0};
for(int j=0;j<MAX-1;j++)
c[a[j]]=c[a[j]]+1;//得到每个元素个个数
for(int i=0;i<MAX-2;i++)
c[i+1]=c[i+1]+c[i];//得到小于等于元素的个数
for(int j=MAX-1;j>=0;j--)
{
b[c[a[j]]]=a[j];
c[a[j]]=c[a[j]]-1;
}
}
最后需要说明的是计数排序牺牲了空间换取了时间,计数排序是稳定的。
2.基数排序
算法是根据这张图来排序的,关于为什么要从最低位开始排序而不是从最高位开始,主要是因为如果从最高位开始的话,每次比较的话都要对前面的位的数字进行记录这样会产生很多中间数组,然而从最低位开始话,直接就可以排好所有的不用额外操作。能这样排序的前提建立在每一位的排序都必须是稳定的。
代码实现:
// radix_sort.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <cmath>
#define MAX 7
void count_sort(int m[],int a[],int b[],int k)
{
//m[]要排序的的数组
//a[]每个数相同位组成的数组
//b[]得到的排序结果
int c[10]={0};
for(int j=0;j<MAX;j++)
c[a[j]]=c[a[j]]+1;//得到每个元素的个数
for(int i=0;i<10-1;i++)
c[i+1]=c[i+1]+c[i];//得到小于等于元素的个数
for(int j=MAX-1;j>=0;j--)
{
b[c[a[j]]-1]=m[j];
c[a[j]]=c[a[j]]-1;
}
}
int min_10(int m,int n)
{
if(0 == n)
return 1;
for(int i=1;i<n;i++)
m=m*m;
return m;
}
void radix_sort(int m[],int d)
{
int a[MAX];
int b[MAX];
for(int j=0;j<d;j++)
{
for(int i=0;i<=MAX;i++)
a[i]=m[i]/min_10(10,j)%10;
count_sort(m,a,b,MAX);
for(int i=0;i<MAX;i++)
m[i]=b[i];
}
for(int i=0;i<MAX;i++)
printf("%d\t",m[i]);
getchar();
}
int _tmain(int argc, _TCHAR* argv[])
{
int a[MAX]={329,457,657,839,436,720,355};
radix_sort(a,3);
return 0;
}
代码还是主要基于基数排序实现每一位的排序,然后依次排完每一位。时间复杂度为计数排序时间复杂度O(n)。