代码改变世界

算法导论第二章 习题作业记录

2013-01-12 17:40  撞破南墙  阅读(760)  评论(0编辑  收藏  举报

 

 

本系列使用CLRS算法导论第二版。

 讨论QQ群181539446 加群请写明来自博客园

 

2.1算法入门

1. Exercises 2.1-1

给出A=<31,41,59,26,41,58>插入排序的实际执行过程

31,41,59,26,41,58

1 31

2 31,41

3 31,41,59

4 26,31,41,59,

5 26,31,41,58,59

2.Exercises 2.1-2

改成降序

INSERTION-SORT-DESC(A)

31,41,59,26,41,58

1 for j ← 2 to length[A] //从第2个开始往后遍历

2  do key ← A[j] //Aj 待插入的元素

3  ▹ Insert A[j] into the sorted sequence A[1 j - 1].

4 i ← j - 1

5  while i > 0 and A[i] < key

6  do A[i + 1] ← A[i]

7  i ← i - 1

8  A[i + 1] ← key

Exercises 2.1-3

Consider the searching problem:

• Input: A sequence of n numbers A = a1, a2, . . . , an and a value v.

• Output: An index i such that v = A[i] or the special value NIL if v does not appear in

A.

Write pseudocode for linear search, which scans through the sequence, looking for v. Using a

loop invariant, prove that your algorithm is correct. Make sure that your loop invariant fulfills

the three necessary properties.’

For (i=0 to length[A])

{

If( A[i]==v )

Return i

}

Return nil;

Exercises 2.1-4

Consider the problem of adding two n-bit binary integers, stored in two n-element arrays A

and B. The sum of the two integers should be stored in binary form in an (n + 1)-element

array C. State the problem formally and write pseudocode for adding the two integers.

1 形式化描述:

画表格

2 伪代码

Int j=0;  //表示进位

For i to n{

If (A[i]+B[i]+j>=2){

C[i]=A[i]+B[i]+j-2;

J=1;

}Else{

J=0;

C[i]=A[i]+B[i]+j;

}

}

C[n+1]=j;

官方答案

wps_clip_image-4209

2.2算法分析

1.

N^3

2.选择排序

void SelectionSort(int A[],int length){

int index=0;

int temp=0;

int i,j;

for ( j=0;j<length-1;j++){//外层遍历           n

index=j;

for (i=j+1;i<length;i++){//内层逐个比较找出最小者的下标       n(n-1)

if(A[i]<A[index]){      //如果某项比该项小                n(n-1)*(1)

                 index=i;      //则将某项与其他项比                   n(n-1)*(1)

            }

        }

//交换第index个和第j个

        temp=A[j];A[j]=A[index];A[index]=temp;

    }

for ( j=0;j<length;j++){//测试

     printf(" %d ",A[j]);

    }

}

3.

平均情况为n/2 最坏情况为n。

4.

检查输入是否符合特定的匹配条件,然后直接给出预先计算的答案。

如 2^16 =655536

2.3算法设计

1.合并排序的过程

3, 41,52, 26, 38, 57, 9, 49

3, 41,52, 26, 38, 57, 9, 49

3, 41,26, 52, 38, 57, 9, 49

3, 26,41, 52,  9,38, 49, 57

3, 9,26,38, 41, 49, 52,57

2.改写merge_sort

//=================================

///A[...p..q,q+1...r...]

#define  N1 3

#define  N2 3

// ---------------------------------------------------------------------------------------------------------

// Description: Merge_sort(2.3-2)

// Input:

// Output:

// Return:

// Exception:

// ---------------------------------------------------------------------------------------------------------

void Merge_sort(int A[],int p,int q,int r){

// int n1=q-p+1;

// int n2=r-q;

int L[N1];

int R[N2];

int i,j=0;

//复制数组

for(i=0;i<N1;i++){

L[i]=A[p+i];

}

for(j=0;j<N2;j++){

R[j]=A[q+j+1];

}

i=0,j=0;

int end,n=0;

//依次取出L、R的头个元素比较并复制到A中

for(int k=p;k<r+1;k++){

if(L[i]<R[j]){

A[k]=L[i];i++;

}else{

A[k]=R[j];j++;

}

//判断是否达到边界

if(i==N1+1){

for(;j<N2;j++,k++){

A[k]=R[j];

}

break;

}else if(j==N2+1){

for(;i<N1;i++,k++){

A[k]=L[i];

}

break;

}

}

//测试

for ( int z=p ;z<r+1;z++){//外层遍历

     printf(" %d ",A[z]);

    }

}

3.略

wps_clip_image-13502

4.略

wps_clip_image-1631

5.二分查找,直接上THE C PROGRAM上的

注:我在重写的时候使用了

High=n+1;

Mid=(high+low+1)/2;

这样的话,无法退出,因为这里的+1将导致最后low<=high永远成立。

/* binsearch: find x in v[0] <= v[1] <= ... <= v[n-1] */

int binsearch(int x, int v[], int n)

{

int low, high, mid;

low = 0;

high = n - 1;

while (low <= high) {

mid = (low+high)/2;

if (x < v[mid])

high = mid - 1;//

else if (x > v[mid])

low = mid + 1;

else /* found match */

return mid;

}

return -1; /* no match */

}

6.

查找可以改成lgN,但移动仍然需要O(N)。

当然如果改成链式存储结构,就没有移动的问题。那么时间复杂度可以降低。

7

此题零零散散耗费了我一些时间,一开始我就想到了使用nlgn 的排序排好,但是一直没想到合适的比较方法。

最开始我想通过排除一些情况,如将数组分成两半,其中后半部分为>x的数,但是这样仍然不能解决问题(N任选2),而且可能出现负数。

也许是在做此题前,刚做了二分查找,也许是二分查找定位刚好是lgn的复杂度,再配合一次遍历耗时n,我想到了下面的方法,后来发现官方答案也是如此。

1使用归并排序

2 遍历i to n,定位另一个数使用二分查找。

wps_clip_image-24847

思考题

1.

1)因为对于1个长为k的待排序的数组,其时间复杂度为o(k^2),因为有n/k个,相乘得nk

