计数排序是输入增强的一个例子,针对待排序列表(A[])的每一个元素,算出列表中小于该元素的元素个数,并把结果记录在一张表(count[])中,个数之处了该数在有序表中的位置。
例如:A[7]={62,31,84,96,19,47}
其中62有3个数字小于62,分别是19 31 47,A[0]=62,count[0]=3,这里3就是小于62的数的个数。
算法流程:
for i<-0 to n-1 do count[i]<-0
for i<-0 to n-2 do
for j<-i+1 to n-1 do
if A[i]<A[j]
count[j]<-count[j]+1
else
count[i]<-count[i]+1
for i<-0 to n-1 so S[count[i]]<-A[i]
#include<iostream> using namespace std; int main() { int A[1001];//可排序数组 int count[1001];// int S[1002];//存好已经排好序的数组 int n,j,i; cin>>n;//输入数据大小 for(i=0;i<n;i++) { cin>>j; A[i]=j; count[i]=0; }//输入数据 for(i=0;i<=n-2;i++) { for(j=i+1;j<=n-1;j++) { if(A[i]<A[j]) { count[j]++; } else count[i]++; } } for(i=0;i<=n-1;i++) S[count[i]]=A[i]; for(i=0;i<n;i++) cout<<S[i]; return 0; }
算法的效率如何?
该算法的基本操作为if(A[i]<A[j]),一共执行次数{n(n-1)}/2次,所以该算法执行键值比较次数和选择排序的一样多,而且占用了线性数量的额外空间。
考虑另外一种计数方法:分布计数
这种排序方法是线性效率的,用空间换时间、利用输入列表的特性,使得效率大大提升。
算法伪代码:
DistributionCountingSort(A[0...n-1],l,u)
//分布计数法,对来自有限范围整数的一个数组进行排序
//输入:数组A[0..n-1],数组的整数位于l和u之间
//输出:A中的元素构成的非降序数组S[0..n-1]
for j<-0 to u-1 do D[j]<-0
for i<-0 to n-1 do D[A[i]-l]++;
for j<-1 to u-l do D[j]=D[j-1]+D[j]//重新计算分布
for i<-n downto 0 do
j<-A[i]-l
S[D[j]-1]<-A[i]
D[j]<-D[j]-1
return S
#include<iostream> using namespace std; int main() { int A[1001];//可排序数组 int D[1001]; int S[1002];//存好已经排好序的数组 int n,j,i,l,u; cin>>n;//输入数据大小 cin>>l>>u;//数组元素大小在[l,u]之间 for(i=0;i<n;i++) { cin>>j; A[i]=j; }//输入数据 int d; d=u-l;//数组元素最大值与最小值的差值 for(j=0;j<=d;j++)//统计分布计数的数组 D[j]=0; for(i=0;i<=n-1;i++)//对A[i]的元素统计计数 D[A[i]-l]++; for(j=1;j<=d;j++)//重新计算计数 D[j]=D[j-1]+D[j]; for(i=n-1;i>=0;i--) { j=A[i]-l; S[D[j]-1]=A[i]; D[j]--; } for(i=0;i<n;i++) cout<<S[i]<<" "; return 0; }
明显这是效率为线性的一个算法,这是遇到过时间效率最好的算法,但是显然需要的空间比较多