算法复习课后习题部分

合集下载

算法设计与分析第二版课后习题解答

算法设计与分析第二版课后习题解答

算法设计与分析第二版课后习题解答算法设计与分析基础课后练习答案习题 4.设计一个计算的算法,n是任意正整数。

除了赋值和比较运算,该算法只能用到基本的四则运算操作。

算法求//输入:一个正整数n2//输出:。

step1:a=1;step2:若a*a 5. a.用欧几里德算法求gcd。

b. 用欧几里德算法求gcd,比检查min{m,n}和gcd间连续整数的算法快多少倍?请估算一下。

a. gcd(31415, 14142) = gcd(14142, 3131) = gcd(3131, 1618) =gcd(1618, 1513) = gcd(1513,105) = gcd(1513, 105) = gcd(105, 43) =gcd(43, 19) = gcd(19, 5) = gcd(5, 4) = gcd(4, 1) = gcd(1, 0) = 1.b.有a可知计算gcd欧几里德算法做了11次除法。

连续整数检测算法在14142每次迭代过程中或者做了一次除法,或者两次除法,因此这个算法做除法的次数鉴于1·14142 和 2·14142之间,所以欧几里德算法比此算法快1·14142/11 ≈ 1300 与 2·14142/11 ≈ 2600 倍之间。

6.证明等式gcd(m,n)=gcd(n,m mod n)对每一对正整数m,n都成立. Hint:根据除法的定义不难证明:如果d整除u和v, 那么d一定能整除u±v;如果d整除u,那么d也能够整除u的任何整数倍ku.对于任意一对正整数m,n,若d能整除m和n,那么d一定能整除n和r=m mod n=m-qn;显然,若d能整除n和r,也一定能整除m=r+qn和n。

数对(m,n)和(n,r)具有相同的公约数的有限非空集,其中也包括了最大公约数。

故gcd(m,n)=gcd(n,r)7.对于第一个数小于第二个数的一对数字,欧几里得算法将会如何处理?该算法在处理这种输入的过程中,上述情况最多会发生几次? Hint:对于任何形如0 gcd(m,n)=gcd(n,m)并且这种交换处理只发生一次.对于所有1≤m,n≤10的输入, Euclid算法最少要做几次除法?(1次) b. 对于所有1≤m,n≤10的输入, Euclid算法最多要做几次除法?(5次) gcd(5,8) 习题 1.(农夫过河)P—农夫 W—狼G—山羊C—白菜 2.(过桥问题)1,2,5,10---分别代表4个人, f—手电筒4. 对于任意实系数a,b,c, 某个算法能求方程ax^2+bx+c=0的实根,写出上述算法的伪代码(可以假设sqrt(x)是求平方根的函数) 算法Quadratic(a,b,c)//求方程ax^2+bx+c=0的实根的算法 //输入:实系数a,b,c//输出:实根或者无解信息 If a≠0D←b*b-4*a*c If D>0temp←2*ax1←(-b+sqrt(D))/temp x2←(-b-sqrt(D))/temp return x1,x2else if D=0 return –b/(2*a) else return “no real roots” else //a=0if b≠0 return –c/b else //a=b=0if c=0 return “no real numbers”else return “no real roots”5. 描述将十进制整数表达为二进制整数的标准算法 a.用文字描述 b.用伪代码描述解答:a.将十进制整数转换为二进制整数的算法输入:一个正整数n输出:正整数n相应的二进制数第一步:用n除以2,余数赋给Ki(i=0,1,2...),商赋给n 第二步:如果n=0,则到第三步,否则重复第一步第三步:将Ki按照i从高到低的顺序输出 b.伪代码算法 DectoBin(n)//将十进制整数n转换为二进制整数的算法 //输入:正整数n//输出:该正整数相应的二进制数,该数存放于数组Bin[1...n]中 i=1while n!=0 do { Bin[i]=n%2; n=(int)n/2; i++; } while i!=0 do{ print Bin[i]; i--; }9.考虑下面这个算法,它求的是数组中大小相差最小的两个元素的差.(算法略) 对这个算法做尽可能多的改进. 算法 MinDistance(A[0..n-1]) //输入:数组A[0..n-1] //输出:the smallest distance d between two of its elements习题1. 考虑这样一个排序算法,该算法对于待排序的数组中的每一个元素,计算比它小的元素个数,然后利用这个信息,将各个元素放到有序数组的相应位置上去.a.应用该算法对列表”60,35,81,98,14,47”排序b.该算法稳定吗?c.该算法在位吗? 解:a. 该算法对列表”60,35,81,98,14,47”排序的过程如下所示:b.该算法不稳定.比如对列表”2,2*”排序c.该算法不在位.额外空间for S and Count 4.(古老的七桥问题) 第2章习题7.对下列断言进行证明:(如果是错误的,请举例) a. 如果t(n)∈O(g(n),则g(n)∈Ω(t(n)) b.α>0时,Θ(αg(n))= Θ(g(n)) 解:a. 这个断言是正确的。

