算法设计与分析(作业一)

合集下载

《计算机算法设计和分析》习题及答案解析

《计算机算法设计和分析》习题及答案解析

《计算机算法设计与分析》习题及答案一.选择题1、二分搜索算法是利用( A )实现的算法。

A、分治策略B、动态规划法C、贪心法D、回溯法2、下列不是动态规划算法基本步骤的是( A )。

A、找出最优解的性质B、构造最优解C、算出最优解D、定义最优解3、最大效益优先是( A )的一搜索方式。

A、分支界限法B、动态规划法C、贪心法D、回溯法4. 回溯法解旅行售货员问题时的解空间树是( A )。

A、子集树B、排列树C、深度优先生成树D、广度优先生成树5.下列算法中通常以自底向上的方式求解最优解的是( B )。

A、备忘录法B、动态规划法C、贪心法D、回溯法6、衡量一个算法好坏的标准是( C )。

A 运行速度快B 占用空间少C 时间复杂度低D 代码短7、以下不可以使用分治法求解的是( D )。

A 棋盘覆盖问题B 选择问题C 归并排序D 0/1背包问题8. 实现循环赛日程表利用的算法是( A )。

A、分治策略B、动态规划法C、贪心法D、回溯法9.下面不是分支界限法搜索方式的是( D )。

A、广度优先B、最小耗费优先C、最大效益优先D、深度优先10.下列算法中通常以深度优先方式系统搜索问题解的是( D )。

A、备忘录法B、动态规划法C、贪心法D、回溯法11.备忘录方法是那种算法的变形。

( B )A、分治法B、动态规划法C、贪心法D、回溯法12.哈夫曼编码的贪心算法所需的计算时间为( B )。

A、O(n2n)B、O(nlogn)C、O(2n)D、O(n)13.分支限界法解最大团问题时,活结点表的组织形式是( B )。

A、最小堆B、最大堆C、栈D、数组14.最长公共子序列算法利用的算法是( B )。

A、分支界限法B、动态规划法C、贪心法D、回溯法15.实现棋盘覆盖算法利用的算法是( A )。

A、分治法B、动态规划法C、贪心法D、回溯法16.下面是贪心算法的基本要素的是( C )。

A、重叠子问题B、构造最优解C、贪心选择性质D、定义最优解17.回溯法的效率不依赖于下列哪些因素( D )A.满足显约束的值的个数B. 计算约束函数的时间C.计算限界函数的时间D. 确定解空间的时间18.下面哪种函数是回溯法中为避免无效搜索采取的策略( B )A.递归函数 B.剪枝函数 C。

算法设计与分析习题答案

算法设计与分析习题答案

算法设计与分析习题答案算法设计与分析是计算机科学中一个重要的领域,它涉及到算法的创建、优化以及评估。

以下是一些典型的算法设计与分析习题及其答案。

习题1:二分查找算法问题描述:给定一个已排序的整数数组,编写一个函数来查找一个目标值是否存在于数组中。

答案:二分查找算法的基本思想是将数组分成两半,比较中间元素与目标值的大小,如果目标值等于中间元素,则查找成功;如果目标值小于中间元素,则在左半部分继续查找;如果目标值大于中间元素,则在右半部分继续查找。

这个过程会不断重复,直到找到目标值或搜索范围为空。

```pythondef binary_search(arr, target):low, high = 0, len(arr) - 1while low <= high:mid = (low + high) // 2if arr[mid] == target:return Trueelif arr[mid] < target:low = mid + 1else:high = mid - 1return False```习题2:归并排序算法问题描述:给定一个无序数组,使用归并排序算法对其进行排序。

答案:归并排序是一种分治算法,它将数组分成两半,分别对这两半进行排序,然后将排序好的两半合并成一个有序数组。

```pythondef merge_sort(arr):if len(arr) > 1:mid = len(arr) // 2left_half = arr[:mid]right_half = arr[mid:]merge_sort(left_half)merge_sort(right_half)i = j = k = 0while i < len(left_half) and j < len(right_half): if left_half[i] < right_half[j]:arr[k] = left_half[i]i += 1else:arr[k] = right_half[j]j += 1k += 1while i < len(left_half):arr[k] = left_half[i]i += 1k += 1while j < len(right_half):arr[k] = right_half[j]j += 1k += 1arr = [38, 27, 43, 3, 9, 82, 10]merge_sort(arr)print("Sorted array is:", arr)```习题3:动态规划求解最长公共子序列问题问题描述:给定两个序列,找到它们的最长公共子序列。

