《数据结构与算法分析:C语言描述_原书第二版》CH2算法分析_课后习题_部分解答

对于一个初学者来说,作者的Solutions Manual把太多的细节留给了读者,这里尽自己的努力给出部分习题的详解:

不当之处,欢迎指正。

1、  按增长率排列下列函数:N,√2,N1.5,N2,NlogN, NloglogN,Nlog2N,Nlog(N2),2/N,2N,2N/2,37,N2logN,N3。指出哪些函数以相同的增长率增长。

   答:排列如下2/N < 37 < √2 < N < NloglogN < NlogN < Nlog(N2) < Nlog2N < N1.5 < N2 < N2logN < N3 < 2N/2 < 2N

   其中,NlogN 与 Nlog(N2) 的增长率相同,均为O(NlogN)。

   补充说明:a) 其中 Nlog2N 与 N1.5, N3 与 2N/2大小关系的判定,可以连续使用洛必达法则(N->∞时,两个函数比值的极限,等于它们分别求导后比值的极限)。当然,更简单的是两边直接求平方。

       b) 同时注意一个常用法则:对任意常数k,logkN = O(N)。这表明对数增长得非常缓慢。习题3中我们会证明它的一个更严格的形式。



2、  函数NlogN 与 N1+ε/√logN (ε>0) 哪个增长得更快?

   分析:我们首先考虑的可能是利用洛必达法则,但是对于第二个函数其上下两部分皆含有变量,难以求导(当然也不是不行,就是麻烦些,如果你愿意设y = N1+ε/√logN ,然后对两边取对数的话)。这里我们将利用反证法:

   要证NlogN < N1+ε/√logN ,即证 logN < Nε/√logN。既然用反证法,那么我们假设 Nε/√logN < logN。两边取对数有 ε/√logN logN < loglogN。即 ε√logN < loglogN。设t = logN,则 ε√t < logt <=> ε2t < log2t,这显然与连续1中b)矛盾,因此假设 Nε/√logN < logN 不成立。因此函数 N1+ε/√logN增长得更快。



3、  证明对任意常数k,logkN = o(N)。

   解:要证明命题成立,只需证limn->∞(logkN / N) = 0即可。证明如下:

   首先,如果k1 < k2,显然有 logk1N = o(logk2N) 。且k = 0时,logkn = 1。应用洛必达法则,limn->∞(logiN / N) = limn->∞(ilogi-1N / Nln2) = limn->∞(logi-1N / N) 。(说明:这里舍弃常数是因为我们假设函数最终的比值为0,否则不可简单的丢弃常数。当然如果比值不为零的话,我们需要返回到这里另行处理,其实证明过程也是不断尝试、调整的,此路不通,另行它法嘛:)就是说,通过不断地规约,最终极限的比值等于零,命题得证。



4、 求两个函数 f(N) 和 g(N),使得 f(N) ≠ O(g(N)) 且 g(N) ≠ O(f(N))。

   一个显然的例子是函数 f(N) = sinN,g(N) = cosN。



5、 假设需要生成前N个自然数的一个随机置换。例如,{4,3,1,5,2} 和 {3,1,4,2,5} 就是合法的置换,但 {5,4,1,2,1} 却不是,因为数1出现两次而数3却没有出现。这个程序常常用于模拟一些算法。我们假设存在一个随机数生成器 RandInt(i, j),它以相同的概率生成 i 和 j 之间的一个整数。下面是三个算法:

   1) 如下填入从 A[0] 到 A[N-1] 的数组 A:为了填入 A[i],生成随机数直到它不同于已经生成的 A[0],A[1],... ,A[i-1],再将其填入 A[i]。

   2) 同算法1),但是要保存一个附加的数组,称之为 Used(用过的)数组。当一个随机数 Ran 最初被放入数组 A 的时候,置 Used[Ran] = 1。这就是说,当用一个随机数填入 A[i] 时,可以用一步来测试是否该随机数已经被使用,而不是像的一个算法那样(可能)进行 i 步测试。

   3) 填写该数组使得 A[i] = i + 1。然后:

    for(i = 1; i < N; i++)
     Swap(&A[i], &A[RandInt(0, i)]);

   对每一个算法给出你能够得到的尽可能准确的期望的运行时间分析(用大O)。

   解:分析,对于1),容易写出如下算法:

 for(i = 0; i < N; i++){
      while(1){
	  A[i] = RandInt(1, N);
	  for(j = 0; j < i; j++)
		if(A[j] == A[i])
		  break;
	  if(j == i)
		break;
        }
 }

   调用一次随机数字生成函数与前面已经生成的随机数(存放在A数组中的)不同的概率为 (N-i) / N,那么理论上经过 N / (N-i) 次随机数的生成我们可以确定其与已生成的概率为 1。因此该算法的期望运行时间为