《数据结构与算法》课后习题答案

《数据结构与算法》课后习题答案

2.3 课后习题解答2.3.2 判断题1.线性表的逻辑顺序与存储顺序总是一致的。

〔×〕2.顺序存储的线性表可以按序号随机存取。

〔√〕3.顺序表的插入和删除操作不需要付出很大的时间代价,因为每次操作平均只有近一半的元素需要移动。

〔×〕4.线性表中的元素可以是各种各样的,但同一线性表中的数据元素具有一样的特性,因此属于同一数据对象。

〔√〕5.在线性表的顺序存储构造中,逻辑上相邻的两个元素在物理位置上并不一定相邻。

〔×〕6.在线性表的链式存储构造中,逻辑上相邻的元素在物理位置上不一定相邻。

〔√〕7.线性表的链式存储构造优于顺序存储构造。

〔×〕8.在线性表的顺序存储构造中,插入和删除时移动元素的个数与该元素的位置有关。

〔√〕9.线性表的链式存储构造是用一组任意的存储单元来存储线性表中数据元素的。

〔√〕10.在单链表中,要取得某个元素,只要知道该元素的指针即可,因此,单链表是随机存取的存储构造。

〔×〕11.静态链表既有顺序存储的优点,又有动态链表的优点。

所以它存取表中第i 个元素的时间与i 无关。

〔×〕12.线性表的特点是每个元素都有一个前驱和一个后继。

〔×〕2.3.3 算法设计题1.设线性表存放在向量A[arrsize] 的前 elenum 个分量中,且递增有序。

试写一算法,将x 插入到线性表的适当位置上,以保持线性表的有序性,并且分析算法的时间复杂度。

【提示】直接用题目中所给定的数据构造〔顺序存储的思想是用物理上的相邻表示逻辑上的相邻,不一定将向量和表示线性表长度的变量封装成一个构造体〕,因为是顺序存储,分配的存储空间是固定大小的,所以首先确定是否还有存储空间,假设有,那么根据原线性表中元素的有序性,来确定插入元素的插入位置,后面的元素为它让出位置,〔也可以从高低标端开始一边比拟,一边移位〕然后插入x ,最后修改表示表长的变量。

int insert (datatype A[],int *elenum,datatype x)/* 设 elenum 为表的最大下标*/ {if (*elenum==arrsize-1)return 0;/* 表已满,无法插入*/else {i=*elenum;while (i>=0 && A[i]>x)/* 边找位置边移动*/{A[i+1]=A[i];i--;}/* 插入成功 */A[i+1]=x;(*elenum)++;return 1;}}时间复杂度为O(n) 。

算法设计与分析基础课后习题答案solu4

算法设计与分析基础课后习题答案solu4
Solving it by backward substitutions for n = 2k yields the following:
C(2k) = 2C(2k−1) + 1 = 2[2C(2k−2) + 1] + 1 = 22C(2k−2) + 2 + 1 = 22[2C(2k−3) + 1] + 2 + 1 = 23C(2k−3) + 22 + 2 + 1 = ... = 2iC(2k−i) + 2i−1 + 2i−2 + ... + 1 = ... = 2kC(2k−k) + 2k−1 + 2k−2 + ... + 1 = 2k − 1 = n − 1.
Design a divide-and-conquer algorithm for this problem.
2
Hints to Exercises 4.1
1. In more than one respect, this question is similar to the divide-and-conquer computation of the sum of n numbers. Also, you were asked to analyze an almost identical algorithm in Exercises 2.4.
b. Set up and solve a recurrence relation for the number of multiplications made by this algorithm.
c. How does this algorithm compare with the brute-force algorithm for this problem?