算法分析与设计作业参考答案

算法分析与设计作业参考答案

算法分析与设计作业参考答案《算法分析与设计》作业参考答案作业⼀⼀、名词解释:1.递归算法:直接或间接地调⽤⾃⾝的算法称为递归算法。

2.程序:程序是算法⽤某种程序设计语⾔的具体实现。

⼆、简答题:1.算法需要满⾜哪些性质?简述之。

答:算法是若⼲指令的有穷序列,满⾜性质:(1)输⼊:有零个或多个外部量作为算法的输⼊。

(2)输出:算法产⽣⾄少⼀个量作为输出。

(3)确定性:组成算法的每条指令清晰、⽆歧义。

(4)有限性:算法中每条指令的执⾏次数有限,执⾏每条指令的时间也有限。

2.简要分析分治法能解决的问题具有的特征。

答:分析分治法能解决的问题主要具有如下特征:(1)该问题的规模缩⼩到⼀定的程度就可以容易地解决;(2)该问题可以分解为若⼲个规模较⼩的相同问题,即该问题具有最优⼦结构性质;(3)利⽤该问题分解出的⼦问题的解可以合并为该问题的解;(4)该问题所分解出的各个⼦问题是相互独⽴的,即⼦问题之间不包含公共的⼦问题。

3.简要分析在递归算法中消除递归调⽤,将递归算法转化为⾮递归算法的⽅法。

答:将递归算法转化为⾮递归算法的⽅法主要有:(1)采⽤⼀个⽤户定义的栈来模拟系统的递归调⽤⼯作栈。

该⽅法通⽤性强,但本质上还是递归,只不过⼈⼯做了本来由编译器做的事情,优化效果不明显。

(2)⽤递推来实现递归函数。

(3)通过Cooper 变换、反演变换能将⼀些递归转化为尾递归,从⽽迭代求出结果。

后两种⽅法在时空复杂度上均有较⼤改善,但其适⽤范围有限。

三、算法编写及算法应⽤分析题: 1.冒泡排序算法的基本运算如下: for i ←1 to n-1 dofor j ←1 to n-i do if a[j]交换a[j]、a[j+1];分析该算法的时间复杂性。

答:排序算法的基本运算步为元素⽐较,冒泡排序算法的时间复杂性就是求⽐较次数与n 的关系。

