算法分析与设计(第2版)递归与分治策略
算法设计与分析:递归与分治法-实验报告

应用数学学院信息安全专业班学号姓名实验题目递归与分治法综合实验评分表实验报告一、实验目的与要求1.掌握递归算法的设计思想2.掌握分治法设计算法的一般过程3.理解并掌握算法渐近时间复杂度的分析方法二、实验内容1、折半查找的递归算法(1)源程序代码#include <StdAfx.h>#include <iostream>using namespace std;int bin_search(int key[],int low, int high,int k){int mid;if(low>high)return -1;else{mid = (low+high) / 2;if(key[mid]==k)return mid;if(k>key[mid])return bin_search(key,mid+1,high,k);elsereturn bin_search(key,low,mid-1,k);}}int main(){int n , i , addr;int A[10] = {2,3,5,7,8,10,12,15,19,21};cout << "在下面的10个整数中进行查找" << endl;for(i=0;i<10;i++){cout << A[i] << " " ;}cout << endl << endl << "请输入一个要查找的整数" << endl;cin >> n;addr = bin_search(A,0,9,n);if(-1 != addr)cout << endl << n << "是上述整数中的第" << addr << "个数" << endl;elsecout << endl << n << "不在上述的整数中" << endl << endl;getchar();return 0;}(2)运行界面①查找成功②查找失败2、用分治法求x的n次方,要求时间复杂度为O(lgn)(1)源程序代码#include <StdAfx.h>#include <iostream>using namespace std;int Pow(int x, int n){if (n == 1)return x;else if (n > 1){int s;int m = n / 2;s = Pow (x, m);if (n % 2 == 0)return (s * s);elsereturn (s * s * x);}}int main(){int x, n;cout << "你将进行x的n次方计算" << endl << endl;cout << "请输入x:" << endl;cin >> x;cout << "请输入n:" << endl;cin >> n;cout << endl << "计算结果:" << Pow(x, n) << endl << endl;return 0;}(2)运行界面3、自然合并排序算法(1)源程序代码#include "StdAfx.h"#include <iostream>using namespace std;const int SIZE = 100;int arr[SIZE];int rec[SIZE];void merge(int fir,int end,int mid);int pass(int n);void mergeSort(int n);void mergeSort(int n){int num=pass(n);while(num!=2){for(int i=0;i<num;i+=2)merge(rec[i],rec[i+2]-1,rec[i+1]-1);num=pass(n);}}void merge(int fir,int end,int mid){int tempArr[SIZE];int fir1=fir,fir2=mid+1;for(int i=fir;i<=end;i++){if(fir1>mid)tempArr[i]=arr[fir2++];else if(fir2>end)tempArr[i]=arr[fir1++];else if(arr[fir1]>arr[fir2])tempArr[i]=arr[fir2++];elsetempArr[i]=arr[fir1++];}for(int i=fir;i<=end;i++)arr[i]=tempArr[i];}int pass(int n){int num=0;int biger=arr[0];rec[num++]=0;for(int i=1;i<n;i++){if(arr[i]>=biger)biger=arr[i];else {rec[num++]=i;biger=arr[i];}}rec[num++]=n;return num;}int main(){int n;cout<<"请输入需要排序的整数个数:"<<endl;while(cin>>n){for(int i=0;i<n;i++){cout<<"请输入整数:"<<endl;cin>>arr[i];}mergeSort(n);cout<<"排序结果为:"<<endl;for(int i=0;i<n;i++){cout<<arr[i]<<" ";}cout<<endl<<endl;cout<<"请输入需要排序的整数个数:"<<endl;}return 0;}(2)运行界面三、问题与讨论问题:分治法能解决的问题一般具有什么特征?解答:任何一个可以用计算机求解的问题所需的计算时间都与其规模有关。
算法之2章递归与分治