算法分析与设计重点课后习题答案

算法分析与设计重点课后习题答案

习题13.设计算法求数组中相差最小的两个元素(称为最接近数)的差。

要求分别给出伪代码和C++描述。

//采用分治法//对数组先进行快速排序//在依次比较相邻的差#include <iostream>using namespace std;int partions(int b[],int low,int high){int prvotkey=b[low];b[0]=b[low];while (low<high){while (low<high&&b[high]>=prvotkey)--high;b[low]=b[high];while (low<high&&b[low]<=prvotkey)++low;b[high]=b[low];}b[low]=b[0];return low;}void qsort(int l[],int low,int high){int prvotloc;if(low<high){prvotloc=partions(l,low,high); //将第一次排序的结果作为枢轴qsort(l,low,prvotloc-1); //递归调用排序由low 到prvotloc-1qsort(l,prvotloc+1,high); //递归调用排序由 prvotloc+1到 high}}void quicksort(int l[],int n){qsort(l,1,n); //第一个作为枢轴,从第一个排到第n个}int main(){int a[11]={0,2,32,43,23,45,36,57,14,27,39};int value=0;//将最小差的值赋值给valuefor (int b=1;b<11;b++)cout<<a[b]<<' ';cout<<endl;quicksort(a,11);for(int i=0;i!=9;++i){if( (a[i+1]-a[i])<=(a[i+2]-a[i+1]) )value=a[i+1]-a[i];elsevalue=a[i+2]-a[i+1];}cout<<value<<endl;return 0;}4.设数组a[n]中的元素均不相等,设计算法找出a[n]中一个既不是最大也不是最小的元素,并说明最坏情况下的比较次数。

算法设计与分析基础课后习题答案

算法设计与分析基础课后习题答案

Program算法设计与分析基础中文版答案习题5..证明等式gcd(m,n)=gcd(n,m mod n)对每一对正整数m,n都成立.Hint:根据除法的定义不难证明:如果d整除u和v, 那么d一定能整除u±v;如果d整除u,那么d也能够整除u的任何整数倍ku.对于任意一对正整数m,n,若d能整除m和n,那么d一定能整除n和r=m mod n=m-qn;显然,若d能整除n和r,也一定能整除m=r+qn和n。

数对(m,n)和(n,r)具有相同的公约数的有限非空集,其中也包括了最大公约数。