当然,也可以对分子放大的同时对分母缩小,不过这样求得的时间界限为O(N2),显然不如上面的做法精确。这里需要注意的一点是调和级数的前N项和,它是发散的,在计算机科学中的使用频率要远比在在数学等其它科目中使用得多。下面给出调和和:

其近似误差r = 0.5772156649,这个值称为欧拉常数(Euler’s constant)。

   对于2),容易写出如下算法: 

for(i = 0; i < N; i++){
	while(1){
		A[i] = RandInt(1, N);
		if(Used[i] == 0){
			Used[i] = 1;
			break;
		}
	}
}

   同1)的分析,其运行时间界限显然为O(NlogN)。

   对于3),运行时间为O(N),不消多说。



6、  记录一个称为Horner法则的算法,该算法用于计算 F(X) = Σi=0~nAiXi的值。

Poly = 0;
for(i = N; i >= 0; i--)
	Poly = X * Ploy + A[i];


7、  给出一个有效的算法来确定在整数 A1  < A2 < A3 < ... < AN 的数组中是否存在整数 i ,使得 Ai = i。你的算法的运行时间是多少?

    分析:类似二分查找,直接上代码:

int(int[] a, int N){
	int low = 0, high = N - 1; middle;

	while(low <= high){
		middle = ((high-low) >> 1) + low;

		if(a[middle]) < middle + 1)
			low = middle + 1;  // 搜索右空间
		else if(a[middle] > middle + 1)
			high = middle - 1; // 搜索做空间
		else
			return middle;
	}

	return -1;
}

    易知该算法的运行时间为O(logN)。



8、  如果7题中的语句 low = middle + 1 更该为 low = middle ,那么这个程序还能正确运行吗?

    答:不能,设 low = n,high = n + 1,则 middle = n,程序陷入死循环。



9、  a.编写一个程序来确定正整数N是否是素数,你的程序在最坏的情形下的运行时间是多少(用N表示)?(你应该能够写出O(√N)的算法程序)。

    b.令B等于N的二进制表示法中的位数。B的值是多少?

    c.你的程序在最坏情形下的运行时间是什么(用B表示)?

    d.比较确定一个20(二进制)位的数是否是素数和确定一个40(二进制)位的数是否是素数的运行时间。

    e.用 N 还是 B 来给出运行时间更合理,为什么?

    解:对于a,由于 √N * √N = N,因此分解 N 时必有一个整数小于 √N。高效的算法思路是:首先,测试N是否能被2整除,不能的话测试N是否能被3,5,7,...,√N整除。编码如下(是素数返回1,不是返回0):

int IsPrime(int N){
	int i;

	if(N == 1)
		return 0;
	if(N % 2 == 0)
		return 0;

	for(i = 3; i <= int(sqrt(w) + 0.5); i += 2)
		if(N % i == 0)
			return 0;

	return 1;
}

    对于b,显然有,B = O(logN)。

    对于c,由于B = O(logN),则2B = O(N),即2B/2 = O(√N),所以用B表示的最坏情况下的运行时间是:O(2B/2)

    对于d,后者的运行时间是前者运行时间的平方,由c中的解答易知。

    对于e,Wiss说:B is the better measure because it more accurately represents the size of the input.


All Rights Reserved.
Author:海峰:)
Copyright © xp_jiang.
转载请标明出处:http://www.cnblogs.com/xpjiang/p/4143743.html

参考资料:Data Structures and Algorithm Analysis in C(second edition) Solutions Manual_Mark Allen Weiss_Florida International University.

时间: 2024-11-10 13:08:53

《数据结构与算法分析:C语言描述_原书第二版》CH2算法分析_课后习题_部分解答的相关文章

《数据结构与算法分析:C语言描述_原书第二版》CH3表、栈和队列_reading notes

表.栈和队列是最简单和最基本的三种数据结构.基本上,每一个有意义的程序都将明晰地至少使用一种这样的数据结构,比如栈在程序中总是要间接地用到,不管你在程序中是否做了生命. 本章学习重点: 理解抽象数据类型(ADT)的概念 学习如何对表进行有效的操作 熟悉栈ADT及其在实现递归方面的应用 熟悉队列ADT及其在操作系统和算法设计中的应用 ADT 抽象数据类型(abstract data type)是一个操作的集合,是数学的抽象,在ADT中不涉及如何实现操作的集合,这可以看作是模块化设计的扩充. 对于每

《数据结构与算法分析—C语言描述》pdf