算法分析(第二章):递归与分治法一、递归的概念知识再现:等比数列求和公式:1、定义:直接或间接地调用自身的算法称为递归算法。
用函数自身给出定义的函数称为递归函数。
2、与分治法的关系:由分治法产生的子问题往往是原问题的较小模式,这就为使用递归技术提供了方便。
在这种情况下,反复应用分治手段,可以使子问题与原问题类型一致而其规模却不断缩小,最终使子问题缩小到很容易直接求出其解。
这自然导致递归过程的产生。
分治与递归经常同时应用在算法设计之中,并由此产生许多高效算法。
3、递推方程:(1)定义:设序列01,....na a a简记为{na},把n a与某些个()ia i n<联系起来的等式叫做关于该序列的递推方程。
(2)求解:给定关于序列{n a}的递推方程和若干初值,计算n a。
4、应用:阶乘函数、Fibonacci数列、Hanoi塔问题、插入排序5、优缺点:优点:结构清晰,可读性强,而且容易用数学归纳法来证明算法的正确性,因此它为设计算法、调试程序带来很大方便。
缺点:递归算法的运行效率较低,无论是耗费的计算时间还是占用的存储空间都比非递归算法要多。
二、递归算法改进:1、迭代法:(1)不断用递推方程的右部替代左部(2)每一次替换,随着n的降低在和式中多出一项(3)直到出现初值以后停止迭代(4)将初值代入并对和式求和(5)可用数学归纳法验证解的正确性2、举例:-----------Hanoi塔算法----------- ---------------插入排序算法----------- ()2(1)1(1)1T n T nT=−+=()(1)1W n W n nW=−+−(1)=021n-23()2(1)12[2(2)1]12(2)21...2++2 (121)n n n T n T n T n T n T −−=−+=−++=−++==++=−(1)2 ()(1)1((n-2)+11)1(2)(2)(1)...(1)12...(2)(1)(1)/2W n W n n W n n W n n n W n n n n =−+−=−−+−=−+−+−==++++−+−=−3、换元迭代:(1)将对n 的递推式换成对其他变元k 的递推式 (2)对k 进行迭代(3)将解(关于k 的函数)转换成关于n 的函数4、举例:---------------二分归并排序---------------()2(/2)1W n W n n W =+−(1)=0(1)换元:假设2kn =,递推方程如下()2(/2)1W n W n n W =+−(1)=0 → 1(2)2(2)21k k k W W W−=+−(0)=0(2)迭代求解:12122222321332133212()2(2)212(2(2)21)212(2)22212(2)2*2212(2(2)21)2212(2)222212(2)3*2221...2(0)*2(22...21)22k k k k k k k k k k k k k k k k k k k k k k k k W n W W W W W W W W k k −−−−−−−+−+−−−=+−=+−+−=+−+−=+−−=+−+−−=+−+−−=+−−−==+−++++=−1log 1n n n +=−+(3)解的正确性—归纳验证: 证明递推方程的解是()(1)/2W n n n =−()(1)1W n W n n W =−+−(1)=0,(n 1)=n +n=n(n-1)/2+n =n[(n-1)/2+1]=n(n+1)/2n W W +方法:数学归纳法证 n=1,W(1)=1*(1-1)/2=0假设对于解满足方程,则()---------------快速排序--------------------->>>平均工作量:假设首元素排好序在每个位置是等概率的112()()()(1)0n i T n T i O n n T −==+=∑ >>>对于高阶方程应该先化简,然后迭代(1)差消化简:利用两个方程相减,将右边的项尽可能消去,以达到降阶的目的。
算法设计与分析(霍红卫)-第2章-分治法

MOVE(X, 4, Z) HANOI(3, Y, X, Z)
HANOI(2, Y, Z, X) HANOI(1, Y, X, Z) MOVE(Y, 1, Z) MOVE(Y, 2, X) HANOI(1, Z, Y, X) MOVE(Z, 1, X) MOVE(Y, 3, Z)
HANOI(2, X, Y, Z) HANOI(1, X, Z, Y) MOVE(X, 1, Y) MOVE(X, 2, Z) HANOI(1, Y, X, Z) MOVE(Y, 1, Z)
n log43
(d)
图 2-4 递归树的构造过程
第2章 分 治 法
现在,我们确定树中每一层的开销。每一层的结点数是上 一层结点数的两倍,因此,第i层的结点数为3i。由于每一层子 问题规模为上一层的 1/4,由根向下,深度为i(i=0,1,…, log4n-1) 的每个结点的开销为c(n/4i)2,那么第i层上结点的总开 销为
3
cn2
3
2
cn2
3
log4
n1
cn2
Θ(nlog4
3)
16 16
16
log4
n1
3
i
cn2
Θ(nlog4 3)
i0 16
3
i
cn2
Θ(nlog4 3 )
i0 16
1 cn2 Θ(nlog4 3) 1 3/16
16 cn2 Θ(nlog4 3)] 13
O(n2)
(n= )
-
图 2 3 汉 诺 塔 的 执 行 过 程
4
第2章 分 治 法 汉诺塔算法的时间复杂度为指数级的复杂度。以下做一简 要证明。假设汉诺塔算法的时间复杂度为T(n),由递归算法可
算法设计与分析第2章