(1)设⽐较⼀次花时间1;(2)内循环次数为:n-i 次,(i=1,…n ),花时间为:∑-=-=in j i n 1)(1(3)外循环次数为:n-1,花时间为:2.设计⼀个分治算法计算⼀棵⼆叉树的⾼度。

《算法设计与分析》实验报告实验一...

《算法设计与分析》实验报告实验一...

《算法设计与分析》实验报告实验一递归与分治策略应用基础学号:**************姓名:*************班级:*************日期:2014-2015学年第1学期第九周一、实验目的1、理解递归的概念和分治法的基本思想2、了解适用递归与分治策略的问题类型,并能设计相应的分治策略算法3、掌握递归与分治算法时间空间复杂度分析,以及问题复杂性分析方法二、实验内容任务:以下题目要求应用递归与分治策略设计解决方案,本次实验成绩按百分制计,完成各小题的得分如下,每小题要求算法描述准确且程序运行正确。

1、求n个元素的全排。

(30分)2、解决一个2k*2k的特殊棋牌上的L型骨牌覆盖问题。

(30分)3、设有n=2k个运动员要进行网球循环赛。

设计一个满足要求的比赛日程表。

(40分)提交结果:算法设计分析思路、源代码及其分析说明和测试运行报告。

三、设计分析四、算法描述及程序五、测试与分析六、实验总结与体会#include "iostream"using namespace std;#define N 100void Perm(int* list, int k, int m){if (k == m){for (int i=0; i<m; i++)cout << list[i] << " ";cout << endl;return;}else{for (int i=m; i<k; i++){swap(list[m], list[i]);Perm(list, k, m+1);swap(list[m], list[i]);}}}void swap(int a,int b){int temp;temp=a;a=b;b=temp;}int main(){int i,n;int a[N];cout<<"请输入排列数据总个数:";cin>>n;cout<<"请输入数据:";for(i=0;i<n;i++){cin>>a[i];}cout<<"该数据的全排列:"<<endl;Perm(a,n,0);return 0;}《算法设计与分析》实验报告实验二递归与分治策略应用提高学号:**************姓名:*************班级:*************日期:2014-2015学年第1学期一、实验目的1、深入理解递归的概念和分治法的基本思想2、正确使用递归与分治策略设计相应的问题的算法3、掌握递归与分治算法时间空间复杂度分析,以及问题复杂性分析方法二、实验内容任务:从以下题目中任选一题完成,要求应用递归与分治策略设计解决方案。

算法设计与分析试卷及答案

算法设计与分析试卷及答案

算法设计与分析1、(1) 证明:O(f)+O(g)=O(f+g)(7分)(2) 求下列函数的渐近表达式:(6分)① 3n 2+10n;② 21+1/n;2、对于下列各组函数f(n)和g(n),确定f(n)=O(g(n))或f(n)=Ω(g(n))或f(n)=θ(g(n)),并简述理由。

(15分)(1);5log )(;log )(2+==n n g n n f (2);)(;log )(2n n g n n f == (3);log )(;)(2n n g n n f == 3、试用分治法对数组A[n]实现快速排序。

(13分)4、试用动态规划算法实现最长公共子序列问题。

(15分)5、试用贪心算法求解汽车加油问题:已知一辆汽车加满油后可行驶n 公里,而旅途中有若干个加油站。

试设计一个有效算法,指出应在哪些加油站停靠加油,使加油次数最少。

(12分)6、试用动态规划算法实现下列问题:设A 和B 是两个字符串。

我们要用最少的字符操作,将字符串A 转换为字符串B ,这里所说的字符操作包括:(1)删除一个字符。

(2)插入一个字符。

(3)将一个字符改为另一个字符。

将字符串A 变换为字符串B 所用的最少字符操作数称为字符串A 到B 的编辑距离,记为d(A,B)。

试设计一个有效算法,对任给的两个字符串A 和B ,计算出它们的编辑距离d(A,B)。

(16分)⎣⎦2/)(;3)(i i g i i f ==。

对于给定的两个整数n 和m ,要求用最少的变换f 和g 变换次数将n 变为m 。

(16分)1、⑴证明:令F(n)=O(f),则存在自然数n 1、c 1,使得对任意的自然数n ≥n 1,有:F(n)≤c 1f(n)……………………………..(2分)同理可令G(n)=O(g),则存在自然数n 2、c 2,使得对任意的自然数n ≥n 2,有:G(n)≤c 2g(n)……………………………..(3分)令c 3=max{c 1,c 2},n 3=max{n 1,n 2},则对所有的n ≥n 3,有: F(n)≤c 1f(n)≤c 3f(n)G(n)≤c 2g(n)≤c 3g(n)……………………………..(5分) 故有:O(f)+O(g)=F(n)+G(n)≤c 3f(n)+c 3g(n)=c 3(f(n)+g(n)) 因此有:O(f)+O(g)=O(f+g)……………………………..(7分) ⑵ 解:① 因为;01033)103(lim 222=+-+∞→n n n n n n 由渐近表达式的定义易知: 3n 2是3n 2+10n 的渐近表达式。

算法设计与分析王晓东

算法设计与分析王晓东

习题2-1 求下列函数的渐进表达式:3n^2+10n; n^2/10+2n; 21+1/n; logn^3; 10 log3^n 。

解答:3n^2+10n=O(n^2),n^2/10+2^n=O(2^n),21+1/n=O(1),logn^3=O(logn),10log3^n=O(n).习题2-3 照渐进阶从低到高的顺序排列以下表达式:n!,4n^2,logn,3^n,20n,2,n^2/3。

解答:照渐进阶从高到低的顺序为:n!、3^n、4n^2 、20n、n^2/3、logn、2习题2-4(1)假设某算法在输入规模为n时的计算时间为T(n)=3*2^n。

在某台计算机上实现并完成该算法的时间为t秒。

现有另外一台计算机,其运行速度为第一台计算机的64倍,那么在这台新机器上用同一算法在t秒内能解输入规模为多大的问题?(2)若上述算法的计算时间改进为T(n)=n^2,其余条件不变,则在新机器上用t秒时间能解输入规模多大的问题?(3)若上述算法的计算时间进一步改进为,其余条件不变,那么在新机器上用t秒时间能解输入规模多大的问题?解答:(1)设能解输入规模为n1的问题,则t=3*2^n=3*2^n/64,解得n1=n+6(2)n1^2=64n^2得到n1=8n(3)由于T(n)=常数,因此算法可解任意规模的问题。

习题2-5 XYZ公司宣称他们最新研制的微处理器运行速度为其竞争对手ABC公司同类产品的100倍。

对于计算复杂性分别为n,n^2,n^3和n!的各算法,若用ABC公司的计算机能在1小时内能解输入规模为n的问题,那么用XYZ公司的计算机在1小时内分别能解输入规模为多大的问题?解答:n'=100nn'^2=100n^2得到n'=10nn'^3=100n^3得到n'=4.64nn'!=100n!得到n'<n+log100=n+6.64习题2-6对于下列各组函数f(n)和g(n),确定f(n)=O(g(n))或f(n)=Ω(g(n))或f(n)=θ(g(n)),并简述理由。

算法设计与分析(第2版)-王红梅-胡明-习题答案(1)

算法设计与分析(第2版)-王红梅-胡明-习题答案(1)

算法设计与分析(第2版)-王红梅-胡明-习题答案习题11. 图论诞生于七桥问题。

出生于瑞士的伟大数学家欧拉(Leonhard Euler ,1707—1783)提出并解决了该问题。

七桥问题是这样描述的:一个人是否能在一次步行中穿越哥尼斯堡(现在叫加里宁格勒,在波罗的海南岸)城中全部的七座桥后回到起点,且每座桥只经过一次,图 1.7是这条河以及河上的两个岛和七座桥的草图。

请将该问题的数据模型抽象出来,并判断此问题是否有解。

七桥问题属于一笔画问题。

输入:一个起点输出:相同的点1, 一次步行2, 经过七座桥,且每次只经历过一次3, 回到起点该问题无解:能一笔画的图形只有两类:一类是所有的点都是偶点。

另一类是只有二个奇点的图形。

2.在欧几里德提出的欧几里德算法中(即最初的欧几里德算法)用的不是除法而是减法。

请用伪代码描述这个版本的欧几里德算法1.r=m-n2.循环直到r=02.1 m=n图1.7 七桥问题2.2 n=r2.3 r=m-n3 输出m3.设计算法求数组中相差最小的两个元素(称为最接近数)的差。

要求分别给出伪代码和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]中一个既不是最大也不是最小的元素,并说明最坏情况下的比较次数。

