导航

算法导论第三版第二章思考题答案

Posted on 2013-03-06 17:13  蝈蝈俊  阅读(4606)  评论(0编辑  收藏  举报

2-1 (在归并排序中对小数组采用插入排序) 

虽然归并排序的最坏情况运行时间为Θ(nlgn),而插入排序的最坏情况运行时间为Θ(n2),但是插入排序中的常量因子可能使得它在n较小时,在许多机器上实际运行得更快。因此,在归并排序中当子问题变得足够小时,采用插入排序来使递归的叶变粗是有意义的。考虑对归并排序的一种修改,
39其中使用插入排序来排序长度为k的n/k个子表,然后使用标准的合并机制来合并这些子表,这里k是一个待定的值。

a.证明:插入排序最坏情况可以在Θ(nk)时间内排序每个长度为k的n/k个子表。
b.表明在最坏情况下如何在Θ(nlg(n/k))时间内合并这些子表。
c.假定修改后的算法的最坏情况运行时间为Θ(nk+nlg(n/k)),要使修改后的算法与标准的归并排序具有相同的运行时间,作为n的一个函数,借助Θ记号,k的最大值是什么?
d.在实践中,我们应该如何选择k?

******************************************************

1)每一个大小为k的子序列最坏情况可以在O(k^2)内完成排序,则n/k个子序列可以在n/k * O(k^2) =  Θ(k^2*n/k) = O(nk)时间内完成排序。

2)  该分治算法一共要分的层数为lg(n/k)次,而每一层,合并算法的时间复杂度为Θ(n),所以总个的时间复杂度为Θ(nlg(n/k))

3) Θ(n*k+n*lg(n/k)) = Θ(n*lgn)

=>Θ(k+lg(n/k)) = Θ(lgn)

所以 k < lgn ,  k 的最大值应该是 lgn.

4)、实践中k应该尽量选择为插入排序比合并排序快的最大的列表长度。

伪代码:


/**
*参数:数组a, 起始位置,结束位置。
**/
void mergeSort(int a[], int p, int r)
{
        if (r-p <= 6) { //这里的r-p +1 < = 7, 即r-p<= 6, k值为7。
              return insertSort(a, p, r);
       } else {
              int q = (p + r)/2;
              mergeSort(a, p, q);
              mergeSort(a, q+1, r);
              merge(a, p, q, r);
       }
}

/**插入排序**/
void insertSort(int a[], int p, int r)
{
       int i, j, key;
       for (j = p+1; j <= r; j++) {
              key = a[j];
              i = j - 1;
              while (i>=p && a[i]>key) {
                     a[i+1] = a[i];
                     i--;
              }
              a[i+1] = key;
       }
}

//下面是插入排序的变形。
void insertsort(int a[], int p, int r){
       int i, j;
       for (i=p; i<r; i++)
              for (j=i+1; j>p && a[j-1]>a[j]; j--)
                     swap(a, j, j-1); //交换数组a中的j和j-1位置处的值。
}

 

 

============================================================================================================

2-2:冒泡排序算法的正确性

冒泡排序(bubblesort)算法是一种流行的排序算法,它重复地交换相邻两个反序元素。

BUBBLESORT(A)

1       for i=1 to length[A] -1
2               for j=length[A] downto i+1
3                       if A[j]< A[j-1]
4                                exchange A[j]←→ A[j-1]

a) 设A’表示BULLESORT(A)的输出,为了证明BUBBLESORT是正确的,需要证明它能够终止,并且有: A’[1]<=A[2]<=..<=A’[n]
其中n=length[A]。为了证明BUBBLESORT的确能实现排序的效果,还需要证明什么?
下面两个部分将证明不等式(2.3)。

b) 对第2~4行中的for循环,给出一个准确的循环不变式,并证明该循环不变式是成立的。在证明中采用本章中给出的循环不变式证明结构。

c) 利用在b)部分证明的循环不变式的终止条件,为第1~4行中的for循环给出一个循环不变式,它可以用来证明不等式(2.3)。你的证明因采用本章中给出的循环不变式的证明结构。

d) 冒泡排序算法的最坏情况运行时间是什么?比较它与插入排序的运行时间。

******************************************************

http://amazingidiot.iteye.com/blog/1127800

http://ufownl.blog.163.com/blog/static/1250122200832410828987/

http://blog.sina.com.cn/s/blog_769a9def0100tx9b.html

a). A’中的元素全部来自于A中变换后的元素。

b)、c) 、 答案看 http://www.cnblogs.com/ghj1976/archive/2013/03/06/2946078.html 最后一个例子的分析

d)、最坏情况为所有数据都是从大到小排序的,这时候时间花费为Θ(n^2)。最好情况是已经排好序的,仍然是Θ(n^2),因为仍然需要双重循环。

但是在最佳情况下,冒泡排序比插入排序略长。 

 

 

============================================================================================================

2-3:霍纳规则的正确性

NewImage

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

http://blog.csdn.net/cppgp/article/details/7161701

 

 公式的简单推理:

NewImage

 