计算F(n-1)所需 乘法次数 计算F(n-1) ×n所需 乘法次数
初始条件(initial condition):停止递归调用的条件 T(0) = 0
• Conquer: 一个划分确定后,A[s]的位置便确定,再 对两个子数组递归地划分 • Combine: 原地排序in-place sort,无需合并
Quicksort(A[l…r]) if l < r s = Partition(A[l…r]) Quicksort(A[l…s-1]) Quicksort(A[s+1…r]) Partition(A[l…r]) p = A[l] //选择第一个元素作为划分基准 i = l; j = r + 1 repeat repeat i = i + 1 until A[i] ≥ p //left-to-right scan repeat j = j - 1 until A[j] ≤ p //right-to-left scan swap(A[i], A[j]) until i ≥ j swap(A[i], A[j]) //undo last swap when i ≥ j swap(A[l], A[j]) return j
二分搜索(Binary Search)
• 给定已按升序排好序的n个元素A[0…n-1],现要在 这n个元素中找出一特定元素k。
– 蛮力算法:遍历、 Tworst(n) =O(n) – 分治法是否适用?
• • • •
算法设计与分析耿国华第二章

Chapter
Hale Waihona Puke 22.4.1替换方法
例2.6 汉诺塔算法(见例2.5)的时间复杂 度分析。 假设汉诺塔算法的时间复杂度为T(n),例 2.5的算法递归方程为:
n 1 1 T ( n) 2T (n 1) 1 n 1
Chapter
2
2.4.1替换方法
利用替换法求解该方程:
T (n) 2T (n 1) 1
2
2.2具有递归特性的问题
• (2)递归定义的数据结构
在数据结构中,如广义表、二叉树、树等结构 其本身均具有固有的递归特性,可以自然地采 用递归法进行处理。 (3)递归求解方法 许多问题的求解过程可以用递归分解的方法描 述,例如:计算两非负整数最大公约数的欧几 里得算法和著名的汉诺塔问题(Hanoi)问题。
T (n) O(2n )
得到该算法的时间复杂度
Chapter
2
2.4.1替换方法
例2.7 2-路归并排序的递归算法分析。 假设初始序列含有n个记录,首先将这n个记 录看成n个有序的子序列,每个子序列的长度为1, 然后两两归并,得到 n / 2个长度为2(n为奇数 时,最后一个序列的长度为1)的有序子序列; 在此基础上,再对长度为2的有序子序列进行两 两归并,得到若干个长度为4的有序子序列;如 此重复,直至得到一个长度为n的有序序列为止。 这种方法被称作2-路归并排序。
F(6) F(5) F(4) F(3) F(2) F(1) F(0) F(1) F(1) F(2) F(3) F(2) F(1) F(2) F(1) F(0) F(3) F(1) F(1) F(4) F(2) F(0)
F(0) F(1) F(0)
图2-1 斐波那契算法的递归结构(n=6)
算法设计与分析实验指导1_分治与递归