计算机算法设计与分析(第4版) 王晓东习题解答

计算机算法设计与分析(第4版) 王晓东习题解答

第一章作业1.证明下列Ο、Ω和Θ的性质1)f=Ο(g)当且仅当g=Ω(f)证明:充分性。

若f=Ο(g),则必然存在常数c1>0和n0,使得∀n≥n0,有f≤c1*g(n)。

由于c1≠0,故g(n) ≥ 1/ c1 *f(n),故g=Ω(f)。

必要性。

同理,若g=Ω(f),则必然存在c2>0和n0,使得∀n≥n0,有g(n) ≥ c2 *f(n).由于c2≠0,故f(n) ≤ 1/ c2*f(n),故f=Ο(g)。

2)若f=Θ(g)则g=Θ(f)证明:若f=Θ(g),则必然存在常数c1>0,c2>0和n0,使得∀n≥n0,有c1*g(n) ≤f(n) ≤ c2*g(n)。

由于c1≠0,c2≠0,f(n) ≥c1*g(n)可得g(n) ≤ 1/c1*f(n),同时,f(n) ≤c2*g(n),有g(n) ≥ 1/c2*f(n),即1/c2*f(n) ≤g(n) ≤ 1/c1*f(n),故g=Θ(f)。

3)Ο(f+g)= Ο(max(f,g)),对于Ω和Θ同样成立。

证明:设F(n)= Ο(f+g),则存在c1>0,和n1,使得∀n≥n1,有F(n) ≤ c1 (f(n)+g(n))= c1 f(n) + c1g(n)≤ c1*max{f,g}+ c1*max{f,g}=2 c1*max{f,g}所以,F(n)=Ο(max(f,g)),即Ο(f+g)= Ο(max(f,g))对于Ω和Θ同理证明可以成立。

