时空权衡之计数排序

 

计数排序是输入增强的一个例子,针对待排序列表(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;
}
复制代码

明显这是效率为线性的一个算法,这是遇到过时间效率最好的算法,但是显然需要的空间比较多

 

posted @   biong  阅读(402)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示