思考题2-1

a) 长度为 kk 的表所需时间 ak2+bk+cak^2+bk+c,其中 a,b,ca,b,c 是常数,对 nk\frac nk 个这样的表需要 nk⋅(ak2+bk+c)\frac nk⋅(ak^2+bk+c),即 Θ(nk)\Theta(nk)。

b) 如果把合并 2 个表拓展到一次合并所有的表则需要 Θ(n⋅nk)=Θ(n2k)\Theta(n⋅\frac nk)=\Theta(\frac {n^2}{k}) (每次从 nk\frac nk 个表中选择一个最小元素放入到最终表中,重复 nn 次)。
要达到 Θ(n⋅lgnk)\Theta(n⋅\lg {\frac nk}),我们两两合并,即每次合并两个表,然后把两个表合并的结果和另外两个表合并的结果再次两两合并,每一层合并需要 Θ(n)\Theta(n),一个有 lg(n/k)\lg(n/k) 高度,所以总时间就是 Θ(n⋅lg(n/k))\Theta(n⋅\lg(n/k))。

c) 当 k=Θ(lgn)k=\Theta(\lg n) 时,有 Θ(nk+n⋅lg(n/k))=Θ(nk+nlgn−nlgk)=Θ(2nlgn−nlglgn)=Θ(nlgn)\Theta(nk+n⋅\lg(n/k))=\Theta(nk+n\lg n−n\lg k)=\Theta(2n\lg n−n\lg \lg n)=\Theta(n\lg n)。

d) 只需计算出当插入排序击败归并排序时的最大 kk 值即可,选择此 kk 值就行。

#include <iostream>
using std::cin;
using std::cout;
using std::endl;const int treshold = 20;        //此阈值只做测试之用,不是实际k值void insertion_sort(int *array,int p,int r)
{for(int i = p + 1; i <= r; ++i){int key = *(array + i);int j = i - 1;while(j >= p && *(array + j) > key){*(array + j + 1) = *(array + j);--j;}*(array + j + 1) = key;}
}void merge(int *array,int p,int q,int r)
{int n1 = q - p + 1;int n2 = r - q;int *L = new int[n1];int *R = new int[n2];int i = 0, j = 0;for(int k = p; k <= q; ++k)*(L + i++) = *(array + k);for(int k = q + 1; k <= r; ++k)*(R + j++) = *(array + k);i = j = 0;for(int k = p; k <= r; ++k){if(i == n1)*(array + k) = *(R + j++);else if(j == n2)*(array + k) = *(L + i++);else if(*(L + i) <= *(R + j))*(array + k) = *(L + i++);else *(array + k) = *(R + j++);}delete []L;delete []R;
}void mixed_merge_sort(int *array,int p,int r)
{if(p < r){if(r - p > treshold){int q = (p + r) / 2;mixed_merge_sort(array,p,q);mixed_merge_sort(array,q+1,r);merge(array,p,q,r);}else insertion_sort(array,p,r);}
}int main()
{int *array;int len,key;cout << "input the length of array" << endl;cin >> len;array = new int[len];cout << "input " << len << " integers" << endl;for(int i = 0; i < len; ++i)cin >> *(array + i);mixed_merge_sort(array,0,len-1);cout << "after sort" << endl;for(int i = 0; i < len; ++i)cout << *(array + i) << ' ';cout << endl;delete []array;return 0;
}

思考题2-2

a) 我们需要证明 A′A' 是 AA 的一个排列,即 A'A′ 的元素全是 AA 中的元素。

b) 每次内部迭代开始时,A[j]=min{A[k]:j≤k≤n}A[j]=min\{A[k]:j≤k≤n\},并且显然 A[j…n]A[j…n] 是初始 A[j…n]A[j…n] 的一个排列。
初始化:j=n,A[j…n]j=n,A[j…n] 仅有一个元素 A[n]A[n],显然成立;
保持:根据循环不变式,A[j]A[j] 是 A[j…n]A[j…n] 的最小元素,若 A[j−1]>A[j]A[j−1]>A[j],则交换它们使得 A[j−1]A[j−1] 是 A[j−1…n]A[j−1…n] 的最小值,而且每次只是交换两个值,因此 A[j−1…n]A[j−1…n] 必然是 A[j−1…n]A[j−1…n] 的一个排列;
终止:当 j=ij=i 时循环终止,A[i]=min{A[k]:i≤k≤n}A[i]=min\{A[k]:i≤k≤n\},并且 A[i…n]A[i…n] 是初始 A[i…n]A[i…n] 的一个排列。