故gcd(m,n)=gcd(n,r)6.对于第一个数小于第二个数的一对数字,欧几里得算法将会如何处理?该算法在处理这种输入的过程中,上述情况最多会发生几次?Hint:对于任何形如0<=m<n的一对数字,Euclid算法在第一次叠代时交换m和n, 即gcd(m,n)=gcd(n,m)并且这种交换处理只发生一次..对于所有1≤m,n≤10的输入, Euclid算法最少要做几次除法?(1次)b. 对于所有1≤m,n≤10的输入, Euclid算法最多要做几次除法?(5次)gcd(5,8)习题1.(农夫过河)P—农夫 W—狼 G—山羊 C—白菜2.(过桥问题)1,2,5,10---分别代表4个人, f—手电筒4. 对于任意实系数a,b,c, 某个算法能求方程ax^2+bx+c=0的实根,写出上述算法的伪代码(可以假设sqrt(x)是求平方根的函数)算法Quadratic(a,b,c)描述将十进制整数表达为二进制整数的标准算法a.用文字描述b.用伪代码描述解答:a.将十进制整数转换为二进制整数的算法输入:一个正整数n输出:正整数n相应的二进制数第一步:用n除以2,余数赋给Ki(i=0,1,2...),商赋给n第二步:如果n=0,则到第三步,否则重复第一步第三步:将Ki按照i从高到低的顺序输出b.伪代码算法 DectoBin(n).n]中i=1while n!=0 do {Bin[i]=n%2;n=(int)n/2;i++;}while i!=0 do{print Bin[i];i--;}9.考虑下面这个算法,它求的是数组中大小相差最小的两个元素的差.(算法略)对这个算法做尽可能多的改进.算法 MinDistance(A[0..n-1])n-1]a.应用该算法对列表”60,35,81,98,14,47”排序b.该算法稳定吗?c.该算法在位吗?解:a. 该算法对列表”60,35,81,98,14,47”排序的过程如下所示:b.该算法不稳定.比如对列表”2,2*”排序c.该算法不在位.额外空间for S and Count[]4.(古老的七桥问题)习题1.请分别描述一下应该如何实现下列对数组的操作,使得操作时间不依赖数组的长度.a.删除数组的第i个元素(1<=i<=n)b.删除有序数组的第i个元素(依然有序)hints:a. Replace the i th element with the last element and decrease the array size of 1b. Replace the ith element with a special symbol that cannot be a value of the array’s element., 0 for an array of positive numbers ) to mark the i th position is empty. (“lazy deletion”)第2章习题7.对下列断言进行证明:(如果是错误的,请举例)a. 如果t(n)∈O(g(n),则g(n)∈Ω(t(n))b.α>0时,Θ(αg(n))= Θ(g(n))解:a. 这个断言是正确的。

算法设计与分析第三版第四章课后习题答案

算法设计与分析第三版第四章课后习题答案

算法设计与分析第三版第四章课后习题答案4.1 线性时间选择问题习题4.1问题描述:给定一个长度为n的无序数组A和一个整数k,设计一个算法,找出数组A中第k小的元素。

算法思路:本题可以使用快速选择算法来解决。

快速选择算法是基于快速排序算法的思想,通过递归地划分数组来找到第k小的元素。

具体步骤如下: 1. 选择数组A的一个随机元素x作为枢纽元。

2. 使用x将数组划分为两个子数组A1和A2,其中A1中的元素小于等于x,A2中的元素大于x。

3. 如果k等于A1的长度,那么x就是第k小的元素,返回x。

4. 如果k小于A1的长度,那么第k小的元素在A1中,递归地在A1中寻找第k小的元素。

5. 如果k大于A1的长度,那么第k小的元素在A2中,递归地在A2中寻找第k-A1的长度小的元素。

6. 递归地重复上述步骤,直到找到第k小的元素。

算法实现:public class LinearTimeSelection {public static int select(int[] A, int k) { return selectHelper(A, 0, A.length - 1, k);}private static int selectHelper(int[] A, int left, int right, int k) {if (left == right) {return A[left];}int pivotIndex = partition(A, left, righ t);int length = pivotIndex - left + 1;if (k == length) {return A[pivotIndex];} else if (k < length) {return selectHelper(A, left, pivotInd ex - 1, k);} else {return selectHelper(A, pivotIndex + 1, right, k - length);}}private static int partition(int[] A, int lef t, int right) {int pivotIndex = left + (right - left) / 2;int pivotValue = A[pivotIndex];int i = left;int j = right;while (i <= j) {while (A[i] < pivotValue) {i++;}while (A[j] > pivotValue) {j--;}if (i <= j) {swap(A, i, j);i++;j--;}}return i - 1;}private static void swap(int[] A, int i, int j) {int temp = A[i];A[i] = A[j];A[j] = temp;}}算法分析:快速选择算法的平均复杂度为O(n),最坏情况下的复杂度为O(n^2)。

(陈慧南 第3版)算法设计与分析——第2章课后习题答案

(陈慧南 第3版)算法设计与分析——第2章课后习题答案

因此 T (n) (n 2 ) (3) a 28, b 3, f n cn3
nlogb a nlog3 28 n3.033 ,则 f (n) c n 2 (nlogb a - ) ,其中可取 =0.04 。符合主定理
的情况 1 ,因此 T (n) (n3.033 )
21 21 当 n n0 时, f n g n ,所以 f n = g n 2 2
(2) f n n 2 logn , g n n log 2 n
2 当 n 4 时, f n n 2 logn n 2 , g n n log 2 n n 。因此可取 n0 4, c 1 ,当
g n
(1) f n 20n logn , g n n+ log 3 n
f n 20n logn 21n , g n n+ log 3 当 n 3 时, logn n log3 n 2n n 因此
因此可取 n0 3, c
f n g n ,所以 f n = g n
2-12 将下列时间函数按增长率的非递减次序排列
3 2
n
, log n , log 2 n , n log n , n ! , log(log(n)) , 2 n , n1 log n , n 2
答: n1 log n
f ( n ) ( n m )
证明:
f (n) am nm am1nm1 a1n a0 F (n) am n m am1 n m1
a1 n a0
由 F (n) 单调性易知,存在 nt 0 ,使得 F (n) 取 n 1 ,且 nt0 nt , F (nt0 ) 0 ,则 当 n nt0 时, F (n) 0 即: f (n) am n m am1 n m1

(陈慧南 第3版)算法设计与分析——第7章课后习题答案

(陈慧南 第3版)算法设计与分析——第7章课后习题答案

③ 其余元素
w[0][2] q[2] p[2] w[0][1] 15
k 1: c[0][0] c[1][2] c[0][2] min k 2 : c[0][1] c[2][2] w[0][2] 22 r[0][2] 2



17000
s[0][2]

0
m[1][3]

min
k k
1: m[1][1] m[2][3] 2 : m[1][2] m[3][3]
p1 p2 p4 p1 p3 p4


10000
s[1][3]

2
m[1][3]

min

k k

0 : m[0][0] m[1][3] 1: m[0][1] m[2][3]
第七章课后习题
姓名:赵文浩 学号:16111204082 班级:2016 级计算机科学与技术 7-1 写出对图 7-19 所示的多段图采用向后递推动态规划算法求解时的计算过程。
3
1
3
1
6
5
0
2
6
6
3
4
4 6
5
2
7
8
3
2
8
5
2
7
解析:
V 5 cost(5,8) 0 d (5,8) 8
V4
cos t(4, 6) minc(6,8) cos t(5,8) 7 cos t(4, 7) minc(7,8) cos t(5,8) 3
k 1: c[0][0] c[1][3] c[0][3] min k 2 : c[0][1] c[2][3] w[0][3] 25
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

树的按层次遍历:template<class T, class Func> //void LevelOrder(treenode<T> *x, Func Visit){ queue<treenode<T> *> Q;Q.push(x);while(!Q.empty()){ x = Q.front(), Q.pop();if(x == 0) continue;Visit(x); // visit x// put x's children on queueQ.push(x->first);for(x = x->first; x != 0; x = x->next) Q.push(x->next);}}图的宽度优先遍历连通图的宽度优先搜索(BFS):// BFS.h#pragma once#include <queue>#include "Matrix.h" // 用于邻接矩阵void BFS(const Matrix <bool> &G, int v, vector <int> &Visited) { // G为图的邻接矩阵,从顶点v开始,已访问的顶点标记为// Visited[i]=访问序号,Visited各分量已经初始化为0。

int n = G.Rows(), k, w; // k为访问序号,v、w为顶点序号。

queue <int> Q;Visited[v] = k = 1, Q.push(v); // 访问v,v加入队列Qwhile(!Q.empty()){ v = Q.front(), Q.pop(); // 取出队首元素vfor(w = 0; w < n; ++w)if(!Visited[w] && G[v][w] == 1)++k, Visited[w] = k, Q.push(w);}}一般图的宽度优先遍历(BFT):#include "Algorithm.hpp" // 用于邻接矩阵#include "BFS.h"void BFT(const Matrix <bool> &G, vector <int> &Visited) { // 从顶点0开始,已访问的顶点标记为Visited[i]=分支中的// 访问序号,Visited各分量已经初始化为0。

int n = G.Rows(); // 顶点个数for(int i = 0; i < n; ++i)if(!Visited[i]) BFS(G, i, Visited);}连通图的深度优先搜索(DFS):#include "Algorithm.hpp"#include "Matrix.h" // 用于邻接矩阵void DFS(const Matrix <bool> &G, int v, vector<int> &Visited, int k = 1) { // 访问由v到达的所有顶点,起始下标为0int n = G.Rows();Visited[v] = k;for(int w = 0; w < n; ++w)if(Visited[w] == 0 && G[v][w] == 1)DFS(G, w, Visited, k + 1);}归并排序算法:#include "Algorithm.hpp"template <class T> // 合并两个有序组到wvoid Merge(T a[], int low, int mid, int high, T w[]){ // 将有序组a[low .. mid]和a[mid+1 .. high]合并到有序组w[low .. high] int i = low, j = mid + 1, k = low; // low组游标i,high组游标j,结果游标k for(; i <= mid && j <= high; ++k) // 当两组都未取尽时if(a[i] <= a[j]) w[k] = a[i], ++i;else w[k] = a[j], ++j;// 当low组取尽,而high组未取尽时,w[k .. high] = a[j .. high]if(i > mid) copy(a + j, a + high + 1, w + k);// 当high组取尽,而low组未取尽时,w[k .. high] = a[i .. mid]else copy(a + i, a + mid + 1, w + k);}快速排序算法// Partition.h#pragma oncetemplate <class T> // 划分程序int Partition(T a[], int low, int high){ // 待划分数组为a[low .. high]。

将<key的元素置于key左侧。

int pivot = low; // 划分位置T key = a[pivot]; // 划分元素for(int i = low + 1; i <= high; ++i)if(a[i] < key) a[pivot] = a[i], ++pivot, a[i] = a[pivot];// 将小于key的元素插入key左侧,大于key的元素向右移。

a[pivot] = key; // 划分位置的元素为key。

return pivot;}#include "Partition.h"#include "Algorithm.hpp"template <class T> //void QuickSort(T a[], int low, int high){ if(low >= high) return;int pivot = Partition(a, low, high); // 划分元素的位置QuickSort(a, low, pivot - 1);QuickSort(a, pivot + 1, high);} //采用划分的选择算法#include "Partition.h"#include "Algorithm.hpp" mtemplate <class T> //T PartSelect(T a[], int n, int k){ // 在数组a[0..(n-1)]中找第k(1≤k≤n)小元素,即a[k-1]。

