算法设计与分析 第3章2
《算法设计与分析》第3章 动态规划法
通常子问题个数随问题的大小呈多项式增长。因此用动态规 划算法只需要多项式时间,从而获得较高的解题效率。
动态规划法 .VS. 分治法
动态规划法的实质也是将较大问题分解为较小的同类 子问题,这一点上它与分治法类似。
分治法的子问题相互独立,相同的子问题被重复计算。 动态规划法利用问题的最优子结构特征,设计自底向 上的计算过程,通过从子问题的最优解逐步构造出整 个问题的最优解。避免重复计算。
2.2 一般方法
设计一个动态规划算法,通常可以按以下几个 步骤进行:
(1)刻画最优解的子结构特性; (2)递归定义最优解值; (3)以自底向上方式计算最优解值; (4)根据计算得到的信息构造一个最优解。
其中,第(1)至(3)步是动态规划算法的基 本步骤。最优解值是最优解的目标函数的值。
3. 多段图问题
最优解的递推关系 定义m[i:j],表示矩阵连乘A[i:j]所需的最少计算 量 则有: i j 0 m[i ][ j ] i j minj{m[i ][ k ] m[k 1][ j ] pi 1 pk p j } i k
假设:N个矩阵的维数依序放在一维数组p中, 其中Ai的维数记为Pi-1×Pi
需要时引用,以避免相同子问题的重复求解。
【程序】矩阵连乘的备忘录方法 //m0 int MatrixChain::LookupChain(int i, int j) { if (m[i][j]>0) return m[i][j]; //子问题已解。 if(i==j) return 0; int u=LookupChain(i+1,j)+p[i]*p[i+1]*p[j+1]; s[i][j]=i; for (int k=i+1;k<j; k++) { int t=LookupChain(i,k)+LookupChain(k+1,j) +p[i]*p[k+1]*p[j+1]; if (t<u) { int MatrixChain::LookupChain() u=t; { s[i][j]=k; return LookupChain(1,n); 备忘录方法的控制结构与直接递归方法的控制结构相同,区别 } } 在于备忘录方法为每个解过的子问题建立了备忘录以备需要时 } 查看,避免了相同子问题的重复求解。 m[i][j]=u; return u; 矩阵连乘A[i:j]的最少计算量记为m[i,j] }
算法分析与设计习题集整理
算法分析与设计习题集整理
第一章算法引论
一、填空题:
一、算法运行所需要的计算机资源的量,称为算法复杂性,主要包括时间复杂度和空间复杂度。
二、多项式10()m
m A n a n a n a =+
++的上界为O(n m )。
3、算法的大体特征:输入、输出、肯定性、有限性。
4、如何从两个方面评价一个算法的好坏:时间复杂度、空间复杂度。 五、计算下面算法的时间复杂度记为: O(n 3) 。
for(i=1;i<=n;i++)
for(j=1;j<=n;j++) {c[i][j]=0; for(k=1;k<=n;k++) c[i][j]= c[i][j]+a[i][k]*b[k][j]; }
六、描述算法常常利用的方式:自然语言、伪代码、程序设计语言、流程图、盒图、PAD 图。 7、算法设计的大体要求:正确性 和 可读性。 八、计算下面算法的时间复杂度记为: O(n 2) 。
for (i =1;i<n; i++)
{ y=y+1; for (j =0;j <=2n ;j++ ) x ++; }
九、计算机求解问题的步骤:问题分析、数学模型成立、算法设计与选择、算法表示、算法分析、算法实现、程序调试、结果整理文档编制。 10、算法是指解决问题的 方式或进程 。
二、简答题:
1、依照时间复杂度从低到高排列:O( 4n 2)、O( logn)、O( 3n )、O( 20n)、O( 2)、O( n 2/3
), O( n!)应该排在哪一名?
答:O( 2),O( logn),O( n 2/3),O( 20n),O( 4n 2),O( 3n
算法设计与分析-第3章-蛮力法
清华大学出版社
算法设计与分析
KMP算法用伪代码描述如下:
算法3.5——KMP算法 1. 在串S和串T中分别设比较的起始下标i和j; 2. 循环直到S中所剩字符长度小于T的长度或T中所有字符均比较完毕
2.1 s++; 2.2 将s对应的子集输出;
显然,算法3.10的时间复杂性为O(2n),也就是说和子 集的数量成正比。
清华大学出版社
算法设计与分析
3.4.3 0/1背包问题
0/1背包问题是给定n个重量为{w1, w2, … ,wn}、 价值为{v1, v2, … ,vn}的物品和一个容量为C的背包, 求这些物品中的一个最有价值的子集,并且要能够 装到背包中。
算法设计与分析
设计思想:尽量利用已经部分匹配的结果信息, 尽量让 i 不回溯,加快模式串的滑动速度。
清华大学出版社
算法设计与分析
i ii
第 a b a bc a bc a cb a b
趟 a bc
i=3,j=3失败;
1
2
j jj
第
i
a b a b c a b c a cb a b
趟
a
s2=t2;t1≠t2 ∴t1≠s2
(1)理论上,蛮力法可以解决可计算领域的各种问题。 (2)蛮力法经常用来解决一些较小规模的问题。 (3)对于一些重要的问题蛮力法可以产生一些合理的算 法,他们具备一些实用价值,而且不受问题规模的限制。 (4)蛮力法可以作为某类问题时间性能的底限,来衡量 同样问题的更高效算法。
算法设计与分析_王红梅_课后答案网(部分)
第六章
动态规划法
• P137 2 ,3, 4
•
2.解答:cost[i]表示从顶点i 到终点n-1 的最短路径,path[i]表示从顶点i 到终点n-1 的路径上顶点i 的下一个顶点。
cost[i]=min{cij+cost[j]}
3 有5 个物品,其重量分别是{3, 2, 1, 4,5},价值分别为{25, 20, 15, 40, 50},背包的容量为6。V[i][j]表
示把前i 个物品装入容量为j 的背包中获得的最大价值。
最优解为(0,0,1,0,1)最优值为65. 4.
序列A =(x, z , y , z , z , y,x ),B =(z , x , y , y , z , x , z ),建立两个(m+1)×(n+1)的二 维表L 和表S ,分别存放搜索过程中得到的子序列的长度和状态。z , x , y , y , z,x , z )
path[i]= 使 cij+cost[j] 最小的 j i 0
1
2
3
4
5
6
7
8 9 10 11 12 13 14 15 Cost[i] 18 13 16 13 10 9 12 7 6
8
7
5
9
4
3
Path[i]
1
4
5
7
7
8
9
11 11 11 13 14 14 15 15 0
得到最短路径 0->1->4->7->11->14->15 , 长度为 18
(a)长度矩阵L(b)状态矩阵S 。。。。。。
第七章贪心算法
2.背包问题:
有7 个物品,背包容量W=15。将给定物品按单位重量价值从大到小排序,结果如下:
个物品,物品重量存放在数组w[n]中,价值存放在数组
第2章 算法分析基础(《算法设计与分析(第3版)》C++版 王红梅 清华大学出版社)
3
2.1.1 输入规模与基本语句
例2.3 如下算法实现将两个升序序列合并成一个升序序列,请找出 输入规模和基本语句。
3
void Union(int A[ ], int n, int B[ ], int m, int C[ ] ) {
int i = 0, j = 0, k = 0; while (i < n && j < m) {
Page 18
2.1.5 递归算法的时间复杂度分析
3
对递归算法时间复杂度的分析,关键是根据递归过程建立递推关 系式,扩展递归是一种常用的求解递推关系式的基本技术。
例 2.7
分析递推式
T (n)
2T (n
7 2) 5n2
假定 n = 2k T (n) 2T (n 2) 5n2
n 1 n 1
n 1
其中 a、b、c、k 都是常数
算 法
n 1
设 计
与
分
析
合并解的时间
( 第
版 )
清
O(nlogb a )
a bk
华 大 学
T (n) O(nk logb n)
a bk
出 版 社
O(nk )
a bk
Page 20
Page 20
小结:时间复杂度分析 算法分析的核心——计数
算法设计与分析双语课Chapter 3 Divide and conquer
North China Electric Power University
Divide-and-conquer algorithm: Divide the input array into two halves A[1..n/2] and A[n/2+1..n], find the minimum and maximum in each half and return the minimum of the two minima and the the maximum of the two maxima.
North China Electric Power University
North China Electric Power University
算法设计与分析
Algorithms Design & Analysis
华北电力大学计算机科学与技术学院
School of Computer Science&Technology of North China Electric Power University
North China Electric Power University
Chapter 3 Divide and Conquer
1. Introduction 2. The divide and conquer paradigm 3. Binary search 4. Mergesort 5. Multiplication of large integers 6. Matrix multiplication 7. Linear-time selection problem
算法设计与分析知识点
第一章算法概述
1、算法的五个性质:有穷性、确定性、能行性、输入、输出。
2、算法的复杂性取决于:(1)求解问题的规模(N) , (2)具体的输入数据(I),( 3)算法本身的设计
(A),C=F(N,I,A。
3、算法的时间复杂度的上界,下界,同阶,低阶的表示。
4、常用算法的设计技术:分治法、动态规划法、贪心法、回溯法和分支界限法。
5、常用的几种数据结构:线性表、树、图。
第二章递归与分治
1、递归算法的思想:将对较大规模的对象的操作归结为对较小规模的对象实施同样的操作。递归的时间复杂性可归结为递归方程:
1 11= 1
T(n) <
aT(n—b) + D(n) n> 1
其中,a是子问题的个数,b是递减的步长,~表示递减方式,D(n)是合成子问题的开销。递归元的递减方式~有两种:1、减法,即n -b,的形式。2、除法,即n / b,的形式。
2、D(n)为常数c:这时,T(n) = 0(n P)。
D(n)为线形函数cn:
r O(n) 当a. < b(N
T(n) = < Ofnlog^n) "n = bllj
I O(I1P)二"A bl吋
其中.p = log b a o
D(n)为幕函数n x:
r O(n x) 当a< D(b)II J
T{ii) = O(ni1og b n) 'ia = D(b)ll]
.O(nr)D(b)lH
JI:中,p= log b ao
考虑下列递归方程:T(1) = 1
⑴ T( n) = 4T(n/2) +n
⑵ T(n) = 4T(n/2)+n2
⑶ T(n) = 4T(n/2)+n3
算法分析与设计第二版习题答案-第三章到第五章
buf[k+1]+=buf[k]/10;
buf[k]%=10;
}
}
for(i=n-1;i>=0;i--)
printf("%d",buf[i]);
printf("\n");
return0;
}
2.
#include<stdio.h>int main(int argc,char **argv){int buf[6][6];int i,j;printf("任意输入6个数
0;}4.#include<stdio.h>#define N 5int main(int argc,char **argv){int buf[N][N];int
i,j,k;int count=1;int n=0;for(i=0;i<N;i++){ for(k=0,j=n;j>=0;j--
,k++) buf[j][k]=count++; n++;}for(i=0;i<N;i++){ for(j=0;j<N-
>next=NULL;if(top==NULL){top=newnode; }else{newnode- >next=top; top=newnode; }}int pop(){int flag;link stack;if(top!=NULL){stack=top; top=top->next; flag=stack- >flag; free(stack); }return flag;}int op(char ch){switch(ch){case'+':return1;break; case'-':return2;break; case'*':return3;break; case'/':return4;break; default: return5;}}void nirnava(char *buf,int count)//count个数,buf数组
算法设计与分析 第2版 吕国英 第三章课后习题答案
3.1//计算2+22+222+...+222 (2)
void main()
{
int i,n,sum=0;
print("请输入最后一个因子的位数\n");
scanf("%d",&n);
for(i=1;i<=n;i++)
sum=sum+((int)pow(10,i)-1)/9*2;
print("2+22+222+...+222……2=%d\n",sum); }
3.2显示{5,7,4,8,9,1}的方阵方式
main()
{
int i,j,t,ori[6]={5,7,4,8,9,1};
for(i=0;i<6;i++)
{
for(j=0;j<6;j++)
{
t=(j-i)<0?j-i+6:j-i;
printf("%d ",ori[t]);}
printf("\n");
}
}
3.3
main()
{
int n;
int **up(int **array);
scanf("%d",&n);
int arr[1][1]={{n*n}};
for(j=1;j
arr=up(**arr,j);
}
int **up(int **array,n)
{
int upN=n+1;
int[upN][upN] tem;
tem[1][1]=array[1][1]-pow(n+1,2);
for(i=1;i<=n;i++)
tem[1][i]=tem[1][i-1]+1;
for(i=1;i<=n;i++)
tem[n][i]=tem[n][i-1]+1;
for(i=1;i<=n;i++)
tem[n][n-i]=tem[n][n+1-i]+1;
for(i=1;i
算法设计与分析报告习题
《算法设计与分析》习题
第一章算法引论
1、算法的定义?
答:算法是指在解决问题时,按照某种机械步骤一定可以得到问题结果的处理过程。
通俗讲,算法:就是解决问题的方法或过程。
2、算法的特征?
答:1)算法有零个或多个输入;2)算法有一个或多个输出; 3)确定性;4)有穷性
3、算法的描述方法有几种?
答:自然语言、图形、伪代码、计算机程序设计语言
4、衡量算法的优劣从哪几个方面?
答:(1) 算法实现所耗费的时间(时间复杂度);
(2) 算法实现所所耗费的存储空间(空间复杂度);
(3) 算法应易于理解,易于编码,易于调试等等。
5、时间复杂度、空间复杂度定义?
答:指的是算法在运行过程中所需要的资源(时间、空间)多少。
6、时间复杂度计算:
{i=1;
while(i<=n)
i=i*2; }
答:语句①执行次数1次,
语句②③执行次数f(n), 2^f(n)<=n,则f(n) <=log2n;
算法执行时间: T(n)= 2log2n +1
时间复杂度:记为O(log2n) ;
7.递归算法的特点?
答:①每个递归函数都必须有非递归定义的初值;否则,递归函数无法计算;(递归终止条件)
②递归中用较小自变量函数值来表达较大自变量函数值;(递归方程式)
8、算法设计中常用的算法设计策略?
答:①蛮力法;②倒推法;③循环与递归;④分治法;
⑤动态规划法;⑥贪心法;⑦回溯法;⑧分治限界法
9、设计算法:
递归法:汉诺塔问题?兔子序列(上楼梯问题)?
整数划分问题?
蛮力法:百鸡百钱问题?
倒推法:穿越沙漠问题?
答:算法如下: (1) 递归法
● 汉诺塔问题
算法设计与分析习题答案1-6章
习题1
1.
图论诞生于七桥问题。出生于瑞士的伟大数学家欧拉(Leonhard Euler ,1707—1783)提出并解决了该问题。七桥问题是这样描述的:一个人是否能在一次步行中穿越哥尼
斯堡(现在叫加里宁格勒,在波罗的海南岸)城中全部的七座桥后回到起点,且每座桥只经
过一次,图1.7是这条河以及河上的两个岛和七
座桥的草图。请将该问题的数据模型抽象出来,并判断此问题是否有解。
七桥问题属于一笔画问题。 输入:一个起点 输出:相同的点 1, 一次步行
2, 经过七座桥,且每次只经历过一次 3, 回到起点
该问题无解:能一笔画的图形只有两类:一类是所有的点都是偶点。另一类是只有二个奇点的图形。
2.在欧几里德提出的欧几里德算法中(即最初的欧几里德算法)用的不是除法而是减法。请用伪代码描述这个版本的欧几里德算法 1.r=m-n
2.循环直到r=0 2.1 m=n 2.2 n=r 2.3 r=m-n 3 输出m
3.设计算法求数组中相差最小的两个元素(称为最接近数)的差。要求分别给出伪代码和C ++描述。
//采用分治法
//对数组先进行快速排序 //在依次比较相邻的差 #include <iostream> using namespace std;
int partions(int b[],int low,int high) {
图1.7 七桥问题
int prvotkey=b[low];
b[0]=b[low];
while (low<high)
{
while (low<high&&b[high]>=prvotkey)
《计算机算法设计与分析》第三章 动态规划
32
33
设要计算矩阵连乘积中各矩阵的维数分别为:
11
3.2 矩阵连乘问题
给定n个矩阵 {A1, A2,..., An} ,其中 Ai与 Ai1是可乘 的,i 1,2,...,n 1。考察这n个矩阵的连乘积
A1A2... An
由于矩阵乘法满足结合律,所以计算矩阵的连乘可以 有许多不同的计算次序。这种计算次序可以用加括号 的方式来确定。
问题的最优子结构性质是该问题可用动态规划算 法求解的显著特征。
26
27
2、建立递归关系
假设计算A[i:j](1≤i≤j≤n)所需要的最少数乘 次数为m[i,j],则原问题的最优值为m[1,n] i=j时,A[i:j]=Ai,m[i,i]=0,i=1,2,…,n
i<j时, m[i, j] m[i, k ] m[k 1, j] pi1 pk p j
19
分治法 将矩阵连乘积AiAi+1…Aj简记为A[i:j]。 设n个矩阵的连乘积A1A2…An的计算次序在矩阵 Ak和Ak+1之间将矩阵链断开,1≤k<n,则其相 应的完全加括号方式为(A1...Ak)(Ak+1…An)。 完全加括号是一个递归定义,可递归地计算A[1: k]和A[k+1:n] ,然后将计算结果相乘得到A[1: n]。 可设计如下递归算法recurmatrixChain:
算法设计与分析习题答案1-6章
习题1
1. 图论诞生于七桥问题。出生于瑞士
的伟大数学家欧拉(Leonhard
Euler ,1707—1783)提出并解决了该问题。七桥问题是这样描述的:一个人是否能在一次步行中穿越哥尼斯堡(现在叫加里宁格勒,在波罗的海南岸)城中全部的七座桥后回到起点,且每座桥只经过一次,图是这条河以及河上的两个岛和七座桥的草图。请将该问题的数据模型抽象出来,并判断此问题是否有解。
七桥问题属于一笔画问题。
输入:一个起点
输出:相同的点
1, 一次步行
2, 经过七座桥,且每次只经历过一次
3, 回到起点
该问题无解:能一笔画的图形只有两类:一类是所有的点都是偶点。另一类是只有二个奇点的图形。
图 七桥问题
南
2.在欧几里德提出的欧几里德算法中(即最初的欧几里德算法)用的不是除法而是减法。请用伪代码描述这个版本的欧几里德算法
=m-n
2.循环直到r=0
m=n
n=r
r=m-n
3 输出m
3.设计算法求数组中相差最小的两个元素(称为最接近数)的差。要求分别给出伪代码和C++描述。
编写程序,求n至少为多大时,n个“1”组成的整数能被2013整除。
#include
using namespace std;
int main()
{
double value=0;
for(int n=1;n<=10000 ;++n)
{
value=value*10+1;
if(value%2013==0)
{
cout<<"n至少为:"<
break;
}
}计算π值的问题能精确求解吗编写程序,求解满足给定精度要求的π值
#include
using namespace std;
终版算法设计与分析第三章课后答案吕国英主编.doc
2、#include
void main()
{
int a[6][6],b[6],i,j;
printf("请输入6个整数:");
for(i=0;i<6;i++)
{
scanf("%d",&b[i]);
}
for(i=0;i<6;i++)
{
a[0][i]=b[i];
}
for(i=1;i<=5;i++)
a[i][0]=b[6-i];
for(i=1;i<=5;i++)
for(j=1;j<=5;j++)
{
a[i][j]=a[i-1][j-1];
}
for(i=0;i<=5;i++)
{
for(j=0;j<=5;j++)
printf("%d ",a[i][j]);
printf("\n");
}
}
3、#include
void main()
{
int i,j,count,n;
int a[100][100];
printf("请输入矩阵的阶n=");
scanf("%d",&n);
count=1;
for(i=1;i<=n/2;i++)
{
for(j=i;j<=n-i+1;j++)//上侧
{
a[i][j]=count;
count++;
}
for(j=i+1;j<=n-i;j++)//右侧
{
a[j][n-i+1]=count;
count++;
}
for(j=n-i+1;j>=i+1;j--)//下侧
{
a[n-i+1][j]=count;
count++;
}
for(j=n-i+1;j>=i+1;j--)//左侧
{
a[j][i]=count;
count++;
}
}
if(n%2==1)
{
i=(n+1)/2;
a[i][i]=n*n;
}
for(i=1;i<=n;i++)
算法设计与分析_第3章_动态规划1
证明
26
步骤1:分析最优解的结构
最优子结构证明
Ai..j 的最优全括号中的 Ai..k 的全括号必 定是 Ai..k 的最优全括号
证明
最优全括号 Ai..j = (Ai…Ak) (Ak+1…Aj) = M·N , M =( Ai Ai+1… Ak ) . 若有一个更优 的完全加括号形式 Ai…Ak=P, 用 P 代替M, 则 P·N 将产生一个新的Ai..j加括号形式, 其计算量比M·N的计算量还小.产生矛盾. 同理,上述结论对Ak+1Ak+2…Aj也成立
27
步骤1:分析最优解的结构
基于最优子结构,可以从子问题的最优 解构造原问题的最优解 矩阵连乘问题的任何最优解必包含其子 问题的最优解
将问题分为两个子问题 (optimally parenthesizing AiAi+1… Ak and Ak+1Ak+2… Aj); 求子问题的最优解(find optimal solutions to subproblem); 合并子问题的最优解(combine these optimal subproblem solutions).
28
步骤1:分析最优解的结构
当寻找矩阵连乘分割点时,需要考虑所 有分割位置以确保最优解是其中之一
k在哪里?? 如何找??
29
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
for( j=0;j<=4;j=j+1)
{input(a[j]);
if(a[j]>=90)
s=s+1; }
42
if (n mod 2=1) {i=(n+1)/2; a[i][i]=n*n;}
for(i=1;i<=n;i=i+1) {print(“换行符”); for( j=1;j<=n;j=j+1) print(a[i][j]); }
}
43
于是一圈内下标的变化情况如下:
j=1 i=i+t 1----n i=n j=j+t 2----n 前半圈共2*k-1个
【例1】统计选票 【例2】统计身高 【例3】统计及格学生的名单 【例4】统计找数字对的出现频率
7
【例3】一次考试共考了语文、代数和外语三科。某小 组共有九人,考后各科及格名单如下表,请编写算法 找出三科全及格的学生的名单(学号)。
科目
及格学生学号
语文 代数 外语
1,9,6,8,4,3,7 5,2,9,1,3,7 8,1,6,7,3,5,4,9
35
2
3)用i代表行下标,以j代表列下标(除特别声明以后 都遵守此约定),则对n*n矩阵有以下常识:
主对角线元素i=j; 副对角线元素: 下标下界为1时 i+j=n+1,
下标下界为0时i+j=n-1; 主上三角◥元素: i <=j; 主下三角◣元素: i >=j; 次上三角◤元素:下标下界为1时i +j<=n+1,
• 问题提出: 有的问题会限定在现有数据中,每个数据只能被使用 一次,怎么样表示一个数据“使用过”还是没有“使 用过”? 一个朴素的想法是:用数组存储已使用过的数据,然 后每处理一个新数据就与前面的数据逐一比较看是否 重复。这样做,当数据量大时,判断工作的效率就会 越来越低。
23
例1
【例1】求X,使X2为一个各位数字互不相同的九位数 • 分析:只能用枚举法尝试完成此题。由X2为一个九
000000 000000 000000 000000
30
3.2.5 构造趣味矩阵
• 根据趣味矩阵中的数据规律,设计算法把要输出的数 据趣存味储矩到阵一经个常二用维二数维组数中组,来最解后决按行输出该数组中的 元素
• 基本常识: 1)当对二维表按行进行操作时,应该“外层循环控制行
;内层循环控制列”;反之若要对二维表按列进行操 作时,应该“外层循环控制列;内层循环控制行”。 2)二维表和二维数组的显示输出,只能按行从上到下连 续进行,每行各列则只能从左到右连续输出。所以, 只能用“外层循环控制行;内层循环控制列”。
39
i层内“摆放”数据的四个过程为(四角元素分别归四个边): 1) i列(左侧),从i行到n-i行
( n=4,i=1时 “摆放1,2,3”) 2) n+1-i行(下方),从i列到n-i列
( n=4,i=1时 “摆放4,5,6”) 3) n+1-i列(右侧),从n+1-i行到i+1行
( n=4,i=1时 “摆放7,8,9”) 4) i行(上方),从n+1-i列到i+1列
for(i=1;i<=n;i=i+1) {print( “换行符”);
for( j=1;j<=n;j=j+1) print(a[i][j]); }
}
38
• 【例2】螺旋阵:任意给定n值,按如下螺旋的方式输 出方阵: n=3 输出: 1 8 7 2 96 3 45 n=4 输出: 1 12 11 10 2 13 16 9 3 14 15 8 4 5 67
位数,估算X应在10000——32000之间。
24
3.2.4 大整数的存储及运算
• 计算机存储数据是按类型分配空间的。在微型机上 为整型提供2个字节16位的存储空间,则整型数据的 范围为-32768——32767;为长整型提供4个字节32位 的存储空间,则长整型数据的范围为-2147483648—— 2147483647;为实型也是提供4个字节32位的存储空 间,但不是精确存储数据,只有六位精度,数据的范 围±(3.4e-38~3.4e+38) ;为双精度型数据提供8个字节 64位的存储空间,数据的范围±(1.7e-308~1.7e+308) ,其精确位数是17位。
算法设计与分析
林玉娥 linyu_e@126.com
1
3.2 算法与数据结构
3.2.1 原始信息与处理结果的对应存储 3.2.2 数组使信息有序化 3.2.3 数组记录状态信息 3.2.4 大整数存储及运算 3.2.5 构造趣味矩阵
2
1、数据的存储结构
数据的存储结构可以分为:连续存储和链式存储。连续存 储又可以分为:静态存储和动态存储
12
3.2.2 数组使信息有序化
当题目中的数据缺乏规律时,很难把重复的工作抽象 成循环不变式来完成,但先用数组结构存储这些地信 息后,问题就迎刃而解了, • 【例1】编程将编号“翻译”成英文。例35706“翻 译”成three-five-seven-zero-six。
17
3.2.3 数组记录状态信息
• 若需从键盘输入要处理的高精度数据,一般用字符数 型组存储,这样无需对高精度数据进行分段输入。当 然这样存储后,需要有类型转换的操作,不同语言转 换的操作差别虽然较大,但都是利用数字字符的 ASCII码进行的。其它的技巧和注意事项通过下面的 例子来说明。本节只针对大 整数的计算进行讨论, 对高精度实数的计算可以仿照进行。
5
2)基于运算的考虑 在顺序表中按序号访问ai的时间性能时O(1),而链表中按 序号访问的时间性能O(n),所以如果经常做的运算是按序 号访问数据元素,显然顺序表优于链表;
3)基于环境的考虑 顺序表容易实现,任何高级语言中都有数组类型,链表的 操作是基于指针的,操作简单。
6
3.2.1 原始信息与处理结果对应存储
下标下界为0时i+j<=n-1; 次下三角◢元素:下标下界为1时i +j>=n+1,
下标下界为0时i+j>=n-1;
36
• 【例1】编程打印形如下规律的n*n方阵。
• 例如下图:使左对角线和右对角线上的元素为0,它们 上方的元素为1,左方的元素为2,下方元素为3,右方元 素为4,下图是一个符合条件的阶矩阵。
27
• 虽然现在工作站或小型机等机型上都有更高精度的数 值类型,但这些机型价格昂贵,只有大型科研机构才 有可能拥有,一般不易接触。当我们需要在个人机上 ,对超过长整型的多位数(简称为“高精度数据”) 操作时,只能借助于数组才能精确存储、计算。
28
• 在用数组存储高精度数据时,从计算的方便性考虑, 决定将数据是由低到高还是由高到低存储到数组中; 可以每位占一个数组元素空间,也可几位占一个数组 元素空间。
算法设计:
1)对每个同学,先计算其成绩高于90分的课程数目,若超过 3,则累加满足条件的人数中。
2)用二重循环实现以上过程,外层循环模拟50个同学,内层 循环模拟五门课程。
56
算法如下:
main( )
{int a[5],i,j,s,num=0;
for ( i=1;i<=50;i=i+1)
{s=0;
{if (i=j or i+j=n+1) a [i][j]=0;
if (i+j<n+1 and i<j) a [i][j]=1;
if (i+j<n+1 and i>j) a [i][j]=2;
if (i+j>n+1 and i>j) a [i][j]=3;
if (i+j>n+1 and i<j) a [i][j]=4;}
t= -t
k=k-1
j=n i=i+t n-1----1 i=1 j=j+t n-1----2 后半圈共2*k-1个
t= -t
用x模拟“摆放”的数据;用y(1——2*k-1)作循环变 量,模拟半圈内数据的处理的过程。
45
• 【例3】设计算法生成魔方阵.
• 魔方阵是我国古代发明的一种数字游戏:n阶魔方是 指这样一种方阵,它的每一行、每一列以及对角线上 的各数之和为一个常数,这个常数是:1/2*n*(n2+1) ,此常数被称为魔方阵常数。由于偶次阶魔方阵(n= 偶数)求解起来比较困难,我们这里只考虑n为奇数 的情况。
( n=4,i=1时 “摆放10,11,12”) 四个过程通过四个循环实现,用j表示i层内每边中行或列的下标
41
main( ) {int i,j,a[100][100],n,k; input(n); k=1; for(i=1;i<=n/2;i=i+1) {for( j=i;j<=n-i;j=j+1) { a [j][i]=k; k=k+1;} /左侧/ for( j=i;j<=n-i;j=j+1) {a [n+1-i][j]=k; k=k+1;} /下方/ for( j= n-i+1;j>=i+1;j=j-1){a[j][n+1-i]=k;k=k+1;} /右侧/ for( j= n-i+1;j>=i+1;j=j-1) {a[i][j]=k; k=k+1;} /上方/ }
以下就是一个n=3的魔方阵:
618
753
294
它的各行、各列及对角线上的元素之和为15。
49
for( i=1;i<=n;i=i+1) {print(“换行符”); for(j=1;j<=n;j=j+1)
print(a[i][j]); } }
• 说明:若当前位置已经填有数的话,则应填在上一个 数的下面,所以需要用变量记录上一个数据填入的位 置,算法中i1,j1的功能就是记录上一个数据填入的 位置。
2、连续存储和链式存储比较
顺序存储的优点: (1) 方法简单,各种高级语言中都提供数组结构,易实现。 (2) 不用为表示结点间的逻辑关系而增加额外的存储开销。 (3) 顺序表具有按元素序号随机访问的特点。
3
• 顺序存储的缺点:
(1) 在顺序表中做插入删除操作时,平均移动大约表中一 半的元素,因此对n较大的顺序表效率低。 (2) 需要预先分配足够大的存储空间,估计过大,可能 会导致顺序表后部大量闲置;预先分配过小,又会造成 溢出。
总之,通过恰当的算术运算可以很好地提高编程效率,以及 相关算法的运行效率。值得认真总结学习。
55
【例1】一次考试,共考了五门课。统计五十个学生中至 少有 三门课成绩高于90分的人数。 问题分析:若一个学生五门课的成绩分别记为:a1,a2,a3, a4,a5,则要表示有三门课成绩高于90分,有C35=10组关系 逻辑表达式,每组三个关系表达式。无论书写还是运行效率都 极低。但通过算法运算就能很简便地解决这类问题。
4
3、在选取存储结构时权衡因素有:
1)基于存储的考虑 顺序表的存储空间是静态分配的,在程序执行之前必须 明确规定它的存储规模,也就是说事先对“MAXSIZE” 要有合适的设定,过大造成浪费,过小造成溢出。可见 对线性表的长度或存储规模难以估计时,不宜采用顺序 表;链表不用事先估计存储规模,但链表的存储密度较 低,
0 1110 2 0104 2 2044 2 0304 0 3330
• 算法设计:根据数据分布的特点,利用以上关于二 维数组的基本常识,在只考虑可读性的情况下,
37
• 算法如下:
main( )
{int i,j,a[100][100],n;
input(n);
for(i=1;i<=n;i=i+1)
for(j=1;j<=n;j=j+1)
29
【例1】编程求当N<=100时,N!的准确值 • 问题分析:问题要求对输入的正整数N,计算N!的
准确值,而N!的增长速度仅次于指数增长的速度, 所以这是一个高精度计算问题。 例如:
9!=362880 100! = 93 326215 443944 152681 699263 856266 700490 715968 264381 621468 592963 895217 599993 229915 608914 463976 156578 286253 697920 827223 758251 185210 916864
• 分析:算法的时间复杂度为O(n2)。
53Βιβλιοθήκη Baidu
3.3 算法优化基本技巧 3.3.1 算术运算的妙用 3.3.2 标志量的妙用 3.3.3 信息数字化
54
3.3.1 算术运算的妙用
有关算术运算的妙用,在前面的许多例题中已有体现。如: 上一节3.2.1“原始信息与处理结果的巧妙对应”中的例2,通 过算术运算把数据信息归类后与下标对应。又如3.2.5“构造趣 味矩阵” 中例2的算法2 ,通过算术运算构造循环不变式。