[练习3.7] 编写一个函数将两个多项式相乘,用一个链表实现.你必须保证输出的多项式按幂次排列,并且任意幂次最多只有一项. a.给出以O(M2N2)时间求解该问题的算法. b.写一个以O(M2N)时间执行乘法的程序,其中M≤N. c.写一个以O(MNlog(MN))时间执行乘法的程序. d.上面哪个时间界最好? Answer: [a].将两链表元素两两相乘并列出,从第一项开始,依次与其后的所有项比较,如相等则合并. 合并完成后,每次找出幂次最小的项,插入链表.(最原始的方法) [b].M≤1时,…
第03章 AOP前奏 提出问题 ●情景:数学计算器 ●要求 ①执行加减乘除运算 ②日志:在程序执行期间追踪正在发生的活动 ③验证:希望计算器只能处理正数的运算 ●常规实现 ●问题 ○代码混乱:越来越多的非业务需求(日志和验证等)加入后,原有的业务方法急剧膨胀.每个方法在处理核心逻辑的同时还必须兼顾其他多个关注点. ○代码分散: 以日志需求为例,只是为了满足这个单一需求,就不得不在多个模块(方法)里多次重复相同的日志代码.如果日志需求发生变化,必须修改所有模块. 动态代理 代理设计模式的原理:使用…
第03章_基本的SELECT语句 1. SQL概述 1.1 SQL背景知识 1946 年,世界上第一台电脑诞生,如今,借由这台电脑发展起来的互联网已经自成江湖.在这几十年里,无数的技术.产业在这片江湖里沉浮,有的方兴未艾,有的已经几幕兴衰.但在这片浩荡的波动里,有一门技术从未消失,甚至"老当益壮",那就是 SQL. 45 年前,也就是 1974 年,IBM 研究员发布了一篇揭开数据库技术的论文<SEQUEL:一门结构化的英语查询语言>,直到今天这门结构化的查询语言并没有太大…
文章目录 1.3.部署flannel网络 1.3.0.下载flannel二进制文件 1.3.1.创建flannel证书和私钥 1.3.2.生成flannel证书和私钥 1.3.3.将pod网段写入etcd 1.3.4.配置flannel为systemctl管理 1.3.5.分发flannel证书和启动文件到所有节点 1.3.6.配置并启动flannel服务 1.3.7.查看已分配的pod网段列表 1.3.8.查看各节点是否都存在flannel网卡 suse 12 二进制部署 Kubernetes…
[练习3.8] 编写一个程序,输入一个多项式F(X),计算出(F(X))P.你程序的时间复杂度是多少? Answer: (特例:P==0时,返回1.) 如果P是偶数,那么就递归计算((F(X))P/2)*((F(X))P/2), 如果P是基数,那么就递归计算((F(X))P/2)*((F(X))P/2)*F(X). 直到P==1时,直接返回F(X)结束递归. 时间复杂度计算为O(N)=2O((N/2)log(N/2))+O(1) 则时间复杂度O(logN) 因为一开始Poly的系数那里用的是in…
[练习3.6] 编写将两个多项式相加的函数.不要毁坏输入数据.用一个链表实现. 如果这两个多项式分别有M项和N项,那么你程序的时间复杂度是多少? 两个按幂次升序的多项式链表,分别维护一个指针. 幂较小者将元素的副本拷贝入节点并加入新链表,指针向后移动. 幂同样大时,将两者的系数相加后的结果加入新链表,两个多项式链表的指针共同向前移动. 其中一个多项式到达尾部时,如另一个未到达尾部,则一边后移一边将相同元素的新节点加入新链表. 时间复杂度O(M+N). 测试代码如下: #include <iost…
[练习3.4] 给定两个已排序的表L1和L2,只使用基本的表操作编写计算L1∩L2的过程. [练习3.5] 给定两个已排序的表L1和L2,只使用基本的表操作编写计算L1∪L2的过程. 思路比较简单,测试代码如下,两道题比较相似,测试代码就放一起了. #include <iostream> #include "linklist.h" using namespace std; using namespace linklist; template class List<in…
[练习3.16] 假设我们有一个基于数组的表A[0,1...N-1],并且我们想删除所有相同的元素. LastPosition初始值为N-1,但应该随着相同元素被删除而变得越来越小. 考虑图3-61中的伪代码程序段.过程Delete删除位置j上的元素并使表破坏. a.解释该过程是如何工作的 b.利用一般的表操作重写这个过程 c.如果用标准的数组实现,则这个过程的运行时间是多少? d.使用链表实现的时间是多少? e.给出一个算法以O(NlogN)时间解决问题 f.证明:如果只使用比较,那么解决该问…
基本上每章到增补附注这里就算是结束了. 根据设想,每章的这一篇基本上会注明这一章哪些题没有做,原因是什么,如果以后打算做了也会在这里补充. 还有就是最后会把有此前诸多习题的代码和原数据结构放整理后,以单个数据结构为单位放在一个文档里面. [未做习题] 习题3.1:编写打印出一个单链表的所有元素的程序. //这题例程里就有了,没必要单独开. 习题3.10:………………(题目太长懒得打,约瑟夫环问题). //这里应该是做循环链表,但是约瑟夫环本身可以用数学方法优化用循环链表做效率还挺低的,于是放弃.…
[练习3.25] 编写实现队列的例程,使用 a.链表 b.数组 Answer: 在这章一开头就已经写了个链表的队列例程了,所以实际上只要做b小题就可以. 数组模拟队列和链表的两点小不同是: ①.数组空间有限,入队需要检测数组是否已经满 ②.数组经过几次操作后,rear可能绕回front前面,所以许多操作都要用模来实现. 测试代码: #include <iostream> #include "queue.h" using namespace std; using namesp…
[练习3.26] 双端队列(deque)是由一些项的表组成的数据结构,对该数据结构可以进行下列操作: Push(X,D):将项X插入到双端队列D的前端. Pop(D):从双端队列D中删除前端项并返回. Inject(X,D):将项X插入到双端队列D的尾端. Eject(D):从双端队列D中删除尾端项并返回. 编写支持双端队列的例程,每种操作均花费O(1)时间. Answer: 相当简单的题目,把改一改双向链表就可以了. 测试代码: #include <iostream> #include &q…
[练习3.22] a.提出支持栈的Push和Pop操作以及第三种操作FindMin的数据结构,其中FindMin 返回该数据结构的最小元素,所有操作在最坏情况下的运行时间都是O(1). b.证明,如果我们加入第四种操作DeleteMin,那么至少有一种操作必须花费Ω(logN)时间. [练习3.23] 说明如何用一个数组实现三个栈. [练习3.24] 在2.4节中用于计算斐波那契的递归例程如果在N=50下运行,栈空间有可能用完吗,为什么? Answer: [练习3.22] a.最简单的想法就是再…
[练习3.21] 编写仅用一个数组而实现两个栈的例程.除非数组的每一个单元都被使用,否则栈例程不能有溢出声明. Answer: 很简单,一个栈从数组头起,一个栈从数组尾起,分别保留左右栈头索引. 如left=5则表示array[0]~array[4]为左栈元素,right=7则表示array[8]~array[size-1]为右栈元素. 当左右索引交叉时(left=right+1),0~left-1为左栈,left~size-1为右栈,刚好用完每一个单元. 测试代码: #include <ios…
[练习3.20] a.编写一个程序将中缀表达式转换为后缀表达式,该中缀表达式含括号及四则运算. b.把幂操作符添加到你的指令系统中去. c.编写一个程序将后缀表达式转化为中缀表达式. Answer: 花了好大力气把a,b就放一起写好了,终于知道为啥说编译原理难了,就这么简单的句法分析也好坑爹. c真的不打算写了,如果以后要学编译原理的话再继续吧. (一).首先是核心思路,还是比较清晰的. ①.对于左结合运算符的出入栈,规则很简单: 如果栈顶运算符为左结合的,那么有同级别或低级别优先级运算符即将入…
[练习3.19] 编写一个程序计算后缀表达式的值. Answer: 计算的方法书上说得很明白了,看代码行,没写错误检测[因为懒]. 测试代码: #include <iostream> #include "stack.h" using namespace std; using namespace stack; template class Stack<int>; int main(void) { calexp item[] = { (4.99), (1.06),…
[练习3.18]用下列语言编写检测平衡符号的程序 a.Pascal ( begin/end, ( ), [ ], { } ). b.C语言( /* */, ( ), [ ], { }). c.解释如何打印出错信息 Answer: a和b本质是一样的,就写了b小题即C语言的检测. 基本思想就是用栈,除了注释符号有一点点麻烦要查看连续两个字符,其它的几组都是很轻松愉快. 具体的细节都放到注释里了,所以在文章上没必要说太多. 这题测试代码就不放了,基本就是自己拿个文本文件改来改去,在main函数里面就…
[练习3.17] 不同于我们已经给出的删除方法,另一种是使用懒惰删除的方法. 为了删除一个元素,我们只标记上该元素被删除的信息(使用一个附加的位域). 表中被删除和非被删除的元素个数作为数据结构的一部分被保留. 如果被删除元素和非被删除元素一样多,我们就遍历整个表,对所有被标记的节点执行标准的删除算法. a.列出懒惰删除的优点和缺点. b.编写实现使用懒惰删除的标准链表操作的例程. Answer: a:优点——思想简单粗暴易于理解,误删可有恢复空间 缺点——需要额外的域且节点不及时释放,需要更多…
[练习3.15] a.写出自调整表的数组实现.自调整表如同一个规则的表,但是所有的插入都在表头进行. 当一个元素被Find访问时,它就被移到表头而并不改变其余的项的相对顺序. b.写出自调整表的链表实现 c.设每个元素都有其被访问的固定概率pi.证明那些具有最高访问概率的元素都靠近表头. Answer: a简单得令人发指,所以不写了. b只需要在原链表上加一个自适应的Find访问版本find_selfadj就行,很简单,如下代码. c在摊还分析那里会频繁遇到的,这儿超纲了. 测试代码: #inc…
[练习3.13] 利用社会安全号码对学生记录构成的数组排序.编写一个程序进行这件工作,使用具有1000个桶的基数排序并且分三趟进行. Answer: 首先,对社会安全号码不了解的就把它当成一个不超过9位的正整数就好了. 于是题目就是,通过1000个桶,对9位正整数进行桶排序. 因为一次最多比较三位(1000桶),刚好分三趟进行,加上最后复制回数组的一次,共遍历数组长度四次,时间复杂度O(N) 测试代码: #include <iostream> #include "linklist.h…
[练习3.12] a.编写一个非递归过程以O(N)时间反转单链表. b.使用常数附加空间编写一个过程以O(N)时间反转单链表. Answer: 这题的b貌似没啥意义,在a小题里直接用头插法,不断地将头节点后移, 并将当前头节点所在的节点的后继指针指回前驱就能倒置链表了,不需要额外的空间. 所以就写了a. 测试代码: #include <iostream> #include "linklist.h" using namespace std; using namespace l…
[练习3.11] 编写查找一个单链表特定元素的程序.分别用递归和非递归实现,并比较它们的运行时间. 链表必须达到多大才能使得使用递归的程序崩溃? Answer: 实现都是比较容易的,但是实际上查找链表元素本身也没必要使用递归的方法. 考虑到题目让人比较运行时间与程序崩溃的边界,可以认为这是警示大家不要滥用递归的题目[[ 毕竟在算法本身足够简单的时候,递归压栈会浪费大量额外空间与时间. 个人设备实测下,链表长度约5000时递归查找即崩溃,而迭代可在1000000长度的链表下正确运行. 测试代码如下…
[练习3.9] 编写任意精度的整数运算包,要求使用类似多项式运算的方法.计算24000内数字0到9的分布.…
主要是,感觉原来的链表例程通过Node的分配形成了链表,但是没有自动消除Node的办法比较危险,一旦在clear()之前把链表赋了其它值就内存泄漏了. 所以改了析构函数,自动清理分配出来的内存.既然改了析构同时就要改拷贝合成与拷贝赋值. 然后还给链表加了个尾指针,否则每次插入都要O(N)的时间真的很蛋疼……改了以后就是O(1)了 栈.队列.双链表的到时候再改. 添加的构造函数.赋值函数.析构函数如下: //构造函数,这部分直接增加在链表内部 public: //拷贝构造函数,深拷贝 List<T…
[练习3.3] 通过之调整指针(而不是数据)来交换两个相邻的元素,使用 a.单链表 b.双链表 Answer: 先放测试代码,折叠标题可以看到分别是哪种链表的测试. 实测可满足题意,但单链表和双链表的两段代码是分开实现的,所以需要分开测试. 如果要合在一起的话,需要改一下头文件包含以及命名空间. 单链表测试代码: #include <iostream> #include "linklist.cpp" using namespace std; using namespace…
[练习3.2] 给你一个链表L和另一个链表P,它们包含以升序排列的整数.操作printlots(L,P)将打印L中那些由P所指定的位置上的元素. 例如,如果p=1,3,4,6,那么,L的第一.第三.第四和第六个元素被打印出来. 你应该只使用基本的表操作,该过程的运行时间是多少? Answer: 老样子,先放折叠的实测代码. #include <iostream> #include <string> #include "linklist.h" using name…
双链表因为多了个前向指针,需要考虑的特殊因素多了一倍 所以中间插入(这儿没写)和中间删除会比较复杂. 其它倒没什么特别的,代码如下. 测试代码 #include <iostream> #include "double_linklist.h" using namespace std; using namespace doublelinklist; template class DList<int>; int main(void) { DList<int>…
写栈比队列更简单一些,毕竟只有一个数据出入口. 之前用C在程序里模拟栈代替递归的时候,直接搞个数组来实现都是非常轻松愉快的事情. 不多说,放代码. 测试代码 #include <iostream> #include "stack.h" using namespace std; using namespace stack; template class Stack<int>; int main(void) { Stack<int> number; //…
前几个例程还是相当简单的,把链表即时改了一下就是队列了. 还有想了一下,决定这种例程的代码放法是:先把测试代码默认折叠放在前面,然后把实现代码默认展开放在后面. 测试代码如下: #include <iostream> #include "queue.h" using namespace std; using namespace queue; template class Queue<int>; int main(void) { Queue<int>…
这种基础例程,如之前所提,会有一个实现和一个简单的测试代码. 链表其实没什么可说的,其实包括后面的栈和队列也没什么可说的,直接放代码吧. 下面这个是测试代码 #include <iostream> #include "linklist.h" using namespace std; using namespace linklist; template class List<int>; int main(void) { List<int> number…
[译者:这个系列教程是以Kitware公司出版的<VTK User's Guide -11th edition>一书作的中文翻译(出版时间2010年,ISBN: 978-1-930934-23-8),因为时间关系,我们不能保证每周都能更新本书内容,但尽量做到一周更新一篇到两篇内容.敬请期待^_^.欢迎转载,另请转载时注明本文出处,谢谢合作! 同一时候,因为译者水平有限,出错之处在所难免,欢迎指出订正! ] [本节相应原书中的第19页至第25页] 本章旨在介绍VTK系统的整体概述,并解说运用C+…