下载地址:网盘下载 内容简介 编辑 <数据结构与算法分析:C语言描述(原书第2版)>内容简介:书中详细介绍了当前流行的论题和新的变化,讨论了算法设计技巧,并在研究算法的性能.效率以及对运行时间分析的基础上考查了一些高级数据结构,从历史的角度和近年的进展对数据结构的活跃领域进行了简要的概括.由于<数据结构与算法分析:C语言描述(原书第2版)>选材新颖,方法实用,题例丰富,取舍得当.<数据结构与算法分析:C语言描述(原书第2版)>的目的是培养学生良好的程序设计技巧和熟练的算

数据结构与算法分析 c语言描述 pdf 高清下载

网盘下载:数据结构与算法分析 c语言描述 pdf 高清下载 – 易分享电子书PDF资源网 作者: [美] Mark Allen Weiss 出版社: 机械工业出版社 副标题: C语言描述 原作名: Data Structures and Algorithm Analysis in C:Second Edition 译者: 冯舜玺 出版年: 2004-1-1 页数: 391 定价: 35.00元 装帧: 平装 内容简介 · · · · · · 本书是<Data Structures and Alg

数据结构与问题求解-Java语言描述(第三版)

数据结构对程序的重要性不言而喻,用java语言来实现常见的一些数据结构,以及在相应数据结构上的操作对学习java的同学来说是必须掌握的. 本系列博文参考<数据结构与问题求解-Java语言描述(第三版)>来实现 在自己学习的过程中,更希望有机会与大家交流. PS :本人是菜鸟,只是用博客的方式激励自己.请轻喷.Fighting!

数据结构与算法分析_Java语言描述(第2版)pdf

下载地址:网盘下载 本书是国外数据结构与算法分析方面的经典教材,使用卓越的Java编程语言作为实现工具讨论了数据结构(组织大量数据的方法)和算法分析(对算法运行时间的估计). 随着计算机速度的不断增加和功能的日益强大,人们对有效编程和算法分析的要求也不断增长.本书将算法分析与最有效率的Java程序的开发有机地结合起来,深入分析每种算法,并细致讲解精心构造程序的方法,内容全面.缜密严格. 第3版的主要更新如下: ? 第4章包含AVL树删除算法的实现. ? 第5章进行了全面修订和扩充,现在包含两种较

数据结构与算法分析_Java语言描述(第2版)高清版pdf免费下载

下载地址:网盘下载 备用地址:网盘下载 内容简介编辑“数据结构”是计算机专业的基础与核心课程之一,Java是现今一种热门的语言.本书在编写过程中特别考虑到了面向对象程序设计(OOP)的思想与Java语言的特性.它不是从基于另一种程序设计语言的数据结构教材简单地“改编”而来的,因此在数据结构的实现上更加“地道”地运用了Java语言,并且自始至终强调以面向对象的方式来思考.分析和解决问题.本书是为数据结构入门课程(通常课号是CS-2)而编写的教材.作者Frank Carrano在编写过程自始至终特别

《数据结构与算法分析Java语言描述》PDF文件免费下载

图书简介: 本书是国外数据结构与算法分析方面的经典教材,使用卓越的Java编程语言作为实现工具讨论了数据结构(组织大量数据的方法)和算法分析(对算法运行时间的估计). 随着计算机速度的不断增加和功能的日益强大,人们对有效编程和算法分析的要求也不断增长.本书把算法分析与最有效率的Java程序的开发有机地结合起来,深入分析每种算法,内容全面.缜密严格,并细致讲解精心构造程序的方法. 图书目录部分截图: 结语:总结 数据结构与算法分析需要这份PDF文档的朋友,欢迎加Q群:219571750,免费领取,

《数据结构与算法分析 C语言描述》读书笔记——分治算法

书中用求解最大子序列和的方式介绍了分治算法(divide-and-conquer) 分治算法是一种相对快速的算法 运行时间为O(logN) 最大子序列和的问题如下: 给出一组整数 A1  A2 … AN 求∑jk=i Ak 若所有整数均为负 则最大子序列和为0 e.g. 输入-2, 11,-4, 13, -5, -2 输出20(A2到A4) 分治算法就如同字面描述的一样 先分再治 分 指的是将问题分为两部分几乎相同的子问题 进行递归求解 治 指的是将 分 的解通过简单的手段合并 得到最终解 对于

【数据结构与算法分析——C语言描述】练习1.1——选择问题

本部分内容来自http://www.cnblogs.com/mingc,笔者在此只用于整理学习. 问题描述:编写一个程序解决选择问题.令k=N/2.画出表格显示你的程序对于N为不同值时的运行时间. 理解:设有一组N个数确定其中第k个最大者,称选择问题(selection problem) 思路:读入前k个数到临时数组tmp(并按降序排列).然后逐个读取后续数字X,当X大于第k个数时,将其加入数组tmp(并按降序排列).最后返回位置k-1上的值 #include <stdio.h> #inclu