《算法设计与分析》实验指导实验一分治与递归一、实验目的:1. 理解递归的概念。
2. 掌握设计有效算法的分治策略。
3. 掌握C++面向对象编程方法。
二、实验指导1. 分治法的总体思想求解一个复杂问题可以将其分解成若干个子问题,子问题还可以进一步分解成更小的问题,直到分解所得的小问题是一些基本问题,并且其求解方法是已知的,可以直接求解为止。
分治法作为一种算法设计策略,要求分解所得的子问题是同类问题,并要求原问题的解可以通过组合子问题的解来获取。
分治与递归像一对孪生兄弟,经常同时应用在算法设计之中,并由此产生许多高效的算法。
2. 分治法的基本步骤divide-and-conquer(P){if ( | P | <= n0) adhoc(P); //解决小规模的问题divide P into smaller subinstances P1,P2,...,Pk;//分解问题for (i=1,i<=k,i++)yi=divide-and-conquer(Pi); //递归的解各子问题return merge(y1,...,yk); //将各子问题的解合并为原问题的解}3. C++类定义例class Complex{public:Complex( ):real(0),imag(0) {} //构造函数Complex(double r,double i):real(r),imag(i) {} //构造函数Complex operator + (Complex c2); //重载“+”运算符operator double( ) //重载类型转换运算符{return real;}friend ostream& operator << (ostream&,Complex&); //重载流插入运算符“<<”private:double real;double imag;};三、实验内容及要求:在程序中创建一个学生对象数组并初始化数据,完成如下编程任务。
算法分析与设计实验一递归与分治策略

实验一递归与分治策略实验目的1.了解并掌握递归的概念,递归算法的基本思想;2.掌握分治法的基本思想方法;3.了解适用于用分治法求解的问题类型,并能用递归或非递归的方式设计相应的分治法算法;4.掌握分治法复杂性分析方法,比较同一个问题的递归算法与循环迭代算法的效率。
预习与实验要求1.预习实验指导书及教材的有关内容,掌握分治法的基本思想;2.严格按照实验内容进行实验,培养良好的算法设计和编程的习惯;3.认真听讲,服从安排,独立思考并完成实验。
实验原理简单说来,当一个函数用它自己来定义时就称为递归。
一般来说,递归需要有边界条件、递归前进段和递归返回段。
当边界条件不满足时,递归前进;当边界条件满足时,递归返回。
因此,在考虑使用递归算法编写程序时,应满足两点:1)该问题能够被递归形式描述;2)存在递归结束的边界条件。
递归的能力在于用有限的语句来定义对象的无限集合。
用递归思想写出的程序往往十分简洁易懂。
一般说来,一个递归算法可以转换称为一个与之等效的非递归算法,但转换后的非递归算法代码将成倍地增加。
分治是一种被广泛应用的有效方法,它的基本思想是把最初的问题分解成若干子问题,然后在逐个解决各个子问题的基础上得到原始问题的解。
所谓分治就是“分而治之”的意思。
由于分解出的每个子问题总是要比最初的问题容易些,因而分治策略往往能够降低原始问题的难度,或者提高解决原始问题的效率。
根据如何由分解出的子问题求出原始问题的解,分治策略又可分为两种情形:第一,原始问题的解只存在于分解出的某一个子问题中,则只需要在原始问题的一个划分中求解即可;第二,原始问题的解需要由各个子问题的解再经过综合处理得到。
无论是哪一种情况,分治策略可以较快地缩小问题的求解范围,从而加快问题求解的速度。
分治策略运用于计算机算法是,往往会出现分解出来的子问题与原始问题类型相同的现象,而与原问题相比,各个子问题的规模变小了,这刚好符合递归的特征。
因此分治策略往往是和递归联系在一起的。
算法设计与分析——浅谈递归思想与分治策略