// 其余元素按划分元素为a[k-1]的划分规则存放。

int low = 0, high = n - 1, m; // low为起始下标,high为终止下标for(--k;;) // 保证0≤k≤n-1{ m = Partition(a, low, high); // m是第m(0≤m≤n-1)小元素的位置if(k == m) return a[m];else if(k < m) high = m - 1; // 新的终止下标为m-1else low = m + 1; // 新的起始下标为m+1}}CH4背包问题背包问题的贪心算法template <class Tv, class Tw, class T> //void GreedyKNAP(Tv V[], Tw W[], T X[], int n, Tw rc){ // V是价值数组,W是重量数组,X是解向量,rc是剩余容量。

int i;fill(X, X + n, 0); // 解向量初始化为零mSort(V, W, n, Comp<Tv, Tw>); // 将物品按单价降序排列for(i = 0; i < n && W[i] <= rc; ++i)X[i] = 1, rc = rc - W[i]; // 可完整装包的物品完整装包if(i < n) X[i] = rc / W[i]; // 不能完整装包的物品部分装包}2 种最小生成树算法Prim 算法// Prim.h#include "Matrix.h"template <class W> //bool Prim(const Matrix<W> &G, Matrix<int> &T){ // G是邻接矩阵。

T存放生成树的边,共n-1行2列。