2)参考图2-5,每层共需要n个操作,共lg(n/k)层。相乘得nlg(n/k)

3)(未理解)

The modiÞed algorithm has the same asymptotic running time as standard

merge sort when (nk +n lg(n/k)) = (n lg n). The largest asymptotic value

of k as a function of n that satisÞes this condition is k = (lg n).

To see why, Þrst observe that k cannot be more than (lg n) (i.e., it can’t have

a higher-order term than lg n), for otherwise the left-hand expression wouldn’t

be (n lg n) (because it would have a higher-order term than n lg n). So all

we need to do is verify that k = (lg n) works, which we can do by plugging

k = lg n into (nk + n lg(n/k)) = (nk + n lg n − n lg k) to get

(n lg n + n lg n − n lg lg n) = (2n lg n − n lg lg n) ,

which, by taking just the high-order term and ignoring the constant coefÞcient,

equals (n lg n).

4)(未理解)

In practice, k should be the largest list length on which insertion sort is faster

than merge sort.

2.冒泡排序

wps_clip_image-178

官方答案为

wps_clip_image-30565

我的疑问是:在最坏情况下,二层循环后,还有2次操作,也就是说,最坏情况应该是n^2-n

3.霍纳规则 第三问没看明白。

4.

1) 2-3     2-8     2-6 3-8  3-6

2)逆序的最多 例如  5,4,3,2,1, 共 4+3+2+1即 n个中有(1+n-1)(n-1)/2=n(n-1)/2

3)逆序对的个数即 “额外”操作,实际执行次数=最好情况+逆序对个数。

4)将合并排序的改序步骤变为统计即可。