(1) 若只有一个盘子,直接从柱子A移动到柱子C (2) 若有两个盘子,先将最上面一个盘子移动到B,再将底下的盘子移动 到C,再将B上的盘子移动到C (3) 若有三个盘子,先借助C将A最上面的两个盘子移动到B,将最大的盘 子移动到C,此时A为空,再借助A将B最上面的一个盘子移动到A,将B 剩余的一个盘子移动到C,再将A上的盘子移动到C …………… 以此类推,假设A上有n个盘子,先借助C将A上n-1个盘子移动到B,再 将第n个盘子移动到C,再借助A盘将B上的n-1个盘子移动到C. 由此可见,此中不断重复一个借助某个柱子将另外一个柱子上的最下面 的盘子移动到第三个柱子上的过程.
算法设计与分析——初章
结束了… 主要内容: 1. 算法的时间复杂度 2. 递归思想
递归定义 直接递归调用与间接递归调用 递归应用 递归算法举例---Hanoi
3.分治策略
分治策略描述 二分法(二分查找,二分插入) 快速排序 归并排序
�
{2,4,5,7 }
{1,2,3,6}
{1,2,2,3,4,5,6,7}
分治策略
归并排序
在上述序列中,将整个序列从中间分成两个子序列,{5,2, 4,7 }和{1,3,2,6},然后将两个子序列按照相同的规则继续划 分直至不能再分为止, {5}{2}{4}{7}{1} {3}{2}{6},然后将不能再分 的子序列排序,对相邻的两个子序列进行归并操作,归并的规则 是: (1)取出相邻两个子序列中最小的数相比较,将两个数添加到归 并后的序列中. (2)对两个子序列中剩余的元素重复(1)操作. (3)当某个子序列为空后,将另一个子序列中的元素直接添加到 序列末尾. (4)重复(1)操作.
递归思想
汉诺塔问题
Hanoi有四个参数,第一个参数表示盘子的数目,第二个参数表示源柱 子,第三个参数表示要借助的柱子,第四个参数表示目标柱子. if(n==1) move(chA, chC) else { Hanoi(chA, chC, chB);//借助C将A上除了最下面一个移动到B move(chA, chC) Hanoi(chB, chA, chC);//借助A将B上面的移动到C }
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
递归小结
• 优点:结构清晰,可读性强,而且容易 用数学归纳法来证明算法的正确性,因 此它为设计算法、调试程序带来很大方 便。
• 缺点:递归算法的运行效率较低,无论 是耗费的计算时间还是占用的存储空间 都比非递归算法要多。
关于递归算法 必须进一步思考和研究的问题:
递归的消除
即递归算法到非递归算法的转化
要点:子问题的平衡性!
O(1) n=n0 n>n0
T(n)=
kT(n/m)+f(n)
分治法所能解决的问题一般具有以下几个特征: 该问题的规模缩小到一定的程度就可以容易地解决; 该问题可以分解为若干个规模较小的相同问题,即该 问题具有最优子结构性质利用该问题分解出的子问题的解 可以合并为该问题的解; 该问题所分解出的各个子问题是相互独立的,即子问 题之间不包含公共的子问题。
T(n)
=
n
T(n/k)
T(n/k)
T(n/k)
T(n/k)
对这k个子问题分别求解。如果子问题的规模仍然不够小, 则再划分为k个子问题,如此递归的进行下去,直到问题规模足 够小,很容易求出其解为止。
T(n)
n/2
=
n/2
n
n/2 n/2
T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4)
这条特征涉及到分治法的效率,如果各子问题是不独立的, 则分治法要做许多不必要的工作,重复地解公共的子问题, 此时虽然也可用分治法,但一般用动态规划较好。
2.3 二分搜索技术
给定已按升序排好序的n个元素a[0:n-1],现要在这n个元素中 找出一特定元素x。 分析:
该问题的规模缩小到一定的程度就可以容易地解决; 该问题可以分解为若干个规模较小的相同问题; 分解出的子问题的解可以合并为原问题的解; 分解出的各个子问题是相互独立的。
例2.4 排列问题
设R={r1,r2,…,rn}是要进行排列的n个元素,R的全排 列记为perm(R),Ri=R-{ri},(ri)perm(Ri)表示集合Ri的全 排列中每个排列前增加一个前缀所形成的所有排列。于是 当n=1时,perm(R)=(r),其中r是R中的唯一元素; 当n>1时,perm(R)由(r1)perm(R1), (r2)perm(R2),…, (rn)perm(Rn)构成。 显然, O(1) n=1 T(n)= nT(n-1)+O(n) n>1
将求出的小规模的问题的解合并为一个更大规模的问题的解, 自底向上逐步求出原来问题的解。
分治法的设计思想是,将一个难以直接解决的大问题, 分割成一些规模较小的相同问题,以便各个击破, 分而治之。 凡治众如治寡,分数是也。 ----孙子兵法
2.1 递归的概念
递归算法: 直接或者间接调用自身的算法。 递归算法实现过程中的堆栈问题及其对算法复杂性的 影响。 例2.1 阶乘函数
问题核心: 子问题的重复计算
public static int fibonacci(int n) 1 n=0 { if(n<=1) return 1; else return fibonacci(n-1)+fibonacci(n-2); n! = n(n-1)! n>0 } public static int factorial(int n) { if(n==0) return 1; else return n*factorial(n-1); } 例2.2 Fibonacci数列 1 n=0,1
public static int q(int n,int m) { if(n<1||m<1) return 0; else if(n==1||m==1) return 1; else if(n<m) return q(n,n); else if(n==m) return q(n,m-1)+1; else return q(n,m-1)+q(n-m,m); } 关于正整数划分问题的再思考
2 2 4 1 1 4 3 3 1 1 4 3
1 1 1 4 4 1 1 1 3 3 3 4
算法的思想: 1. 给排列中的每个元素均赋予 一个向左或向右的箭头。 2. 如果元素k的箭头指向的是与 其相邻但小于k的元素,则称元 素k是活动的。 3. 从排列 1 2 3 … n 开始,找 其中的最大活动元素k,将该元 素k与它所指向的相邻元素交换 位置,并改变所有大于k的元素 的方向。
第2章 递归与分治策略
递归和分治的思想方法: 将一个难以解决的规模较大的问题,分割成一些规 模较小的求解思路一致的子问题,以便各个击破,分而 治之。如果原问题可以分割成k个子问题,1<k≤n,并 且这些子问题都是可解的,同时可以利用这些子问题的 解求出原问题的解,那么这种分治便是可行的。 递归函数论:作为一种计算模型,它的计算能力等 价于Turing机。
1 2 3 4
2 1 3 4
例2.5 正整数的划分问题 对于正整数n,若存在正整数n1,n2,…,nk,使得 n= n1+n2+…+nk 则称n1,n2,…,nk是n的一个划分。正整数n的不同划分数称 为n的划分数,记为p(n)。 在正整数n的不同划分中,将最大加数不大于m的划分 个数记作q(n,m),则 1 n=1,m=1 q(n,n) n<m q(n,m)= 1+q(n,n-1) n=m q(n,m-1)+q(n-m,m) n>m>1
分析:很显然此问题分解出的子问题相互独立,即在a[i]的前面 或后面查找x是独立的子问题,因此满足分治法的第四个适用条 件。
public static int binarysearch(int []a,int x,int n) { int left=0; int right=n-1; while(left<=right) { int middle=(left+right)/2; if(x==a[middle]) return middle; else if(x<a[middle]) right=middle-1; else left=middle+1; } return -1; } 思考题:给定a,用二分法设计出求an的算法。
2.2 分治法的基本思想
将一个难以解决的规模为n的问题分解成k个规模较小 的子问题,这些子问题是相互独立的,并且与原问题具有 相同的性质。递归地解这些子问题,然后将这些子问题的 解合并得到原问题的解。 假设需要解决的原问题是P,其规模是|P|=n,则用分 治法解决问题P的算法结构是: divide_and_conquer(P) { if(n<=n0) adhoc(P); else { divide P into smaller subinstances P1,P2,…,Pk; for(i=1;i<=k;i++) yi=divide_and_conquer(Pi); return merge(y1,y2,…,yk); } }
0 list
前缀
k
i
m
public static void perm(Objict []list, int k, int m) { if(k==m) { for(i=0; i<=m; i++) System.out.print(list[i]); System.out.println(); } else for(i=k; i<=m; i++) { MyMath.swap(list,k,i); perm(list,k+1,m); MyMath.swap(list,k,i); } }
• • • • • • • • • • • •
表示6=3+1+1+1和6=4+1+1
表示6=3+2+1
• • • • • •
设n=6,则p(6)=11
• • • • • •
表示6=3+3和6=2+2+2
• • • • • •
表示6=1+1+1+1+1+1和6=6
• • • • • •
表示6=2+1+1+1+1和6=5+1
F(n) =
F(n-1)+F(n-2) n>1
2 n=1,m=0 例2.3 Ackerman函数 1 n=0,m≥0 A(n,m) = n+2 n≥2,m=0 问题核心: A(A(n-1,m),m-1) n,m>1 子问题的重复计算
public static long ackerman(int n,int m) { if(n=1&&m==0) return 2; else if(n==0&&m>=0) return 1; else if(n>=2&&m==0) return n+2; else return ackerman(ackerman(n-1,m),m-1); }
要点:字典中的元素按照查找关键子有序。
通过一次比较排除字典中的一半元素,从而使得 算法的时间复杂度为O(logn)。
2.4 大整数的乘法
首先以二进制数的乘法为例说明计算机中实现乘法的 算法的思想方法。假设被乘数是10110,乘数是01101。
10110 乘数 01101 积 0000000000 被乘数10110 × 01101 0101100000 (1加右移) 10110 0010110000 (0右移) 00000 0110111000 (1加右移) 10110 1000111100 (1加右移) 10110 0100011110 (0右移) + 00000 积100011110 算法的思想:初始化积为全0;由低向高取 乘数的每一位;当乘数的当前位是1时,将 该算法的 被乘数加在积的高位部分,然后右移积一 时间复杂度是 位;否则只右移积一位;直到取完了乘数的 O(n*n) 所有位。