4)log(n!)= Θ(nlogn)证明:∙由于log(n!)=∑=n i i 1log ≤∑=ni n 1log =nlogn ,所以可得log(n!)= Ο(nlogn)。

∙由于对所有的偶数n 有,log(n!)= ∑=n i i 1log ≥∑=n n i i 2/log ≥∑=nn i n 2/2/log ≥(n/2)log(n/2)=(nlogn)/2-n/2。

当n ≥4,(nlogn)/2-n/2≥(nlogn)/4,故可得∀n ≥4,log(n!) ≥(nlogn)/4,即log(n!)= Ω(nlogn)。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

算法设计与分析实验报告学院信息科学与技术学院专业班级软件工程3班学号 20122668 姓名王建君指导教师尹治本2014年10月实验一 同时求最大元与次大元一、问题提出在N 个元素中同时求出最大元与次大元。

二、求解思路利用分治法解决问题。

将一个规模为n 的问题分解为k 个规模较小的子问题,这些子问题互相独立且与原问题相同。

递归地解这些子问题,然后将各个子问题解合并得到原问题的解。

三、算法复杂度当n=1时,不需要比较就可知最大元和次大元均为该数本身。

当n=2时,一次比较就可以找出两个元素的最大元和次大元。

当n>2时,可以把n 个数据元素分为大致相等的两半,一半有n/2个数据元素,而另一半有n/2个数据元素。

先分别找出各自组中的最大元和最小元,然后将两个最大元进行比较,就可得n 个元素的最大元; 将两个最小元中的大元与两个最大元中的小元进行比较,就可得n 个元素的次大元。