c) 每次迭代开始时,A[1…i−1]A[1…i−1] 包含初始 A[1…n]A[1…n] 最小的 i−1i−1 个元素,且 A[1]≤A[2]≤⋯≤A[i−1]A[1]≤A[2]≤⋯≤A[i−1]。
初始化:当 i=1i=1 时,A[1…i−1]A[1…i−1] 为空,循环成立;
保持:A[1…i−1]A[1…i−1] 包含初始 A[1…n]A[1…n] 最小的 i−1i−1 个元素,且 A[1]≤A[2]≤⋯≤A[i−1]A[1]≤A[2]≤⋯≤A[i−1]。内部循环使得 A[i]A[i] 是 A[i…n]A[i…n] 的最小元素,所以现在 A[1…i]A[1…i] 是初始 A[1…i]A[1…i] 元素的非递减排列;
终止:当 i=ni=n 时循环终止,A[1…i−1A[1…i−1] 即 A[1…n−1]A[1…n−1] 是初始 A[1…n−1]A[1…n−1] 的非递减排列,包含 AA 中最小 n−1n−1 个元素,显然 A[n]A[n] 是 AA 中最大的元素,所以 A[1…n]A[1…n] 是排序后的序列。

d) 最坏运行时间是 Θ(n2)\Theta(n^2),与插入排序运行时间一样。
附上冒泡排序代码:

void bubble_sort(int *array,int length)
{for(int i = 0; i < length - 1; ++i){for(int j = length - 1; j > i; --j){if(*(array + j) < *(array + j - 1)){int temp = *(array + j);*(array + j) = *(array + j - 1);*(array + j - 1) = temp;}}}
}

思考题2-3

a) Θ(n)\Theta(n)
b) 伪代码如下,运行时间为 Θ(n2)\Theta(n^2),显然变慢了。

y = 0
for i = 0 to nt = 1for j = 1 to it = t·xy = y + t·aᵢ

c) 初始化:累加项为空,成立;
保持:在第 ii 次迭代结束时有:

y=ai+x∑k=0n−(i+1)ak+i+1xk=aix0+∑k=0n−i−1ak+i+1xk+1==aix0+∑k=1n−iak+ixk=∑k=0n−iak+ixk

\begin{align}y &= a_i + x\sum_{k=0}^{n-(i+1)}a_{k+i+1}x^k= a_ix^0 + \sum_{k=0}^{n-i-1}a_{k+i+1}x^{k+1} = \\&= a_ix^0 +\sum_{k=1}^{n-i}a_{k+i}x^k= \sum_{k=0}^{n-i}a_{k+i}x^k \end{align}

终止:当 i=−1i=−1 时循环终止,带入循环不变式得

y=∑k=0n−i−1ak+i+1xk=∑k=0nakxk

y = \sum_{k=0}^{n-i-1}a_{k+i+1}x^k = \sum_{k=0}^na_kx^k
d) 由c)显然正确得出 a0,a1…,ana_0,a_1\dots ,a_n,循环不变式的总和等于给定的系数多项式和。

思考题2-4

a) <8,6>、<2,1>、<3,1>、<8,1>、<6,1><script type="math/tex" id="MathJax-Element-101"><8,6>、<2,1>、<3,1>、<8,1>、<6,1></script>
b) 当集合是逆序排列时逆序对最多,一共有n−1+n−2+⋯+1=n(n−1)2n−1+n−2+⋯+1=\frac{n(n−1)}{2}对。

c) 每有一个逆序对就意味着插入排序需要改变这两个元素的位置。也就是每交换一对元素,就会消除一对原序列中的逆序对,所以逆序对和插入排序运行时间是同数量级的。

d) 我们知道归并排序运行时间是 Θ(nlgn)\Theta(n\lg n),在归并排序中合并两个子表的时候需要比较两个子表当前元素的大小(不妨称呼为 LL 表和 RR 表,另外有两个指针分别指向 LL 和 RR 表中需要比较的元素),然后将较小的元素放入到最终数组中,并使指向较小元素的指针后移。假设当前指向 LL 表中的元素比指向 RR 表中的元素要大,这说明指向 LL 表的元素以及 LL 表中该元素的后面所有元素都大于指向 RR 表的元素,因此可得到 LL 表中这一段的逆序对。一直求 LL 表中的逆序即可得到总对数。反之也可以求 RR 表中的逆序对数。通过改变归并排序即可在 Θ(nlgn)\Theta(n\lg n) 求出逆序对数。

#include <iostream>
using std::cin;
using std::cout;
using std::endl;int merge(int *array,int p,int q,int r)
{int n1 = q - p + 1;int n2 = r - q;int *L = new int[n1];int *R = new int[n2];int i = 0, j = 0;for(int k = p; k <= q; ++k)*(L + i++) = *(array + k);for(int k = q + 1; k <= r; ++k)*(R + j++) = *(array + k);i = j = 0;int  inversions = 0;for(int k = p; k <= r; ++k){if(i == n1)*(array + k) = *(R + j++);else if(j == n2)*(array + k) = *(L + i++);else if(*(L + i) <= *(R + j))*(array + k) = *(L + i++);else{*(array + k) = *(R + j++);inversions += n1 - i;}}delete []L;delete []R;return inversions;
}int inversions_merge_sort(int *array,int p,int r)
{int  inversions = 0;if(p < r){int q = (p + r) / 2;inversions += inversions_merge_sort(array,p,q);inversions += inversions_merge_sort(array,q+1,r);inversions += merge(array,p,q,r);}return inversions;
}int main()
{int *array;int len,key;cout << "input the length of array" << endl;cin >> len;array = new int[len];cout << "input " << len << " integers" << endl;for(int i = 0; i < len; ++i)cin >> *(array + i);cout << "Total inversions: " << inversions_merge_sort(array,0,len-1) << endl;delete []array;return 0;
}