a0+a1*x+a2*x^2+a3*x^3+a4*x^4+…+ak*x^k+…+an*x^n

 

NewImage

 

 

计算机的循环计算。

1      y = 0                                      时间花费  1

2      for i=n down to 0                                   n+1

3              y = ai + x*y                                     n

                                                                        总时间花费  2n+2

这样循环计算出来的y就是上面汇总的值。

 

a)、Θ(n), 推理过程看上面。

b)、伪代码实现的朴素的多项式求值算法。

NewImage








下面是一个取巧的算法,时间消耗是 3n, 在n >2 时 时间消耗大于 2n+2

void Ploynomial()                                  时间消耗 = 3n
{
        int t;                                                      1
        sum = a[0];                                          1
        for (i = 1; i < n; i++)                            n
        {
                sum += a[i]*x;                             n-1
                x = x*x;                                         n-1
        }
}

c)、

初始化: 有 y = 0, i = n , 这样 计算 下面公式的右边 为 0 , 所以初试化满足循环不变式。 

NewImage

 

 

          

保持:假设当第i=j满足时,考察i=j-1。

终止: 当循环结束时候,有 i= -1,

 

------------

由于0从0到n-(i+1),因此有:
y = Σ ak+i+1 * x^k
  = ak+i+1 + ak+i+2 * x + ... + an * x^(n-(i+1))
霍纳规则代码段循环不变式证明如下:
初始:
    i=n,y[n] = 0,迭代开始时,循环后有y[n] = a[n]。
保持:
    对于任意 0 ≤ i ≤ n,循环后有:
        y[i] = a[i] + y[i+1] * x = a[i] + (a[i+1] * x + a[i+2] * x + ... + a[n] * x^(n-(i+1))) * x
             = a[i] + a[i+1] * x + a[i+2] * x^2 + ... + a[n] * x^(n-i)
终止:
    i小于0时终止,此时有 y[0] = a[0] + a[1] * x + a[2] * x^2 + a[n] * x^n

证明和y = Σ a[k+i+1] * x^k的关系:
    k 从0到n-(i+1),等价于 0 ≤ k ≤ n-(i+1)。因此
        y = Σ a[k+i+1] * x^k
            = a[i+1] + a[i+2] * x + ... + a[n-(i+1)+i+1] * x^(n-i)
            = a[i+1] + a[i+2] * x + ... + a[n] * x^(n-i)
    由于i+1循环之后和i循环之前的值相等,用y'[i]表示i循环之前的值,则有:
        y'[i] = y[i+1]
    霍纳规则循环不变式的结果表明:
        y[i] = a[i] + a[i+1] * x + a[i+2] * x^2 + ... + a[n] * x^(n-i)
    因此有:
        y'[i] = y[i+1] = a[i+1] + a[i+2] * x + ... + a[n] * x^(n-(i+1))
    令k=n-(i+1),则n=k+i+1,所以:
        y'[i] = a[i+1] + a[i+2] * x + ... + a[k+i+1] * x^(k+i+1-(i+1))
                = a[i+1] + a[i+2] * x + ... + a[k+i+1] * x^k
    用y表示y'[i],则有:
        y = a[i+1] + a[i+2] * x + ... + a[k+i+1] * x^k
            = Σ a[k+i+1] * x^k
    其中 k从0到n-(i+1)
    证毕。


 

 

============================================================================================================

2.4 逆序对
设A[1..n]是一个包含n个不同数的数组。如果i<j且A[i]>A[j],则(i,j)就称为A中的一个逆序对(inversion)。
a)列出数组〈2,3,8,6,1〉的5个逆序。
b)如果数组的元素取自集合{1, 2, ..., n},那么,怎样的数组含有最多的逆序对?它包含多少个逆序对?
c)插入排序的运行时间与输入数组中逆序对的数量之间有怎样的关系?说明你的理由。
d)给出一个算法,它能用Θ(nlgn)的最坏情况运行时间,确定n个元素的任何排列中逆序对的数目。(提示:修改合并排序)

a)  (2,1)  (3,1) (8,1) (6,1),(8,6)

b) 数组从大到小有序排列时,逆序对最多,为n(n-1)/2个。

c)

逆序对增加时,插入排序时间增加。
没有逆序对时,插入排序时间最少,为Θ(n)。
逆序对最多时,插入排序时间最多,为Θ(n^2)。

d)  归并算法, 每次移动牌,次数加1, 合计的次数就是逆序对的个数。

NewImage

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

在归并排序合并步骤时,每移动一个右边的数,查看他左边数组还剩多少数,然后将其总数相加,就可以得到逆序对的数目了。

http://www.cnblogs.com/liao-xiao-chao/articles/2351925.html


 

============================================================================================================

 

 

 

参考资料:

http://qiemengdao.iteye.com/blog/1328678

http://www.cnblogs.com/sinoxavier/archive/2012/11/23/2785082.html

http://www.cnblogs.com/liao-xiao-chao/articles/2351925.html

http://fongfc.files.wordpress.com/2009/10/alg_sol_ch_2.pdf