线性时间排序

Posted a-runner

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线性时间排序相关的知识,希望对你有一定的参考价值。

  堆排序,快速排序的时间复杂度为nlog(n)。他们都是运用比较排序的结果。好比决策树模型。

  属于线性时间排序的算法有:计数排序,基数排序和桶排序。

计数排序:

 

先分别求出每个元素的频数,不过如果元素值较大时,比较浪费内存空间。

技术图片

def Counting_Sort(A,B,k):
    for i in range(k+1):
        c[i]=0
    for j in range(1,len(A)):
        c[A[j]]=c[A[j]]+1
    for i in range(1,k+1):
        c[i]=c[i]+c[i-1]
    for j in range(len(A),0,-1):
        B[c[A[j]]]=A[j]
        c[A[j]]=c[A[j]]-1

   排序代价为theta(n)。同时上述算法是稳定的,也就是说对于两个相同的数来说,在输入数组中先出现的数,在输出数组中也位于前面。

  实际上是因为我们在最后的给B赋值过程中,用的倒叙。

 

基数排序:

  基数牌组法先是按最低有效位进行排序。为确保基数排序的正确性,一位排序算法必须是稳定的。

#include <iostream>
#include <time.h>
using namespace std;
const n=10,m=4;
int Max(int B[n][m],int h)//O(n)
{//求最大k值
    int k=0;
    for (int i=0;i<n;i++)//O(n)
    {
        if (B[i][h]>k)
        {
           k=B[i][h];
        }
    }
    return k;
}
void COUNTING_SORT(int B[n][m],int C[n],int k,int h)//O(k)+O(n)+O(k)+O(n)=O(n+k)
{//计数排序
   
    int *D=new int[k+1];
    for (int i=0;i<=k;i++)//O(k)
    {
        D[i]=0;
    }
    for (int j=0;j<n;j++)//O(n)
    {
        D[B[j][h]]=D[B[j][h]]+1;
    }
    for (i=0;i<=k;i++)//O(k)
    {
        D[i+1]=D[i+1]+D[i];
    }
    for (j=n-1;j>=0;j--)//O(n)
    {
        C[D[B[j][h]]-1]=j;//把排好序的下标存放到数组C中以便按顺序把它存储到辅助数组E中。
        D[B[j][h]]=D[B[j][h]]-1;
    }
}
int Converted_to_Decimal(int A[],int B[][m],int i)//O(d)+O(d)=O(d)
{//此函数是将十进制数以2维数组B的形式存放。
    int x=A[i];
    for (int j=0;x>0;j++ )//O(d)循环了j<d次
    {
        B[i][j]=x%10;
        x=x/10;
    }
    if (j<m)
    {
        for (int k=j;k<m;k++)//O(d) 循环了d-j次
        {
            B[i][k]=0;
        }
    }
    return j;
}
void Radix_sort(int A[n],int B[][m],int C[n],int E[n],int d)
{
    d=m;
    for ( int i=0;i<n;i++)//O(nd)
    {
        Converted_to_Decimal(A,B,i);
    }
    for ( i=0;i<d;i++)//O(d) d为位数
    {//因为d<=d位数的最小值<=k,(例如3<3位数最小值100)所以d<=n+k,内层循环O(n)+O(n+k)+O(n)+O(n)+O(d)+O(n)=O(n+k)
        int k=Max(B,i);//O(n)
        COUNTING_SORT(B,C,k,i);//O(n+k)
        for (int i=0;i<n;i++)//O(n)
        {
            E[i]=A[C[i]];//每位上排好序后,将其复制到辅助数组E上。
        }
        for ( i=0;i<n;i++)//O(n)
        {
            Converted_to_Decimal(E,B,i);//把辅助数组E上的数转换成二维数组存放到二维数组B中。
        }
        for (i=0;i<n;i++)//O(n)
        {
            A[i]=E[i];//每次将按位排好序的数存放到数组A中以便在下一次循环中对下一位进行排序。
        }
    }//所以Radix_sort时间复杂度为O(d(n+k))
    //O(nd)+O(d(n+k))=O(d(n+k))
}
void main()
{
    srand( (unsigned)time( NULL ) );
    int A[n]={0};
    for (int i=0;i<n;i++)
    {
        A[i]=rand()%(n);
    }
    int  B[n][m]={0},C[n]={0},E[n]={0};
    Radix_sort(A,B,C,E,m);
    for ( i=0;i<n;i++)
    {
        cout<<A[i]<<" ";
    }
}

  更加详细,请看:https://blog.csdn.net/z84616995z/article/details/18502085

 

桶排序法:

  桶排序法假设了输入数据服从均匀分布,平均情况下时间代价为theta(n)。桶排序将[0, 1)区间分为n个相同大小额子区间,称之为桶。然后,将n个输入书分别放到各个同中。这里,我们按找顺序放进桶,桶中的元素是无序的。

class bucketSort(object):
    def insertSort(self,a):
        n=len(a)
        if n<=1:
            pass
        for i in range(1,n):
            key=a[i]
            j=i-1
            while key<a[j] and j>=0:
                a[j+1]=a[j]
                j-=1
            a[j+1]=key
    def sort(self,a):
        n=len(a)
        s=[[] for i in xrange(n)]
        for i in a:
            s[int(i*n)].append(i)
        for i in s:
            self.insertSort(i)
        return [i for j in s for i in j]
    def __call__(self,a):
        return self.sort(a)    

 

以上是关于线性时间排序的主要内容,如果未能解决你的问题,请参考以下文章

如何在android中的地图片段内中心线性布局?

最全排序算法原理解析java代码实现以及总结归纳

垂直线性布局中的多个片段

快速排序线性时间?

动画展现十大经典排序算法(附代码)

线性排序搜索