算法导论_第八章_线性时间排序

12 篇文章 0 订阅
10 篇文章 0 订阅

算法导论_第八章_线性时间排序


排序算法的下界


决策树模型


决策树是一颗完全二叉树


决策树的每个节点代表需要比较的两个数,叶节点为一个数的排序。所以任何正确的排

序,n个元


素的n!个排列情况都应该出现在叶节点上。

比较排序的最坏情况出现在比较次数为决策树的高度,而决策数的高度

h<=lg(n!)=Ω(n*lg(n))


堆排序和归并排序都是渐进最优的比较排序算法


其运行时间上界为O(n*lg(n))




计数排序:


基本思想

对于每一个输入的元素x,确定小于x的元素个数。利用这一信息可以直接把x放到它在输出

数组中的位置上。


下面来看代码

/*************************************************************************
	> File Name: counting_sort.cpp
	> Author:chudongfang 
	> Mail:1149669942@qq.com 
	> Created Time: 2016年06月29日 星期三 08时42分35秒
 ************************************************************************/

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;

void counting_sort(int a[],int b[],int n,int k);
int main(int argc,char *argv[])
{
    int a[100],b[100];
    int n;
    int max=-INF;
    printf("please input the number of array:");
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        if(max<a[i])  max=a[i];//确定输入元素的最大值,便于开辟c数组
    }
    
    counting_sort(a,b,n,max);
    for(int i=1;i<=n;i++)
        printf("%d ",b[i]);
    return 0;
}
//a数组表示要排序的数组,
//b表示排序过后的数组,
//c表示a数组元素在b数组中的位置。
void counting_sort(int a[],int b[],int n,int k)
{
    int c[1000];
    
    for(int i=0;i<=k;i++)
        c[i]=0;
    
    for(int i=1;i<=n;i++)
        c[a[i]]++;//初始化为1代表有1个元素与其相等,为其本身
   
    /*******important**************/
    for(int i=1;i<=k;i++)//确定比其小或等于的元素的个数
        c[i]+=c[i-1];
    
    for(int j=n;j>=1;j--)
    {
        b[c[a[j]]]=a[j];//确定位置
        c[a[j]]--;//若有重复,则位置减1   
                  //在这里,其保证了如果多个元素相同,其在b数组中的顺序与其
                  //在a数组中的顺序相同,就保证了其稳定性。  
    }
    /*****************************/
}




据计算其时间复杂度为Θ(n)

计数排序不涉及到比较,所以其脱离比较模型,时间复杂度可以降低很多,再者其具有

稳定性,对于附带卫星数据来说,比较重要。

不过当k非常大时,可能导致内存空间利用过多。



基数排序:


排序思想

假定要对一个有10位的十进制的数排序,那么就从最低有效位开始进行排序,就是先对个位数进行排序,

然后十位,百位……直到排序完成,在排序过程中卫星数据顺序不变,所以需要稳定的排序算法。


这里可以采用基数排序

下面上具体代码:

/*************************************************************************
	> File Name: radix_sort.cpp
	> Author:chudongfang 
	> Mail:1149669942@qq.com 
	> Created Time: 2016年06月29日 星期三 09时46分44秒
 ************************************************************************/

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef struct node
{
    int ge;
    int shi;
    int bai;
}NODE;
void counting_sort_ge(NODE a[],NODE b[],int n,int k);
void counting_sort_shi(NODE a[],NODE b[],int n,int k);
void counting_sort_bai(NODE a[],NODE b[],int n,int k);

int main(int argc,char *argv[])
{
    NODE a[100];
    NODE b[100];
    a[1].ge=1;
    a[1].shi=2;
    a[1].bai=3;
    
    a[2].ge=2;
    a[2].shi=2;
    a[2].bai=2;

    a[3].ge=7;
    a[3].shi=2;
    a[3].bai=3;
    
    a[4].ge=3;
    a[4].shi=1;
    a[4].bai=2;
    
    a[5].ge=5;
    a[5].shi=2;
    a[5].bai=3;
    int n=5,d=3;
    int max_ge=7;
    int max_shi=2;
    int max_bai=3;
    counting_sort_ge(a,b,n,max_ge);
    counting_sort_shi(b,a,n,max_shi);
    counting_sort_bai(a,b,n,max_bai);
    for (int i = 1; i <=5; ++i)
    {
        printf("%d%d%d\n",b[i].bai,b[i].shi,b[i].ge);
    }
            
    
    
    return 0;
}