在规模为n 的数据元素集合中找出最大元和次大元,至少需要5n/2-4次比较,即5n/2-4是找最大次大元算法的下界,得算法复杂度)(42/5)(T n O n n =-=。

四、源代码 #include<stdio.h>#include<stdlib.h>#define N 10 //宏定义元素的个数int max(int a,int b){if(a>b)return a;elsereturn b;}int min(int a,int b){if(a<b)return a;elsereturn b;}void Search(int a[],int *max0,int *second0,int n){int g[30];int i,m;int max1,max2,second1,second2;if(n==1){*max0=a[0];*second0=a[0];}else if(n==2){*max0=max(a[0],a[1]);*second0=min(a[0],a[1]);}else{m=n/2;for(i=0;i<m;i++)g[i]=a[i];Search(g,&max1,&second1,m);for(i=0;i<n-m;i++)g[i]=a[i+m];Search(g,&max2,&second2,n-m);*max0=max(max1,max2);*second0=max(min(max1,max2),max(second1,second2));}}int main(){int a[N];int i,max,second;system("title 软件3班王建君20122668 分治法求最大元与次大元");printf("请输入%d个数字:\n",N);for(i=0;i<N;i++)scanf("%d",&a[i]);Search(a,&max,&second,N);printf("最大元为%d\n次大元为%d\n",max,second);return 0;}五、结果分析运算结果截图如下依次输入10个数字 12、3、4、9、6、87、34、23、4、2后求得最大元为87,次大元为34。

实验二 实现两个大整数的乘法一、问题提出实现两个大整数的乘法。

二、求解思路利用分治法解决问题。

将一个规模为n 的问题分解为k 个规模较小的子问题,这些子问题互相独立且与原问题相同。

递归地解这些子问题,然后将各个子问题解合并得到原问题的解。

三、算法复杂度设X 和Y 都是n 位的二进制整数,现在要计算它们的乘积XY ,我们将n 位的二进制整数X 和Y 各分为2段,每段的长为n/2位(为简单起见,假设n 是2的幂),如下图所示:由此,X=A2n/2+B ,Y=C2n/2+D ,这样,X 和Y 的乘积可表示为:XY=AC2n+[(A-B)(D-C)+AC+BD]2n/2+BD 。

它仅需做3次n/2位整数的乘法(AC ,BD 和(A-B)(D-C)),6次加、减法和2次移位,由此可得算法复杂度为:用解递归方程的套用法可得其解为:)3log n T 59.12n n O O ()()(==。

四、源代码#include <iostream>#include <sstream>#include <string>#include <stdlib.h>using namespace std;//string 类型转换成int 类型int string_to_num(string k){int back;stringstream instr(k);instr>>back;return back;}//整形数转换为string类型string num_to_string(int intValue){string result;stringstream stream;stream << intV alue;stream >> result;return result;}//在字符串str前添加s个零string stringBeforeZero(string str,int s){for(int i=0;i<s;i++){str.insert(0,"0");}return str;}//两个大整数字符串相加,超出计算机表示范围的数也能实现相加(本函数可以实现大整数加法运算)string stringAddstring(string str1,string str2){//假定str1和str2是相等的长度,不相等时在前面自动补零,使两个字符串长度相等if (str1.size() > str2.size()){str2 = stringBeforeZero(str2,str1.size() - str2.size());}else if (str1.size() < str2.size()){str1 = stringBeforeZero(str1,str2.size() - str1.size());}string result;int flag=0;//前一进位是否有标志,0代表无进位,1代表有进位for(int i=str1.size()-1;i>=0;i--){int c = (str1[i] - '0') + (str2[i] - '0') + flag;//利用ASCII码对字符进行运算,这里加上flag 代表的是:当前一位有进位时加1,无进位时加0flag = c/10;//c大于10时,flag置为1,否则为0c %= 10;//c大于10时取模,否则为其本身result.insert(0,num_to_string(c));//在result字符串最前端插入新生成的单个字符}if (0 != flag) //最后一为(最高位)判断,如果有进位则再添一位{result.insert(0,num_to_string(flag));}return result;}/*两个大整数字符串相减,超出计算机表示范围的数也能实现相减(在这里比较特殊,第一个参数一定大于第二个参数,因为:a1*b0+a0*b1=(a1+a0)*(b1+b0)-(a1*b1+a0*b0) > 0 ,所以(a1+a0)*(b1+b0) > (a1*b1+a0*b0)这个函数的两个参数,第一个代表的其实就是(a1+a0)*(b1+b0),第二个代表的其实就是(a1*b1+a0*b0)所以本函数里不用考虑最终得到结果为负数的情况,至于计算有关大整数负数相乘的问题可以通过其他途径判断*/string stringSubtractstring(string str1,string str2){//对传进来的两个数进行修剪,如果前面几位有0则先去掉,便于统一处理while ('0' == str1[0]&&str1.size()>1){str1=str1.substr(1,str1.size()-1);}while ('0' == str2[0]&&str2.size()>1){str2=str2.substr(1,str2.size()-1);}//使两个字符串长度相等if (str1.size() > str2.size()){str2 = stringBeforeZero(str2,str1.size() - str2.size());}string result;for(int i=str1.size()-1;i>=0;i--){int c = (str1[i] - '0') - (str2[i] - '0');//利用ASCII码进行各位减法运算if (c < 0) //当不够减时向前一位借位,前一位也不够位时再向前一位借位,依次如下{c +=10;int prePos = i-1;char preChar = str1[prePos];while ('0' == preChar){str1[prePos]='9';prePos -= 1;preChar = str1[prePos];}str1[prePos]-=1;}result.insert(0,num_to_string(c));//在result字符串最前端插入新生成的单个字符}return result;}//在字符串str后跟随s个零string stringFollowZero(string str,int s){for(int i=0;i<s;i++){str.insert(str.size(),"0");}return str;}//分治法大整数乘法实现函数string IntMult(string x,string y)//递归函数{//对传进来的第一个数进行修剪,如果前面几位有0则先去掉,便于统一处理while ('0' == x[0]&&x.size()>1){x=x.substr(1,x.size()-1);}//对传进来的第二个数进行修剪,如果前面几位有0则先去掉,便于统一处理while ('0' == y[0]&&y.size()>1){y=y.substr(1,y.size()-1);}/*这里的f变量代表在两个数据字符串长度不想等或者不是2的指数倍的情况下,所要统一的长度,这样做是为了让数据长度为2的n次方的情况下便于利用分治法处理*/int f=4;/*当两字符串中有任意一个字符串长度大于2时都要通过与上面定义的f值进行比较,使其达到数据长度为2的n次方,实现方式是在前面补0,这样可以保证数据值大小不变*/if (x.size()>2 || y.size()>2){if (x.size() >= y.size()) //第一个数长度大于等于第二个数长度的情况{while (x.size()>f) //判断f值{f*=2;}if (x.size() != f){x = stringBeforeZero(x,f-x.size());y = stringBeforeZero(y,f-y.size());}}else//第二个数长度大于第一个数长度的情况{while (y.size()>f) //判断f值{f*=2;}if (y.size() != f){x = stringBeforeZero(x,f-x.size());y = stringBeforeZero(y,f-y.size());}}}if (1 == x.size()) //数据长度为1时,在前面补一个0(这里之所以会出现长度为1的数据是因为前面对数据修剪过){x=stringBeforeZero(x,1);}if (1 == y.size()) //数据长度为1时,在前面补一个0(这里之所以会出现长度为1的数据是因为前面对数据修剪过){y=stringBeforeZero(y,1);}if (x.size() > y.size()) //最后一次对数据校正,确保两个数据长度统一{y = stringBeforeZero(y,x.size()-y.size());}if (x.size() < y.size()) //最后一次对数据校正,确保两个数据长度统一{x = stringBeforeZero(x,y.size()-x.size());}int s = x.size();string a1,a0,b1,b0;if( s > 1){a1 = x.substr(0,s/2);a0 = x.substr(s/2,s-1);b1 = y.substr(0,s/2);b0 = y.substr(s/2,s-1);}string result;if( s == 2) //长度为2时代表着递归的结束条件{int na = string_to_num(a1);int nb = string_to_num(a0);int nc = string_to_num(b1);int nd = string_to_num(b0);result = num_to_string((na*10+nb) * (nc*10+nd));}else{ //长度不为2时利用分治法进行递归运算/***************************************************小提示:c = a*b = c2*(10^n) + c1*(10^(n/2)) + c0;a = a1a0 = a1*(10^(n/2)) + a0;b = b1b0 = b1*(10^(n/2)) + b0;c2 = a1*b1; c0 = a0*b0;c1 = (a1 + a0)*(b1 + b0)-(c2 + c0);****************************************************/string c2 = IntMult(a1,b1);// (a1 * b1)string c0 = IntMult(a0,b0);// (a0 * b0)string c1_1 = stringAddstring(a1,a0);// (a1 + a0)string c1_2 = stringAddstring(b1,b0);// (b1 + b0)string c1_3 = IntMult(c1_1,c1_2);// (a1 + a0)*(b1 + b0)string c1_4 = stringAddstring(c2,c0);// (c2 + c0)string c1=stringSubtractstring(c1_3,c1_4);// (a1 + a0)*(b1 + b0)-(c2 + c0)string s1=stringFollowZero(c1,s/2);// c1*(10^(n/2))string s2=stringFollowZero(c2,s);// c2*(10^n)result = stringAddstring(stringAddstring(s2,s1),c0);// c2*(10^n) + c1*(10^(n/2)) + c0 }return result;}int main(){int f=1;string A,B,C,D;string num1,num2;string r;system("title 软件3班王建君20122668 分治法实现大整数乘法");cout<<"请输入第一个大整数(任意长度):";cin>>num1;int i=0;//判断第一个输入的数据是否合法,当字符串中包含非数字字符时提示用户重新输入for(i=0 ;i < num1.size();i++){if (num1[i]<'0' || num1[i]>'9'){cout<<"您输入的数据不合法,请输入有效的整数!"<<endl;cin>>num1;i=-1;}}cout<<"请输入第二个大整数(任意长度):";cin>>num2;//判断第二个输入的数据是否合法,当字符串中包含非数字字符时提示用户重新输入for(i=0 ;i < num2.size();i++){if (num2[i]<'0' || num2[i]>'9'){cout<<"您输入的数据不合法,请输入有效的整数!"<<endl;cin>>num2;i=-1;}}r=IntMult(num1,num2);//对求得的结果进行修剪,去掉最前面的几个0while ('0' == r[0]&&r.size()>1){r=r.substr(1,r.size()-1);}cout<<"两数相乘结果为:"<<endl;cout<<num1<<" "<<"*"<<" "<<num2<<" "<<"="<<" "<<r<<endl<<endl;}五、结果分析计算结果截图如下11210748210374098777790374124081568900。

相关文档
最新文档