算法导论第八章思考题

这篇博客探讨了算法导论中的几个问题,涉及比较排序的时间下界,线性时间原址排序的实现及其应用场景。分析了决策树在确定性排序算法中的应用,证明了在平均情况下排序n个元素的时间代价是Ω(nlgn)。还讨论了线性时间对0-1值数组进行排序的可能性,并提出了满足特定条件的排序算法。此外,博主还解答了关于水壶配对和合并有序列表的排序问题,涉及排序算法的时间复杂度下界和最优策略。
摘要由CSDN通过智能技术生成

8-1(比较排序的概率下界) 在这一问题中,我们将证明对于给定的n个互异的输入元素,任何确定或随机的比较排序算法,其概率运行时间都有下界Ω(nlgn)。首先分析一个确定的比较排序算法A,其决策树为Ta,假设A的输入的每一种排列情况都是等可能的。

a) 假设Ta的每个叶子结点都标有在给定的随机输入情况下到达该结点的概率。证明:恰有n!个叶子结点标有1/n!,其他的叶结点标记为0.

因为对于n个元素有n!种可能数组元素排列,那么由此对应于决策树的n!个叶子结点,对于n!个叶子结点中的每一个叶子结点对应一种排序情况,因为假设每一种排列情况都是等可能的,所以到达每一个叶子结点的概率1/n!,对于决策树来说,我们只考虑这n!个叶子结点。其他叶子结点不属于这n!种排序情况,所以随机输入排序情况到达该结点的概率是0.

b)定义D(T)表示一颗决策树T的外部路径长度,即D(T)是T的所有叶结点深度的和,假设T为一颗有k>1个叶结点的决策树,LT和RT分别是T的左子树和右子树。证明:D(T)=D(LT)+D(RT)+k.

c)定义d(k)为所有具有k>1叶结点的决策树T的最小D(T)值。证明:d(k)=min{d(i)+d(k-i)+k}.


d)证明:d对于给定的k(k>1)和i(1<i<k-1),函数ilgi+(k-i)lg(k-i)在i=k/2处取得最小值,并有结论d(k)=Ω(klgk).



e)证明:D(Ta)=Ωm(n!lgn!),并得出在平均情况下,排序n个元素的时间代价Ω(nlgn)


f) 不太懂。


8-2 (线性时间原址排序) 假设有一个包含n个待排序数据记录的数组,且每条记录的关键字的值为0或1,对这样一组记录进行排序的算法可能具备如下三种特性中的一部分。

1,算法的时间代价是O(n).

2,算法是稳定的。

3,算法是原址排序,除了输入数组之外,算法只需要固定的额外存储空间。

a,给出满足1和2的算法

计数排序

b,给出满足1和3的算法

既然n个数只有0和1两种值,那么可以按照我设计的算法,满足线性时间,不需要辅助空间,但是不稳定。

#include <iostream>
#include <time.h>
using namespace std;
void _8_2_b(int A[],int n)
{
   int k=0;
   for (int i=0;i<n;i++)
   {
      if (A[i]==0)
      {
          k++;
      }
   }
   for (int j=0;j<n;j++)
   {
       if (j<=k)
       {
           A[j]=0;
       }
       else 
       {
           A[j]=1;
       }
    }
}
void main()
{
    const n=100;
    int A[n]={0};
    srand( (unsigned)time( NULL ) );
    for (int i=0;i<n;i++)
    {
        A[i]=rand()%2;
    }
    _8_2_b(A,n);
    for ( i=0;i<n;i++)
    {
        cout<<A[i]<<" ";
    }
}


c,给出满足2和3的算法

插入排序

d 你设计的算法a-c中的任一个是否可以用于RADIX-SORT的第2行作为基础排序方法,从而使RADIX-SORT在排序有b位关键字的n条记录时的时间代价是O(bn)?如果可以,请解释应如何处理,如果不行,请说明原因。

(a)可以。用计数排序作为基数排序的子程序即可。
(b)不可以。我设计的这个程序,只是在特定情况下可以排序,不具备普遍性。
(c)不可以。插入排序属于比较排序算法,所以其时间下界是Ω(nlgn)。没有达到O(bn).

e.假设有n条记录,其中所有关键字的值都在1到k的区间内,你应该如何修改计数排序,使得它可以在O(n+k)时间内完成对n条记录的原址排序。除输入数组外,你可以O(k)使用大小的额外存储空间。你给出的算法是稳定的吗?

不稳定。以下是具体算法:

//此算法也是对计数排序的一种改进,这里有以下3点改进。
//1.只需要计算等于A[i]的元素,不用添加循环用来计算小于A[i]的元素
//2.同时也不用添加辅助数组B来对数组A进行输出,只需要在原来的A数组上进行排序就可以了。
//3.对于含有重复数据的数组进行排序时,用于存放数据出现次数的数组C的长度是刨去重复数据的最小值k,但是对于重复数据的处理是不稳定的。
//但是我还在思考这个排序是否是原址的计数排序?懂的请留言和我交流下哦,谢谢!
#include <iostream>
#include <time.h>
using namespace std;
const n=20;
void COUNTING_SORT(int A[n])
{
    int max=A[0],min=A[0];
    for (int i=0;i<n;i++)
    {
        if (A[i]>max)
        {
            max=A[i];
        }
        if (A[i]<min)
        {
            min=A[i];
        }
    }
    int k=max-min+1;   
    int *C=new int[k+1];
    for ( i=0;i<=k;i++)
    {
        C[i]=0;
    }
    for (int j=0;j<n;j++)
    {
        C[A[j]-min+1]++;
    }
    for (j=n-1;j>=0;)
    {
        k=max-min+1;
        if(C[k]!=0)
        {
          A[j]=max;
          C[k]--;j--;
        }
        else 
        {
            max--;
        }
    }
}
void main()
{
    int A[n]={0};
    srand( (unsigned)time( NULL ) );
    for (int i=0;i<n;i++)
    {
        A[i]=rand()%100;
    }
    COUNTING_SORT(A);
    for (int j=0;j<n;j++)
    {
        cout<<A[j]<<" ";
    }   
}

8-3 (变长数据项的排序)

a.给定一个整数数组,其中不同的整数所包含的的数字的位数可能不同,但该数组中,所有整数中包含的总数字位数为n.设计一个算法,使其可以在O(n)时间内对该数组进行排序。


                
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值