void counting_sort_ge(NODE a[],NODE b[],int n,int k)
{
    int c[1000];
    
    for(int i=0;i<=k;i++)
        c[i]=0;
    
    for(int i=1;i<=n;i++)
        c[a[i].ge]++;//初始化为1代表有1个元素与其相等,为其本身
   
    /*******important**************/
    for(int i=1;i<=k;i++)//确定比其小或等于的元素的个数
        c[i]+=c[i-1];
    for(int j=n;j>=1;j--)
    {
        b[c[a[j].ge]]=a[j];//确定位置
        c[a[j].ge]--;//若有重复,则位置减1   
                  //在这里,其保证了如果多个元素相同,其在b数组中的顺序与其
                  //在a数组中的顺序相同,就保证了其稳定性。  
    }
    /*****************************/
}
void counting_sort_shi(NODE a[],NODE b[],int n,int k)
{
    int c[1000];
    
    for(int i=0;i<=k;i++)
        c[i]=0;
    
    for(int i=1;i<=n;i++)
        c[a[i].shi]++;//初始化为1代表有1个元素与其相等,为其本身
   
    /*******important**************/
    for(int i=1;i<=k;i++)//确定比其小或等于的元素的个数
        c[i]+=c[i-1];
    
    for(int j=n;j>=1;j--)
    {
        b[c[a[j].shi]]=a[j];//确定位置
        c[a[j].shi]--;//若有重复,则位置减1   
                  //在这里,其保证了如果多个元素相同,其在b数组中的顺序与其
                  //在a数组中的顺序相同,就保证了其稳定性。  
    }
    /*****************************/
}


void counting_sort_bai(NODE a[],NODE b[],int n,int k)
{
    int c[1000];
    
    for(int i=0;i<=k;i++)
        c[i]=0;
    
    for(int i=1;i<=n;i++)
        c[a[i].bai]++;//初始化为1代表有1个元素与其相等,为其本身
   
    /*******important**************/
    for(int i=1;i<=k;i++)//确定比其小或等于的元素的个数
        c[i]+=c[i-1];
    
    for(int j=n;j>=1;j--)
    {
        b[c[a[j].bai]]=a[j];//确定位置
        c[a[j].bai]--;//若有重复,则位置减1   
                  //在这里,其保证了如果多个元素相同,其在b数组中的顺序与其
                  //在a数组中的顺序相同,就保证了其稳定性。  
    }
    /*****************************/
}









其利用了计数排序,对nd位数来说

其时间复杂度为:Θ(d*(n+k))

d为常数时且k=O(n),基数排序具有线性的时间代价

由于其不是原址排序,所以其会耗费大量内存空间,当内存非常珍贵的情况下,利用快排




桶排序


桶排序假设输入的数据服从均匀分布,平均情况下,其时间代价为O(n)


桶排序将[0,1)区间划分为n个相同大小的子区间上,或称为桶,然后将n个输入数分别放到各个桶中,先对

桶中的数进行排序,然后遍历每个桶,按照次序把各个桶中的元素列出来。


下面看具体代码

/*************************************************************************
	> File Name: bucket_sort.cpp
	> Author:chudongfang 
	> Mail:1149669942@qq.com 
	> Created Time: 2016年06月29日 星期三 10时50分26秒
 ************************************************************************/

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
void bucket_sort(float a[],float b[][100],int num[],int n,float max);
int main(int argc,char *argv[])
{
    float a[100];//要排序的数组
    float b[100][100];//桶
    int num[100];//桶内的元素
    int n;
    float max=-INF;
    memset(num,0,sizeof(num));//赋值清零
    
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%f",&a[i]);
        if(a[i]>max)  max=a[i];//找到最大值
    }
    
    bucket_sort(a,b,num,n,max);//桶排序
    
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=num[i];j++)
            printf("%g ",b[i][j]);
    }
    return 0;
}


void bucket_sort(float a[],float b[][100],int num[],int n,float max)
{
    int i,j,k;
    for(i=1;i<=n;i++)
    {
        j=(int)(a[i]/max*n);//找到其应该放入桶的下标
        if(!j)  j++;  //如果为0,则变为1
        num[j]++;     //计数器加1
        
        /*************插入排序_部分功能********************/
        for(k=num[j];k>1&&b[j][k-1]>a[i];k--)
            b[j][k]=b[j][k-1];
        b[j][k]=a[i];
    }
}



桶排序效率分析:


桶排序的时间代价为

T(n)=Θ(n)+sum(O(n[i]^2))


最后求得其时间复杂度为:Θ(n)


即使输入数据不服从平均分布桶排序也仍然可以在线性时间内完成。只要输入数据满足所有桶的大小的平

方和与总的元素呈线性关系。







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值