CLRS第二章思考题相关推荐

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

    算法导论第三版第二章思考题答案 第二章思考题 算法导论第三版第二章思考题答案 2.1 2.2 2.3 2.4 汇总传送门 2.1 #include<iostream> using name ...

  2. CLRS第三章思考题

    本章思考题证明太繁琐,因此只证明某一些,其余的可类似证明. 思考题3-1 本题只证明前两个,后面可类似得到. 首先,很容易想到 p(n)=Θ(nd)p(n)=\Theta(n^d),若 k≥dk\ge ...

  3. 机器学习(浙大课程b站)第二章

    机器学习(浙大课程b站)第二章:支持向量机 笔记 测试 根据我个人学习的感受,我是以b站浙大机器学习研究生课程(BV1dJ411B7gh)为主,MOOC为辅. 笔记 线性可分与线性不可分 线性可分(L ...

  4. matplotlib 第二章学习

    一.概述 1.matplotlib的三层api matplotlib的原理或者说基础逻辑是,用Artist对象在画布(canvas)上绘制(Render)图形. matplotlib有三个层次的API ...

  5. 蓝桥杯算法竞赛系列第二章——深入理解重难点之递归(上)

    铁汁们,递归(下)已经更新咯,欢迎铁汁们批评指正. 蓝桥杯算法竞赛系列第二章--深入理解重难点之递归(下)_安然无虞的博客-CSDN博客 目录 一.递归是什么? 二.如何理解"递归" ...

  6. 操作系统1~6章思考题

    操作系统思考题 第一章 操作系统 1 在计算机中系统,操作系统有哪两个重要作用? 管理系统中的各种资源 为好友提供友好界面 2 根据操作系统的地位作用 ,请给出操作系统的非形式化的定义 操作系统是位于 ...

  7. 王道考研 计算机网络笔记 第二章:物理层

    本文基于2019 王道考研 计算机网络: 2019 王道考研 计算机网络 个人笔记总结 第一章:王道考研 计算机网络笔记 第一章:概述&计算机网络体系结构 后续章节将陆续更新- 第二章 一.物 ...

  8. 计算机组成原理-第二章 数据表示与运算

    计算机组成原理-第二章 数据表示与运算 一.数据的表示 1.数值型数据的表示(重点难点) 1.1数值型数据的表示--进位制 1.2数值型数据表示-码制 1.3数值型数据的表示--定点数 1.4数值型数 ...

  9. 2021-08-08概率论与数理统计-第二章

    文章目录 概率论与数理统计-第二章 概率论与数理统计-第二章

最新文章

  1. stm32 cubemx hal 工程中 微秒延迟 delay_us
  2. 切诺夫界证明(Chernoff bound)
  3. cudnn v4安装
  4. Python中列表和字符串的反转
  5. 缓存三大问题及解决方案
  6. python网络聊天器多线程版
  7. 程序员面试金典 - 面试题 10.11. 峰与谷(排序/不排序)
  8. Java大牛的一些总结,献给对未来还在迷茫中的你!
  9. 不得不说,其实你的性能优化手段已经过时了
  10. 六部工坊ros启智机器人定点导航技术_【展品抢鲜看】程天科技外骨骼机器人亮相峰会,让每个人享受机器人的服务!...
  11. SLAM:计算机对世界的感知与理解
  12. 【概率论与数理统计】1.2 概率的定义及其确定方法
  13. AUTOSAR实战教程pdf版
  14. 【CSDN】博文导入微信公众号
  15. 基于照片标记的广州市旅游流特征简单分析(上)
  16. 基于朴素贝叶斯的兴趣分类
  17. GMA Round 1 大吉大利,晚上吃鸡
  18. win10电脑玩红警老是卡死怎么办?win10电脑玩红警老是卡死解决方法
  19. 中国-东盟数字经济合作有韧性前景好
  20. 服务器主机和显示器怎么连接,主机跟显示器怎么连接

热门文章

  1. 计算机组成原理实验tec2000,TEC-2000A计算机组成原理实验系统
  2. 模拟电路2(二极管的模型与电路分析)
  3. 用html做一个横向导航菜单,CSS样式制作的漂亮WEB横向导航菜单
  4. jconsole 使用入门
  5. CAN总线与RS485的比较
  6. 学习笔记3-数学基础
  7. 【技术】基于数据库的权限设计
  8. Mac OSX下使用VMware Fusion 配置静态IP 图文教程指南
  9. “三天打鱼两天晒网”程序的c语言实现
  10. 基于Java毕业设计疫情期间物资分派管理系统源码+系统+mysql+lw文档+部署软件