int i, j, k, n = G.Rows();W minCost = 0; // 刚开始时最小生成树的成本值为0vector<int> near(n, 0); // 指定各顶点的初始near值near[0] = -1; // 将0加到树中for(i = 0; i < n - 1; ++i) // 循环n-1次, 添加n-1条边{ // 求树外顶点到树内顶点具有最小权值的边及顶点位置jW min = Matrix<W>::inf; // 无穷大for(j = 0, k = 1; k < n; ++k)if(near[k] >= 0 && G[near[k]][k] < min) min = G[near[k]][k], j = k;if(min >= Matrix<W>::inf) return false; // min是无穷大,没有生成树T[i][0] = near[j], T[i][1] = j; // 添加(near[j], j),其中j是near[j]的儿子minCost += min; // 添加(near[j], j)后,树的成本值增加near[j] = -1; // 将j加到树中for(k = 1; k < n; ++k) // 更新每个顶点的near值if(near[k] >= 0 && G[j][k] < G[near[k]][k]) near[k] = j;6} //return true; // 共找到n-1条,有生成树}Kruskal算法template <class Ty> //bool Kruskal(Edge <Ty> Ed[], int n, int e, Edge <Ty> T[]){ UnionFind U(n); // 合并/查找结构,初始时表示n个不同集合sort(Ed, Ed + e); // 对边集合排序int i, k;for(i = 0, k = 0; i < e && k < n - 1; ++i){ int a = U.Find(Ed[i].u), b = U.Find(Ed[i].v); // u,v所在集合if(a != b) // 如果u、v分属不同集合,选取该边{ T[k] = Ed[i], ++k; // 将边x加入最小生成树,边数增加1U.Union(a, b); // 合并u、v分属的两个集合}}return k == n - 1; // 是否有最小生成树}Dijkstra 最短路径算法#include "Algorithm.hpp"#include "Matrix.h"template<class T> // G是有向图的邻接矩阵,v是指定顶点void Dijkstra(const Matrix<T> &G, int v, vector<T> &dist, vector<int> &Prev) {int i, u, w, n = G.Rows();vector<bool> S(n, 0); // 标志一个顶点是否属于S,初始化为0for(i = 0; i < n; ++i) dist[i] = G[v][i], Prev[i] = v; // 初始化dist,Prevdist[v] = 0, S[v] = 1; // v加入Sfor(i = 0; i < n - 1; ++i){ // 选取w使Dist(w)=min{Dist(u)|S(u)=0}for(w = 0; w < n && S[w] == 1; ++w) {} // 第一个满足S(w)=0的wfor(u = w; u < n; ++u) // 找到满足要求的wif(S[u] == 0 && dist[u] < dist[w])w = u;S[w] = 1; // w加入Sfor(u = 0; u < n; ++u) // 更新未选顶点的dist和Previf(S[u] == 0 && G[w][u] < dist[u] && dist[w] + G[w][u] < dist[u])dist[u] = dist[w] + G[w][u], Prev[u] = w;}} //CH5矩阵连乘问题的解法1、计算矩阵连乘的递归算法计算最优值#include "Algorithm.hpp"#include "Matrix.h"int MatrixChain1(int r[], Matrix<int> &kay, int i = 0, int j = -1){ if(j < 0) j = kay.Rows() - 1; // 初始化,j=n-1if(j <= i) return 0; // 只有一个矩阵// 有多个矩阵,从k=i开始计算最小项u,并更新kay#define C(i, j) MatrixChain1(r, kay, (i), (j))int u = C(i, i) + C(i + 1, j) + r[i] * r[i + 1] * r[j + 1];kay[i][j] = i;for(int k = i + 1; k < j; ++k){ int t = C(i, k) + C(k + 1, j) + r[i] * r[k + 1] * r[j + 1];if(t < u) u = t, kay[i][j] = k; // 找到更小的项}return u;#undef C}求矩阵连乘最优次序的备忘录方法int MatrixChain2(int r[], Matrix<int> &kay, Matrix<int> &c, int i = 0, int j = -1) { if(j < 0) j = kay.Rows() - 1, fill(c.begin(), c.end(), 0); // 初始化,j=n-1if(j <= i) return 0; // 只有一个矩阵if(c[i][j] > 0) return c[i][j]; // c[i][j]已经确定// 有多个矩阵,从k=i开始计算最小项u,并更新kay#define C(i, j) MatrixChain2(r, kay, c, (i), (j))c[i][j] = C(i, i) + C(i + 1, j) + r[i] * r[i + 1] * r[j + 1];kay[i][j] = i;for(int k = i + 1; k < j; ++k){ int t = C(i, k) + C(k + 1, j) + r[i] * r[k + 1] * r[j + 1];if(t < c[i][j]) c[i][j] = t, kay[i][j] = k; // 找到更小的项}return c[i][j];#undef c}求矩阵连乘最优次序的动态规划算法int MatrixChain3(int r[], Matrix<int> &kay, Matrix<int> &c){ int i, j, k, t, n = kay.Rows(); // 动态规划方法,n为矩阵个数fill(c.begin(), c.end(), 0); // 初始化for(i = n - 2; i >= 0; --i) // 计算c[i][j]和kay[i][j],其中j>i{ for(j = i + 1; j < n; ++j) // 从k=i开始计算最小项u,并更新kay{ c[i][j] = c[i][i] + c[i + 1][j] + r[i] * r[i + 1] * r[j + 1], kay[i][j] = i;for(k = i + 1; k < j; ++k){ t = c[i][k] + c[k + 1][j] + r[i] * r[k + 1] * r[j + 1];if(t < c[i][j]) c[i][j] = t, kay[i][j] = k; // 找到更小的项}}}return c[0][n - 1];}任意顶点间最短路径#include "Algorithm.hpp"#include "Matrix.h"template <class T, class Func> // 顶点编号从0开始Matrix<T> Floyd(const Matrix<T> &Cost, Matrix<int> &Next, Func Plus) { int i, j, k, n = Cost.Rows();Matrix<T> A = Cost; // A[-1]=Costfor(i = 0; i < n; ++i)for(j = 0; j < n; ++j)Next[i][j] = j; // 建立初始Next55for(k = 0; k < n; ++k) //A[0]到A[n-1]的循环控制for(i = 0; i < n; ++i)for(j = 0; j < n; ++j){ if(i == k || j == k) continue;T x = Plus(A[i][k], A[k][j]);if(x < A[i][j]) A[i][j] = x, Next[i][j] = Next[i][k];}return A;}CH6子集问题递归方法(一)#include "Algorithm.hpp"#define legal(t) true // 检查合法性#define bound(t) true // 检查界限void Subset1(int X[], int n, int t = 0) // 递归方法(一){ for(int i = 0; i <= 1; ++i){ X[t] = i;if(!legal(t)) continue; // not legalif(t >= n - 1) Copy(X, X + n) << endl; // answerelse if(bound(t)) Subset1(X, n, t + 1); // bound}}递归方法(二)void Subset2(int X[], int n, int t = 0) // 递归方法(二){ if(t >= n) Copy(X, X + n) << endl; // answerelse{ X[t] = 1; // 尝试选取t,生成左儿子if(legal(t)) Subset2(X, n, t + 1); // legalX[t] = 0; // 若根t子树没有越界,生成右儿子if(bound(t)) Subset2(X, n, t + 1); // bound}}迭代方法void Subset(int X[], int n) // 迭代方法{ X[0] = - 1;for(int t = 0; t >= 0;){ ++X[t];if(X[t] > 1) --t; // 回溯else if(!legal(t)) continue; // not legalelse if(t >= n - 1) Copy(X, X + n) << endl; // answer else if(bound(t)) ++t, X[t] = - 1; // bound}}排列问题递归方法(一)#include "Perm.h"#include "Algorithm.hpp"#define legal(X, t) true // 检查合法性#define bound(X, t) true // 检查界限void Perm1(int X[], int n, int t = 0) // 生成分量的方法{ if(t <= 0) fill(X, X + n, -1); // X初始化为-1,必须while(NextValue(X, n, t))if(legal(X, t))if(t >= n - 1) Copy(X, X + n) << endl; // 已经获得一个排列else if(bound(X, t)) Perm1(X, n, t + 1); // 纵深搜索}递归方法(二)void Perm2(int X[], int n, int t = 0) // 对自然排列重新排列的方法{ if(t <= 0) InitPerm(X, n); // 初始化为0..(n-1)的自然排列,必须for(int i = t; i < n; ++i){ swap(X[t], X[i]);if(legal(X, t))if(t >= n - 1) Copy(X, X + n) << endl; // 已经获得一个排列else if(bound(X, t)) Perm2(X, n, t + 1); // 纵深搜索swap(X[t], X[i]);}}迭代方法void Perm(int X[], int n) // 用迭代方法生成各个分量{ int t = 0;X[t] = -1;while(t >= 0){ if(!NextValue(X, n, t)) --t; // 回溯else if(legal(X, t))if(t >= n - 1) Copy(X, X + n) << endl; // 已经获得一个排列else if(bound(X, t)) ++t, X[t] = -1; // 纵深搜索}}旅行商问题递归方法(一)#include "Algorithm.hpp"#include "Perm.h"#include "Matrix.h"#include "TSP.h"template <class T> // BX为最优路径,BC为最优耗费,C为当前耗费void TSP1(Matrix<T> &G, int BX[], T &BC, T C = 0, int t = 1){ static int n, *X; // n为图的顶点个数。

相关文档
最新文档