实验4:递归与分治策略的应用
递归与分治算法心得
递归与分治算法心得
递归与分治算法是算法设计中常见的两种方法,它们在解决问题时都采用了“分而治之”的思想,将问题分解成更小的子问题,然后通过递归调用或者合并子问题的解来得到原问题的解。
通过我的学习和实践,我深刻认识到了递归与分治算法的重要性和优势。
首先,递归算法可以使问题的描述更加简单明了。
通过将问题转化为自身的子问题,我们可以建立起更为简洁优美的数学模型。
其次,递归算法可以使问题的解决过程更加自然。
在递归过程中,我们可以利用已知的子问题解决同类问题,实现代码的复用和模块化。
此外,递归算法还可以解决一些重要的数学问题,如斐波那契数列和二分查找等。
分治算法则更加注重问题的分解和合并。
它将问题划分成若干个规模相同或相近的子问题,然后将子问题的解合并起来得到原问题的解。
这种方法在解决某些复杂问题时具有很大的优势。
例如,在排序算法中,归并排序采用了分治算法的思想,将待排序的序列分成两个长度相等的子序列,然后递归地对子序列排序,最后将子序列合并成有序序列。
这种算法具有较高的稳定性和灵活性,常常被应用于海量数据的排序任务中。
总之,递归与分治算法是算法设计中不可或缺的两种方法。
在解决问题时,我们应该根据具体情况选择合适的算法,并在实践中不断探索、总结和优化。
只有这样,我们才能更好地应对日益复杂多变的计算机科学挑战。
递归和分治法
递归和分治法摘要:1.递归和分治法的定义2.递归和分治法的区别3.递归和分治法的应用实例4.递归和分治法的优缺点正文:递归和分治法是计算机科学中常用的两种算法设计技巧。
它们在解决问题时都采用了将问题分解成更小子问题的思路,但在具体实现上却有所不同。
下面,我们来详细了解一下递归和分治法。
1.递归和分治法的定义递归法是指在算法中调用自身来解决问题的方法。
递归函数在执行过程中,会将原问题分解成规模更小的相似子问题,然后通过调用自身的方式,解决这些子问题,最后将子问题的解合并,得到原问题的解。
分治法是指将一个大问题分解成若干个规模较小的相似子问题,然后分别解决这些子问题,最后将子问题的解合并,得到原问题的解。
分治法在解决问题时,通常需要设计一个主函数(master function)和一个子函数(subfunction)。
主函数负责将问题分解,子函数负责解决子问题。
2.递归和分治法的区别递归法和分治法在解决问题时都采用了将问题分解成更小子问题的思路,但它们在实现上存在以下区别:(1)函数调用方式不同:递归法是通过调用自身来解决问题,而分治法是通过调用不同的子函数来解决问题。
(2)递归法必须有递归出口,即必须有一个基线条件,而分治法不一定需要。
3.递归和分治法的应用实例递归法应用广泛,例如斐波那契数列、汉诺塔问题、八皇后问题等。
分治法也有很多实际应用,例如快速排序、归并排序、大整数乘法等。
4.递归和分治法的优缺点递归法的优点是代码简单易懂,但缺点是容易产生大量的重复计算,导致时间复杂度较高。
分治法的优点是时间复杂度较低,但缺点是代码实现相对复杂,需要设计主函数和子函数。
总之,递归和分治法都是解决问题的有效方法,具体应用需要根据问题的特点来选择。
算法实验报告
实验一分治与递归算法的应用一、实验目的1.掌握分治算法的基本思想(分-治-合)、技巧和效率分析方法。
2.熟练掌握用递归设计分治算法的基本步骤(基准与递归方程)。
3.学会利用分治算法解决实际问题。
二 . 实验内容金块问题老板有一袋金块(共n块,n是2的幂(n≥2)),最优秀的雇员得到其中最重的一块,最差的雇员得到其中最轻的一块。
假设有一台比较重量的仪器,希望用最少的比较次数找出最重和最轻的金块。
并对自己的程序进行复杂性分析。
三.问题分析:一般思路:假设袋中有n 个金块。
可以用函数M a x(程序1 - 3 1)通过n-1次比较找到最重的金块。
找到最重的金块后,可以从余下的n-1个金块中用类似法通过n-2次比较找出最轻的金块。
这样,比较的总次数为2n-3。
分治法:当n很小时,比如说,n≤2,识别出最重和最轻的金块,一次比较就足够了。
当n 较大时(n>2),第一步,把这袋金块平分成两个小袋A和B。
第二步,分别找出在A和B中最重和最轻的金块。
设A中最重和最轻的金块分别为HA 与LA,以此类推,B中最重和最轻的金块分别为HB 和LB。
第三步,通过比较HA 和HB,可以找到所有金块中最重的;通过比较LA 和LB,可以找到所有金块中最轻的。
在第二步中,若n>2,则递归地应用分而治之方法程序设计据上述步骤,可以得出程序1 4 - 1的非递归代码。
该程序用于寻找到数组w [ 0 : n - 1 ]中的最小数和最大数,若n < 1,则程序返回f a l s e,否则返回t r u e。
当n≥1时,程序1 4 - 1给M i n和M a x置初值以使w [ M i n ]是最小的重量,w [ M a x ]为最大的重量。
首先处理n≤1的情况。
若n>1且为奇数,第一个重量w [ 0 ]将成为最小值和最大值的候选值,因此将有偶,数个重量值w [ 1 : n - 1 ]参与f o r循环。
当n 是偶数时,首先将两个重量值放在for 循环外进行比较,较小和较大的重量值分别置为Min和Max,因此也有偶数个重量值w[2:n-1]参与for循环。
《算法设计与分析》实验报告实验一...
《算法设计与分析》实验报告实验一递归与分治策略应用基础学号:**************姓名:*************班级:*************日期: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.1 分解首先,将原始问题分解成多个规模较小、相互独立的子问题。
这些子问题可以具有相同的性质,并且它们的解决方法相同。
1.2 解决接下来,递归地解决这些子问题。
如果子问题足够小,可以直接求解并得到结果。
1.3 合并最后,将子问题的解答合并起来,得到原始问题的解答。
在某些情况下,合并这些解决得到的子问题的结果可能需要额外的计算或处理。
2. 实际问题中的分治策略应用现在,我们将介绍如何在实际问题中应用分治策略来解决问题。
以下是几个常见的实例:2.1 归并排序归并排序是分治算法的经典应用之一。
它将待排序的数组分为两个子数组,然后分别对这两个子数组进行排序。
最后,将排序好的子数组合并成一个有序的数组。
这种分治策略可以大大提高排序的效率。
2.2 汉诺塔问题汉诺塔问题是一个经典的递归问题,也可以通过分治策略来解决。
该问题的目标是将一堆大小不同的盘子从一个柱子上移动到另一个柱子上,且在移动过程中要保持较小的盘子在较大的盘子上方。
解决该问题的方法是将问题分解为移动最大盘子以外的子问题,然后递归地解决这些子问题。
2.3 最大子数组和问题最大子数组和问题是在一个整数数组中寻找连续子数组的和的最大值。
这个问题可以使用分治策略来解决。
将问题划分为左半部分、右半部分和跨越中点的子问题。
最后,将这三者的最大值作为最终的结果返回。
3. 分治策略的优缺点分治策略具有一些优点和缺点,我们来看看它们是什么。
分治法实验心得
分治法实验心得分治法实验心得分治法是一种常见的算法设计策略,它将原问题划分成若干个规模较小但结构与原问题相似的子问题,然后递归地求解这些子问题,最终将子问题的解合并得到原问题的解。
在本次实验中,我们实现了两个基于分治法的算法:归并排序和快速排序,并对它们进行了性能测试和比较。
一、归并排序1. 原理归并排序是一种典型的分治算法。
它将待排序数组不断地二分为两个子数组,直到每个子数组只剩下一个元素。
然后将相邻的两个子数组合并成一个有序数组,再将相邻的两个有序数组合并成一个更大的有序数组,直到最终合并成整个待排序数组。
2. 实现我们采用了自顶向下的递归方式实现了归并排序。
具体来说,我们定义了一个merge函数用于合并两个有序子数组,并定义了一个sort 函数用于递归地对左右两个子数组进行排序和合并。
3. 性能测试与比较我们使用Python内置的time模块对不同规模(10^2 ~ 10^6)的随机整数列表进行了性能测试,并绘制出了运行时间随数组规模增大的变化曲线。
结果表明,归并排序的时间复杂度为O(nlogn),与理论分析相符。
二、快速排序1. 原理快速排序也是一种分治算法。
它选择一个基准元素,将数组中小于等于它的元素放在其左侧,大于它的元素放在其右侧。
然后递归地对左右两个子数组进行同样的操作,直到每个子数组只剩下一个元素。
2. 实现我们实现了两个版本的快速排序:递归版本和非递归版本。
其中,递归版本采用了经典的Lomuto分区方案,而非递归版本则采用了更高效的Hoare分区方案。
3. 性能测试与比较我们同样使用Python内置的time模块对不同规模(10^2 ~ 10^6)的随机整数列表进行了性能测试,并绘制出了运行时间随数组规模增大的变化曲线。
结果表明,快速排序具有很好的平均时间复杂度(O(nlogn)),但最坏情况下时间复杂度会退化到O(n^2)。
三、总结与思考通过本次实验,我们深入理解了分治算法设计策略,并学会了如何实现归并排序和快速排序。
算法设计与分析:递归与分治法-实验报告(总8页)
算法设计与分析:递归与分治法-实验报告(总8页)实验目的:掌握递归与分治法的基本思想和应用,学会设计和实现递归算法和分治算法,能够分析和评价算法的时间复杂度和空间复杂度。
实验内容:1.递归算法的设计与实现3.算法的时间复杂度和空间复杂度分析实验步骤:1)递归定义:一个函数或过程,在其定义或实现中,直接或间接地调用自身的方法,被成为递归。
递归算法是一种控制结构,它包含了解决问题的基础情境,也包含了递归处理的情境。
2)递归特点:递归算法具有以下特点:①依赖于递归问题的部分解被划分为若干较小的部分。
②问题的规模可以通过递推式递减,最终递归终止。
③当问题的规模足够小时,可以直接求解。
3)递归实现步骤:①确定函数的定义②确定递归终止条件③确定递归调用的过程4)经典实例:斐波那契数列递推式:f(n) = f(n-1) + f(n-2)int fib(int n) {if (n <= 0)return 0;else}5)优化递归算法:避免重复计算例如,上述斐波那契数列的递归算法会重复计算一些中间结果,影响效率。
可以使用动态规划技术,将算法改为非递归形式。
int f1 = 0, f2 = 1;for (int i = 2; i <= n; i++) {f1 = f2;使用循环避免递归,重复计算可以大大减少,提高效率。
1)分治算法的定义:将原问题分解成若干个规模较小且类似的子问题,递归求解子问题,然后合并各子问题得到原问题的解。
2)分治算法流程:②将问题分解成若干个规模较小的子问题。
③递归地解决各子问题。
④将各子问题的解合并成原问题的解。
3)分治算法实例:归并排序归并排序是一种基于分治思想的经典排序算法。
排序流程:②分别对各子数组递归进行归并排序。
③将已经排序好的各子数组合并成最终的排序结果。
实现源代码:void mergeSort(int* arr, int left, int right) {if (left >= right)while (i <= mid && j <= right)temp[k++] = arr[i] < arr[j] ? arr[i++] : arr[j++];temp[k++] = arr[i++];1) 时间复杂度的概念:指完成算法所需的计算次数或操作次数。
分治策略算法实验报告
分治策略算法实验报告引言分治策略是一种经典的算法设计策略,也是算法设计中最重要的思想之一。
其基本思想是将大问题划分成小的、相互独立的子问题,再将子问题合并求解,最终得到原问题的解。
本实验将通过实际例子,验证分治策略算法的有效性。
实验内容本实验选择两个经典的算法问题进行实现和验证,分别是二分查找和快速排序。
这两个问题在算法领域都有重要的应用价值,也是实践分治算法的好例子。
问题1:二分查找二分查找是一种在有序数组中查找特定元素的算法,其基本思想是将数组分为两部分,然后判断目标值在哪一部分,并且逐步缩小问题的规模。
具体实现如下:pythondef binary_search(arr, target):low = 0high = len(arr) - 1while low <= high:mid = (low + high) 2if arr[mid] == target:return midelif arr[mid] < target:low = mid + 1else:high = mid - 1return -1问题2:快速排序快速排序是一种高效的排序算法,其基本思想是通过一趟划分将待排序序列分割成两个独立的子序列,然后递归地对子序列进行排序,最终得到有序序列。
具体实现如下:pythondef quicksort(arr):if len(arr) <= 1:return arrpivot = arr[len(arr) 2]left = [x for x in arr if x < pivot]middle = [x for x in arr if x == pivot]right = [x for x in arr if x > pivot]return quicksort(left) + middle + quicksort(right)实验结果为了验证分治策略算法的有效性,我们分别对上述两个问题进行了测试。
分治法实验总结
分治法实验总结
分治法是一种常用的算法设计策略,它将问题分解成若干个子问题,然后递归地解决这些子问题,最后将子问题的解合并成原问题的解。
在本次实验中,我们通过实现归并排序和快速排序两个算法,深入理解了分治法的思想和实现方式。
我们实现了归并排序算法。
归并排序的基本思想是将待排序的序列分成若干个子序列,每个子序列都是有序的,然后再将子序列合并成一个有序的序列。
在实现过程中,我们采用了递归的方式,将序列不断地分成两半,直到每个子序列只有一个元素,然后再将这些子序列两两合并,直到最终得到一个有序的序列。
归并排序的时间复杂度为O(nlogn),是一种稳定的排序算法。
接着,我们实现了快速排序算法。
快速排序的基本思想是选择一个基准元素,将序列分成两个部分,一部分比基准元素小,一部分比基准元素大,然后递归地对这两个部分进行排序。
在实现过程中,我们选择了序列的第一个元素作为基准元素,然后使用两个指针分别从序列的两端开始扫描,将比基准元素小的元素放在左边,将比基准元素大的元素放在右边,最后将基准元素放在中间,然后递归地对左右两个部分进行排序。
快速排序的时间复杂度为O(nlogn),但是在最坏情况下,时间复杂度会退化为O(n^2)。
通过实现归并排序和快速排序两个算法,我们深入理解了分治法的
思想和实现方式。
分治法是一种非常重要的算法设计策略,可以用来解决很多复杂的问题,比如最近点对问题、矩阵乘法问题等。
在实际应用中,我们可以根据具体问题的特点选择合适的分治算法,以提高算法的效率和准确性。
分治算法探讨分治策略与应用场景
分治算法探讨分治策略与应用场景随着计算机科学的快速发展,算法成为了解决问题的重要工具。
其中,分治算法在很多场景下展现出强大的能力,被广泛应用于各个领域。
本文将探讨分治策略的原理和常见应用场景。
一、分治策略的基本原理分治策略是一种将大问题划分为细分的子问题,并通过解决子问题来解决原始问题的思想。
其基本思路可以概括为以下三个步骤:1. 分解:将原始问题划分为若干规模较小的子问题。
2. 解决:递归地解决各个子问题。
3. 合并:将各个子问题的解合并为原始问题的解。
通过将大问题递归地划分为越来越小的子问题,最终解决各个子问题,再将子问题的解合并为原始问题的解,分治策略能够高效地解决很多复杂的问题。
二、分治策略的应用场景1. 排序算法排序是计算机科学中一个重要的问题,各种排序算法都可以使用分治策略来实现。
例如,快速排序和归并排序就是使用分治策略的经典排序算法。
在快速排序中,通过选择一个基准元素将问题划分为两个子问题,然后递归地排序子问题。
最后,再将排序好的子数组合并为原始数组的有序序列。
在归并排序中,通过将问题划分为两个子问题,递归地排序子数组。
最后,再将排序好的子数组合并为原始数组的有序序列。
归并排序的特点是稳定性好,适用于大规模数据的排序。
2. 查找问题分治策略也可以应用于查找问题。
例如,在有序数组中查找某个元素可以使用二分查找算法,该算法也采用了分治思想。
二分查找算法通过将问题划分为两个子问题,然后根据子问题的规模逐步缩小查找范围,最终找到目标元素。
这种分治思想使得二分查找具有高效性。
3. 矩阵乘法矩阵乘法是一个常见的数学运算问题。
通过分治策略,可以将矩阵乘法划分为多个小问题,并递归地解决这些小问题。
然后,再将这些小问题的解进行合并,得到原始问题的解。
分治法用于矩阵乘法算法的优化,可以减少运算量,提高计算效率。
4. 搜索问题分治策略也可以应用于搜索问题。
例如,在搜索引擎中,分治策略可以用于并行搜索,从而加快搜索速度。
递归实验报告分析总结
递归实验报告分析总结递归是一种非常重要的编程思想和技巧,对于理解和解决问题具有非常大的帮助。
通过递归,我们可以将一个问题分解成为更小的子问题,从而简化问题的复杂度和难度。
在本次实验中,我深入学习了递归的原理和应用,并实践了一些递归算法。
通过这些实验,我对递归有了更深入和全面的理解,掌握了递归的使用方法和注意事项。
在实验中,我首先学习了递归的概念和原理。
递归是一种将大问题分解成小问题的算法思想,通过不断调用自己来解决问题。
递归算法通常包含两个部分:基本情况和递归情况。
基本情况是递归终止的条件,递归情况是递归调用自身的条件。
通过合理设置这两个条件,我们可以确保递归算法能够得到正确的结果并正常终止。
然后,我练习了递归的应用。
在实验中,我实现了一些常见的递归算法,如计算阶乘、斐波那契数列等。
通过这些实践,我更加熟悉了递归的写法和思维模式。
递归算法的核心思想是将大问题分解成小问题,然后通过递归调用解决这些小问题,最终得到整个问题的解。
这种思维模式非常灵活和高效,对于解决一些复杂和抽象的问题非常有帮助。
在实验过程中,我也遇到了一些递归算法的常见问题和注意事项。
例如,递归算法容易出现堆栈溢出的问题,因为每次递归调用都会占用一定的内存空间,如果递归层数过多,就容易导致栈溢出。
为了解决这个问题,我们可以在递归算法中加入递归深度的限制条件,或者考虑使用迭代算法等其他算法思想。
此外,递归算法的时间复杂度一般比较高,因为递归算法需要不断的调用自身,导致函数的调用次数非常多。
为了提高递归算法的效率,我们可以尝试使用尾递归优化、记忆化搜索等技巧。
尾递归优化是指在递归函数的最后一步调用中,直接返回递归函数的结果,而不再进行其他操作。
这样可以有效避免函数调用的堆栈积累,提高程序的性能。
总的来说,通过本次递归实验,我对递归算法有了更深入的理解和掌握。
递归是一种非常强大和灵活的算法思想,可以用来解决各种复杂的问题。
通过合理设置递归的基本情况和递归情况,我们可以通过递归算法简化问题的复杂度和难度,高效地解决问题。
棋盘覆盖
实验一:棋盘覆盖(递归与分治策略)一、实验目的与要求1、明确棋盘覆盖的概念2、明确递归与分治策略的设计思路。
3、利用递归与分治策略解决棋盘覆盖问题。
二、实验题:问题描述:递归与分治策略算法,用4种不同形态的L型骨牌覆盖一个给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。
输入数据由程序运行后的界面中的编辑框中输入游戏规模,特殊方格的位置。
将覆盖的结果在窗口中显示出来。
三、实验代码#include<iostream>#include<stdio.h>using namespace std;#define SIZE 16 //宏定义棋盘的大小int board[SIZE][SIZE] ; //全局变量int chessboard(int tr,int tc, int dr, int dc, int size);int main(){int tr = 0,tc = 0;int dr,dc;cout<<"特殊棋子的列号:dr = ";cin>>dr;cout<<"特殊棋子的行号:dc = ";cin>>dc;chessboard(tr,tc,dr,dc,SIZE);for(int i = 0;i < SIZE; ++ i){for(int j = 0;j < SIZE;++ j){//cout<<board[i][j]<<" ";printf("%-2d ",board[i][j]); //控制字符输出格式}cout<<endl;}}int chessboard(int tr,int tc, int dr, int dc, int size){if(size == 1) return 0;int s,t;static int tile = 0; //将tile申请为静态变量,以便储存tile随时改变的值t = tile ++;s = size / 2;if(dr < tr+ s && dc < tc +s){chessboard(tr,tc,dr,dc,s);}else{board[tr + s - 1][tc + s - 1] = t;chessboard(tr,tc,tr + s -1,tc + s - 1,s);}//覆盖左上角if(dr < tr+ s && dc >= tc +s){chessboard(tr,tc + s,dr,dc,s);}else{board[tr + s - 1][tc + s] = t;chessboard(tr,tc + s,tr + s -1,tc + s,s);}//覆盖棋盘右上角if(dr >= tr+ s && dc < tc +s){chessboard(tr + s,tc,dr,dc,s);}else{board[tr + s][tc + s - 1] = t;chessboard(tr + s,tc,tr + s,tc + s - 1,s);}//覆盖棋盘左下角if(dr >= tr+ s && dc >= tc +s){chessboard(tr + s,tc + s,dr,dc,s);}else{board[tr + s][tc + s] = t;chessboard(tr + s,tc + s,tr + s,tc + s,s);}//覆盖棋盘右下角return 1;}四、实验结果。
算法设计与分析:第02章 递归与分治策略
A(1,0) 2 A(0, m) 1 m0 A(n,0) n 2 n2 A(n, m) A( A(n 1, m), m 1) n, m 1
2.1
递归的概念
例3 Ackerman函数 前2例中的函数都可以找到相应的非递归方式定义:
n! 1 2 3 (n 1) n
课件第2章
递归与分治策略
算法总体思想
• 将要求解的较大规模的问题分割成k个更小规模的子问 对这k个子问题分别求解。如果子问题的规模仍然不够 小,则再划分为k个子问题,如此递归的进行下去,直 题。 到问题规模足够小,很容易求出其解为止。
T(n)
=
n
T(n/2)
T(n/2)
T(n/2)
T(n/2)
算法总体思想
下面来看几个实例。
2.1
递归的概念
边界条件
例1 阶乘函数 阶乘函数可递归地定义为:
n0 1 n! n(n 1)! n 0
递归方程 边界条件与递归方程是递归函数的二个要素,递归函 数只有具备了这两个要素,才能在有限次计算后得出 结果。
2.1
递归的概念
例2 Fibonacci数列 无穷数列1,1,2,3,5,8,13,21,34,55,…,被 称为Fibonacci数列。它可以递归地定义为:
2.1
递归的概念
例6 Hanoi塔问题 public static void hanoi(int n, int a, int b, int c) 当n=1时,问题比较简单。此时,只要将编号为1的圆盘从塔座a直 在问题规模较大时,较难找到一般的方法,因此我们尝试 接移至塔座b上即可。 用递归技术来解决这个问题。 { 思考题:如果塔的个数变为a,b,c,d 当n>1时,需要利用塔座c作为辅助塔座。此时若能设法将n-1个 if (n > 0) 四个,现要将n个圆盘从a全部移动 较小的圆盘依照移动规则从塔座a移至塔座c,然后,将剩下的最 { 到d,移动规则不变,求移动步数最 大圆盘从塔座a移至塔座b,最后,再设法将n-1个较小的圆盘依照 hanoi(n-1, a, c, b); 小的方案。 移动规则从塔座c移至塔座b。 move(a,b); 由此可见,n个圆盘的移动问题可分为2次n-1个圆盘的移动问题, hanoi(n-1, c, b, a); 这又可以递归地用上述方法来做。由此可以设计出解Hanoi塔问题 的递归算法如下。 } }
递归和分治法
递归和分治法摘要:一、递归与分治法的概念1.递归:函数调用自身的思想2.分治法:把一个大问题分解成若干个小问题二、递归与分治法的联系与区别1.递归通常作为分治法的实现方式2.分治法不一定要用递归实现三、递归与分治法的应用实例1.快速排序算法2.归并排序算法3.汉诺塔问题正文:递归和分治法是两种在计算机科学中经常使用的解决问题的方法。
递归是一种函数调用自身的思想,即函数在执行过程中,会调用自身来完成某些操作。
而分治法则是把一个大问题分解成若干个小问题,然后逐个解决这些小问题,最后再把它们的解合并,得到大问题的解。
这两种方法在某些情况下可以相互转化,递归通常作为分治法的实现方式,但分治法不一定要用递归实现。
递归与分治法之间的联系在于,递归通常是分治法的实现方式。
在分治法中,我们会把一个大问题分解成若干个小问题,然后通过递归的方式,逐个解决这些小问题。
最后,再把它们的解合并,得到大问题的解。
在这个过程中,递归函数的调用栈会随着问题规模的减小而减小,最终回到原点,从而完成问题的求解。
然而,分治法并不一定要用递归实现。
在一些情况下,我们可以通过迭代的方式,逐个解决小问题,然后把它们的解合并。
这种方式虽然不是通过递归函数调用自身来实现的,但它仍然符合分治法的思想,即把大问题分解成小问题,逐个解决。
递归和分治法在实际问题中有很多应用。
例如,快速排序算法和归并排序算法都是基于分治法的思想设计的。
在快速排序算法中,我们选择一个基准元素,然后把数组中小于基准的元素放在左边,大于基准的元素放在右边,再对左右两个子数组递归地执行相同的操作,直到数组有序。
而在归并排序算法中,我们同样把数组分成左右两个子数组,然后递归地对它们进行排序,最后再把排序好的子数组合并成一个有序的数组。
另一个例子是汉诺塔问题。
在这个问题中,有三个柱子和一个大小不同的圆盘。
要求把圆盘从第一个柱子移动到第三个柱子,每次只能移动一个圆盘,并且大盘不能放在小盘上。
算法与设计实验报告
实验一分治与递归(4学时)一、实验目的与要求1、熟悉C/C++语言的集成开发环境;2、通过本实验加深对递归过程的理解二、实验内容掌握递归算法的概念和基本思想,分析并掌握“整数划分”问题的递归算法。
三、实验题任意输入一个整数,输出结果能够用递归方法实现整数的划分。
四、程序代码五、实验结果首先按照提示输入数字:按回车键,得到此数划分的个数:此时您可以接着计算另一个数的划分个数:若要退出,请输入一个小于等于零的数:六、结果分析及程序功能经过和其它同学的实验数据对比,初步认定此程序基本正确,然而不足之处是只能得到划分的个数,而不能列出每个划分的详细情况。
一、实验目的与要求1、掌握棋盘覆盖问题的算法;2、初步掌握分治算法二、实验题盘覆盖问题:在一个2k×2k个方格组成的棋盘中,恰有一个方格与其它方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。
在棋盘覆盖问题中,要用图示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。
三、程序代码四、实验结果按照提示输入特殊方格的行号和列号(起始行列号为0):按回车键,得到一个矩阵,数字相同区域为一个L型骨牌覆盖:五、结果分析及程序功能得到的16*16棋盘覆盖结果正确,此程序的不足之处:只能设定特殊方格的行列号,而不能设定棋盘的大小。
实验二动态规划算法(4学时)一、实验目的与要求1、熟悉最长公共子序列问题的算法;2、初步掌握动态规划算法;二、实验题若给定序列X={x1,x2,…,xm},则另一序列Z={z1,z2,…,zk},是X的子序列是指存在一个严格递增下标序列{i1,i2,…,ik}使得对于所有j=1,2,…,k有:zj=xij。
例如,序列Z={B,C,D,B}是序列X={A,B,C,B,D,A,B}的子序列,相应的递增下标序列为{2,3,5,7}。
给定2个序列X和Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列。
快速排序算法实验报告
一、实验目的1. 理解快速排序算法的基本原理和实现方法。
2. 掌握快速排序算法的递归分治策略。
3. 分析快速排序算法的时间复杂度和空间复杂度。
4. 通过实验验证快速排序算法的性能。
二、实验内容本实验主要涉及快速排序算法的原理、实现和性能分析。
实验内容包括:1. 快速排序算法的基本原理。
2. 快速排序算法的递归分治策略。
3. 快速排序算法的时间复杂度和空间复杂度分析。
4. 快速排序算法的C语言实现。
5. 快速排序算法的性能测试。
三、实验原理快速排序算法是一种高效的排序算法,其基本思想是选取一个基准元素(pivot),将待排序的序列划分为两部分,使得左边的部分都小于等于基准元素,右边的部分都大于等于基准元素。
然后递归地对左右两部分分别进行快速排序,直到整个序列有序。
快速排序算法的递归分治策略如下:1. 选择基准元素:在待排序序列中选取一个元素作为基准元素。
2. 分区操作:将待排序序列划分为两部分,使得左边的部分都小于等于基准元素,右边的部分都大于等于基准元素。
3. 递归排序:分别对左右两部分递归进行快速排序。
四、实验步骤1. 快速排序算法的C语言实现```c#include <stdio.h>void swap(int a, int b) {int temp = a;a = b;b = temp;}int partition(int arr[], int low, int high) { int pivot = arr[high];int i = (low - 1);for (int j = low; j <= high - 1; j++) {if (arr[j] < pivot) {i++;swap(&arr[i], &arr[j]);}}swap(&arr[i + 1], &arr[high]);return (i + 1);}void quickSort(int arr[], int low, int high) { if (low < high) {int pi = partition(arr, low, high);quickSort(arr, low, pi - 1);quickSort(arr, pi + 1, high);}}void printArray(int arr[], int size) {int i;for (i = 0; i < size; i++)printf("%d ", arr[i]);printf("\n");}int main() {int arr[] = {10, 7, 8, 9, 1, 5};int n = sizeof(arr) / sizeof(arr[0]);quickSort(arr, 0, n - 1);printf("Sorted array: \n");printArray(arr, n);return 0;}```2. 快速排序算法的性能测试为了测试快速排序算法的性能,我们可以对不同的输入数据量进行排序,并记录排序所需的时间。
函数思想在解题中的应用
函数思想在解题中的应用函数思想是一种方法或策略,它将一个复杂的问题分解为更小的子问题,并通过解决这些子问题来解决整个问题。
在计算机科学和数学中,函数思想广泛应用于问题求解、算法设计和编程等方面。
本文将从几个不同的角度探讨函数思想在解题中的应用。
一、抽象和封装函数思想的一个核心概念是抽象和封装。
通过将一组操作封装到一个函数中,我们可以将其视为一个黑盒,只关注其输入和输出,而不需要了解内部的具体实现细节。
这种抽象和封装的方式使得我们能够更加专注于问题的本质,提高代码的可读性和可维护性。
例如,在一个数字列表中找到最大值的问题中,我们可以定义一个函数`find_max(`来实现。
这个函数接收一个数字列表作为输入,并返回列表中的最大值。
在使用这个函数时,我们只需要关注输入和输出,而不需要了解函数内部是如何实现的。
这种抽象和封装的方式使得我们可以将注意力集中在解决问题本身上,而不需要关注底层的实现细节。
二、模块化和复用函数思想能够将一个大问题分解为更小的子问题,从而实现模块化和复用。
通过将一些常用的操作封装到函数中,我们可以在解决不同的问题时重复使用这些函数,提高代码的重用性和效率。
例如,在一个学生成绩管理系统中,我们可以定义一个函数`calculate_average(`来计算一个学生的平均分数。
在需要计算多个学生的平均分数时,我们可以重复调用这个函数,从而实现代码的复用和简化。
这种模块化和复用的方式不仅提高了代码的效率,还使得代码更加清晰和易于理解。
三、递归和分治递归和分治是函数思想的两个重要概念,它们在解决问题中起到了重要的作用。
递归是指一个函数可以在其定义中调用自身的过程。
递归可以将一个复杂的问题分解为更小的相似子问题,并通过解决这些子问题来解决原始问题。
递归通常使用递归函数来实现,其中递归函数是一个对自身进行调用的函数。
例如,求阶乘是一个经典的递归问题。
我们可以定义一个递归函数`factorial(n)`来计算一个数字n的阶乘。
河内塔实验报告论文
摘要河内塔问题,又称为汉诺塔问题,是问题解决领域中的一个经典实验。
本研究旨在通过河内塔实验,探讨被试者在解决问题过程中的思维策略和认知过程。
实验结果表明,被试者在解决问题时,会运用多种策略,如递归、分治等,且口头报告能够促进思维过程的明确化。
本文将从实验设计、结果分析、讨论与结论等方面进行详细阐述。
关键词:河内塔问题;问题解决;思维策略;口头报告一、引言河内塔问题最早由法国数学家Edouard Lucas于1883年提出,该问题要求将一系列圆盘从一个柱子移动到另一个柱子,同时遵守以下规则:1. 每次只能移动一个圆盘;2. 圆盘必须按照从大到小的顺序移动;3. 任何时候,都不能将一个较大的圆盘放在一个较小的圆盘上面。
河内塔问题不仅是一个经典的数学问题,也是一个心理学问题。
在认知心理学领域,河内塔问题被广泛应用于研究问题解决策略和认知过程。
本研究旨在通过河内塔实验,探讨被试者在解决问题过程中的思维策略和认知过程。
二、实验设计1. 被试:选取30名大学生作为被试,男女各半,年龄在18-22岁之间。
2. 实验材料:河内塔问题实验装置,包括三个柱子和一系列大小不同的圆盘。
3. 实验步骤:(1)向被试介绍河内塔问题的规则和目标;(2)让被试独立完成河内塔问题的解决;(3)在被试解决过程中,要求其进行口头报告,描述自己的思考过程;(4)记录被试解决问题的总时间、移动次数以及口头报告的内容。
三、结果分析1. 解决问题总时间:被试解决问题的总时间在60-300秒之间,平均时间为120秒。
2. 移动次数:被试解决问题的移动次数在30-60次之间,平均次数为45次。
3. 口头报告内容:(1)部分被试在解决问题过程中,采用了递归策略。
例如,将被试者A上的n-1个圆盘移动到B上,然后将A上的第n个圆盘移动到C上,最后将B上的n-1个圆盘移动到C上。
(2)部分被试在解决问题过程中,采用了分治策略。
例如,将被试者A上的n-1个圆盘移动到B上,然后将A上的第n个圆盘移动到C上,最后将B上的n-1个圆盘移动到C上。
算法设计与分析实验报告
本科实验报告课程名称:算法设计与分析实验项目:递归与分治算法实验地点:计算机系实验楼110专业班级:物联网1601 学号:2016002105 学生姓名:俞梦真指导教师:郝晓丽2018年05月04 日实验一递归与分治算法1.1 实验目的与要求1.进一步熟悉C/C++语言的集成开发环境;2.通过本实验加深对递归与分治策略的理解和运用。
1.2 实验课时2学时1.3 实验原理分治(Divide-and-Conquer)的思想:一个规模为n的复杂问题的求解,可以划分成若干个规模小于n的子问题,再将子问题的解合并成原问题的解。
需要注意的是,分治法使用递归的思想。
划分后的每一个子问题与原问题的性质相同,可用相同的求解方法。
最后,当子问题规模足够小时,可以直接求解,然后逆求原问题的解。
1.4 实验题目1.上机题目:格雷码构造问题Gray码是一个长度为2n的序列。
序列无相同元素,每个元素都是长度为n的串,相邻元素恰好只有一位不同。
试设计一个算法对任意n构造相应的Gray码(分治、减治、变治皆可)。
对于给定的正整数n,格雷码为满足如下条件的一个编码序列。
(1)序列由2n个编码组成,每个编码都是长度为n的二进制位串。
(2)序列中无相同的编码。
(3)序列中位置相邻的两个编码恰有一位不同。
2.设计思想:根据格雷码的性质,找到他的规律,可发现,1位是0 1。
两位是00 01 11 10。
三位是000 001 011010 110 111 101 100。
n位是前n-1位的2倍个。
N-1个位前面加0,N-2为倒转再前面再加1。
3.代码设计:}}}int main(){int n;while(cin>>n){get_grad(n);for(int i=0;i<My_grad.size();i++)cout<<My_grad[i]<<endl;My_grad.clear();}return 0;}运行结果:1.5 思考题(1)递归的关键问题在哪里?答:1.递归式,就是如何将原问题划分成子问题。
《算法设计与分析》课程实验报告 (分治法(三))
《算法设计与分析》课程实验报告实验序号:04实验项目名称:实验4 分治法(三)一、实验题目1.邮局选址问题问题描述:在一个按照东西和南北方向划分成规整街区的城市里,n个居民点散乱地分布在不同的街区中。
用x 坐标表示东西向,用y坐标表示南北向。
各居民点的位置可以由坐标(x,y)表示。
街区中任意2 点(x1,y1)和(x2,y2)之间的距离可以用数值∣x1−x2∣+∣y1−y2∣度量。
居民们希望在城市中选择建立邮局的最佳位置,使n个居民点到邮局的距离总和最小。
编程任务:给定n 个居民点的位置,编程计算邮局的最佳位置。
2.最大子数组问题问题描述:对给定数组A,寻找A的和最大的非空连续子数组。
3.寻找近似中值问题描述:设A是n个数的序列,如果A中的元素x满足以下条件:小于x的数的个数≥n/4,且大于x的数的个数≥n/4 ,则称x为A的近似中值。
设计算法求出A的一个近似中值。
如果A中不存在近似中值,输出false,否则输出找到的一个近似中值4.循环赛日程表问题描述:设有n=2^k个运动员要进行网球循环赛。
现要设计一个满足以下要求的比赛日程表:每个选手必须与其他n-1个选手各赛一次,每个选手一天只能赛一次,循环赛一共进行n-1天。
二、实验目的(1)进一步理解分治法解决问题的思想及步骤(2)体会分治法解决问题时递归及迭代两种不同程序实现的应用情况之差异(3)熟练掌握分治法的自底向上填表实现(4)将分治法灵活于具体实际问题的解决过程中,重点体会大问题如何分解为子问题及每一个大问题涉及哪些子问题及子问题的表示。
三、实验要求(1)写清算法的设计思想。
(2)用递归或者迭代方法实现你的算法,并分析两种实现的优缺点。
(3)根据你的数据结构设计测试数据,并记录实验结果。
(4)请给出你所设计算法的时间复杂度的分析,如果是递归算法,请写清楚算法执行时间的递推式。
四、实验过程(算法设计思想、源码)1.邮局选址问题(1)算法设计思想根据题目要求,街区中任意2 点(x1,y1)和(x2,y2)之间的距离可以用数值∣x1−x2∣+∣y1−y2∣度量。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
课程实验报告结果运行到一定规模:快速排序:运行到一定规模:堆排序:运行到一定规模:矩阵乘法:1朴素算法:2Strassen矩阵乘算法一定规模后:总结横坐标计算规模:1:8129 2:65536 3:131072 4:262144 5:1048576随着输入规模的增大,通过三种算法的时间记录做成折线图观察不难发现,在初期,三种算法所用时间几乎相等,随着输入规模的不断增大,堆排序和快速排序仍然能够保持相对较小的增长,而并归排序所用时间复杂度开始大幅度增加。
快速排序果然是快,数据越大优势越明显,并且实现上也较为简单。
理论上它的平均时间和归并排序,堆排序都是一样的(在最坏情况还还不如它们),都是O(nlog2n),但实际运行来看比它们两者的速度都快一倍以上。
COOL!合并排序需要额外相同规模的数组,空间复杂度为O(n)。
从具体实现来看,这只是一种理论上的优秀算法,想法比较简单直接,但实现上比quicksort 复杂,运行时间也差,在数据很大的时候运行时间是heapsort的两倍,更不用说quicksort了。
堆排序利用了二分树的结构,将时间复杂度降到O(nlog2n),理论上和实现上表现都不错,并且发现在数据量是10 000 000时,甚至优于快排,可能是运行时数据的问题。
对于strassen 算法对其时间复杂度分析:T(n)=7T(n/2)+O(n);而朴素算法的时间复杂度为n的三次方。
随着数据增大,也出现乘方级别的时间复杂度差距。
附录//头文件#include<iostream>#include<stdio.h>#include<windows.h>#include<time.h>#include<string.h>#define PARENT(i) (i/2) //几个较简单函数#define LEFT(i) (2*i+1)#define RIGHT(i) (2*i+2)using namespace std;//定义所需要变量等#define MAX 100000int a[MAX]; //数组存储原始顺序int temp[MAX]; //临时数组存储临时排序值int num; //计算统计逆序对数int N = 2; //数据规模clock_t begintimes, endtimes; //clock_t为clock()函数返回的变量类型double duration; //运行时间计算int heapsize; //堆长度//随机生成数函数int number(){int a;a = rand() % 10000 + 1; //随机生成1到一万之间的整数return a;}//初始化函数对数组a[]初始化。
void init(){memset(temp,0, MAX * sizeof(int)); //临时数组清零for (int i = 0; i < N; i++){ //新数组赋值a[i] = number();}return;}//单次并归挑选void Merge(int left, int mid, int right) //需要三个参数,将原来数组分割{int i = left, j = mid + 1, n = 0, length = right - left;//i开始为左半部分最左边,j为右半部分最左边while (i <= mid && j <= right){ //未超限进行循环填数if (a[i]>a[j]){ //左边比右边大temp[n++] = a[j++];num += mid - i + 1; //从i到mid都比a[j]大}else{temp[n++] = a[i++];}}if (i>mid){ //左边全部填满了,填右边while (j <= right){temp[n++] = a[j++];}}else{ //右边填满,填左边while (i <= mid){temp[n++] = a[i++];}}for (int k = 0; k <= length; k++){ //最后临时数组赋值到原数组a[left + k] = temp[k];}//递归进行并归排序void MergeSort(int left, int right){if (left<right){int mid = (left + right) / 2;MergeSort(left, mid);MergeSort(mid + 1, right);Merge(left, mid, right);}}//快速排序一次int Partition(int left, int right){int i = left - 1;for (int j = left; j <= right - 1; j++){if (a[j] < a[right]){ //把right作为轴i++; //这个i坐标左边的值是比a[right]小的swap(a[i], a[j]); //交换}}swap(a[i + 1], a[right]); //最后把i+1和right交换,这样轴就是i+1了必须是保证i+1上当初就是作为标杆的a[right]啊。
return i + 1;}//递归进行快排整体void QuickSort(int left, int right){if (left<right){int q = Partition(left, right);QuickSort(left, q - 1);QuickSort(q + 1, right);}}//堆排序,函数太多,新建一个命名空间namespace MySort{template<typename T> //堆排序的大顶堆优化(找数)void Max_Heapify(T*arr, int i, size_t heapSize){//从元素A[i]、A[LEFT(i)]、A[RIGHT(i)]中找出最大的,并将其下标保存在Largest中//size_t heapSize = sizeof(arr) / sizeof(*(arr)); 也就是数量nint l = LEFT(i);int r = RIGHT(i);int largest;//寻找if (l<heapSize && *(arr + l)>*(arr + i))largest = l;elselargest = i;if (r<heapSize && *(arr + r)>*(arr + largest))largest = r;if (largest != i){swap(*(arr + i), *(arr + largest));Max_Heapify(arr, largest, heapSize);}//如果A[i]是最大的,则以i为根的子树已经是最大堆}template<typename T> //建立大顶堆,采用上面大顶堆方法进行优化void Build_Max_Heap(T*arr, size_t heapSize){ //从底部开始进行向上优化for (int i = heapSize / 2 - 1; i >= 0; i--)Max_Heapify(arr, i, heapSize);}template <typename T> //获得最大顶堆,堆排序开始,即元素出堆void HeapSort(T *arr, size_t heapSize){Build_Max_Heap(arr, heapSize);for (int i = heapSize - 1; i > 0; i--){swap(*arr, *(arr + i));Max_Heapify(arr, 0, i);}}}int main(){N = 2;do{N *= 2; //依次增大计算规模srand((unsigned)time(NULL)); //给一个时间种子init();//初始化一次cout << "进行规模为" << N << "的排序" << endl;cout << "原始数组为:";for (int i = 0; i < N; i++){cout << a[i] << " ";}cout << endl;begintimes = clock(); //计时开始MergeSort(0,N-1);QuickSort(0,N-1);MySort::HeapSort<int>(a, N);endtimes = clock(); //计时结束duration = 1000 * (double)(endtimes - begintimes) / CLK_TCK; //总共用时(毫秒)cout << "排序后数组为:";for (int i = 0; i < N; i++){cout << a[i] << " ";}cout << endl;cout << "此次用时为" << duration << "毫秒" << endl << endl << endl;//记录实验结果,注意运行一次手动进行数据转移,清除数据FILE *fpWrite1 = fopen("data1.txt", "a+"); //记录实验结果fprintf(fpWrite1, "%d\n", N);fclose(fpWrite1);FILE *fpWrite2 = fopen("data2.txt", "a+"); //记录实验结果fprintf(fpWrite2, "%d\n", duration);fclose(fpWrite2);} while (duration < 180000); //单次时间小于3分钟return 0;}#include<iostream>#include<stdio.h>#include<time.h>#include<windows.h>#define MAX 10000using namespace std;int N;clock_t begintimes, endtimes; //clock_t为clock()函数返回的变量类型double duration; //运行时间计算//随机生成数函数int number(){int a;a = rand() % 100 + 1; //随机生成1到一万之间的整数return a;}//最朴素算法三重循环void pusu(int **arr, int **brr, int **crr){for (int i = 0; i <= N - 1; i++) {for (int j = 0; j <= N - 1; j++) {for (int k = 0; k <= N - 1; k++) {crr[i][j] += arr[i][k] * brr[k][j];}}}}//Strassen矩阵乘法算法,矩阵分块,仅仅针对2的n次幂次阶处理void gerResultStrassen(int **arr, int **brr, int n, int **crr){ if (n == 1){crr[0][0] += arr[0][0] * brr[0][0];}else{int m = n / 2;int **arr11 = new int*[m];int **arr12 = new int*[m];int **arr21 = new int*[m];int **arr22 = new int*[m];int **brr11 = new int*[m];int **brr12 = new int*[m];int **brr21 = new int*[m];int **brr22 = new int*[m];int **crr11 = new int*[m];int **crr12 = new int*[m];int **crr21 = new int*[m];int **crr22 = new int*[m];for (int i = 0; i < m; ++i){arr11[i] = new int[m];arr12[i] = new int[m];arr21[i] = new int[m];arr22[i] = new int[m];brr11[i] = new int[m];brr12[i] = new int[m];brr21[i] = new int[m];brr22[i] = new int[m];crr11[i] = new int[m];crr12[i] = new int[m];crr21[i] = new int[m];crr22[i] = new int[m];}//获取矩阵//四块矩阵的分别计算//11for (int i = 0; i < m; ++i){for (int j = 0; j < m; ++j){arr11[i][j] = arr[i][j];brr11[i][j] = brr[i][j];}}//22for (int i = m; i < n; ++i){for (int j = m; j < n; ++j){arr22[i - m][j - m] = arr[i][j];brr22[i - m][j - m] = brr[i][j];}}//12for (int i = 0; i < m; ++i){for (int j = m; j < n; ++j){arr12[i][j - m] = arr[i][j];brr12[i][j - m] = brr[i][j];}}//21for (int i = m; i < n; ++i){for (int j = 0; j < m; ++j){arr21[i - m][j] = arr[i][j];brr21[i - m][j] = brr[i][j];}}for (int i = 0; i < m; ++i){for (int j = 0; j < m; ++j){crr11[i][j] = 0;crr12[i][j] = 0;crr21[i][j] = 0;crr22[i][j] = 0;}}//递归分治gerResultStrassen(arr11, brr11, m, crr11); gerResultStrassen(arr12, brr21, m, crr11);gerResultStrassen(arr11, brr12, m, crr12);gerResultStrassen(arr12, brr22, m, crr12);gerResultStrassen(arr21, brr11, m, crr21); gerResultStrassen(arr22, brr21, m, crr21);gerResultStrassen(arr21, brr12, m, crr22); gerResultStrassen(arr22, brr22, m, crr22); //一下是矩阵的分为四块//11for (int i = 0; i < m; ++i){for (int j = 0; j < m; ++j){crr[i][j] += crr11[i][j];}}//22for (int i = m; i < n; ++i){for (int j = m; j < n; ++j){crr[i][j] += crr22[i - m][j - m];}}//12for (int i = 0; i < m; ++i){for (int j = m; j < n; ++j){crr[i][j] += crr12[i][j - m];}}//21for (int i = m; i < n; ++i){for (int j = 0; j < m; ++j){crr[i][j] += crr12[i - m][j];}}//后期处理for (int i = 0; i < m; ++i){delete[] arr11[i];delete[] brr11[i];delete[] crr11[i];delete[] arr12[i];delete[] brr12[i];delete[] crr12[i];delete[] arr21[i];delete[] brr21[i];delete[] crr21[i];delete[] arr22[i];delete[] brr22[i];delete[] crr22[i];}delete[] arr11;delete[] brr11;delete[] crr11;delete[] arr12;delete[] brr12;delete[] crr12;delete[] arr21;delete[] brr21;delete[] crr21;delete[] arr22;delete[] brr22;delete[] crr22;}}//初始化函数void init(int **arr, int **brr, int **crr){//初始化赋值for (int i = 0; i < N; ++i){for (int j = 0; j < N; ++j){arr[i][j]=number();crr[i][j] = 0;}}for (int i = 0; i < N; ++i){for (int j = 0; j < N; ++j){brr[i][j]=number();}}}//输出函数void input(int **arr, int **brr, int **crr){ cout << "矩阵A\n";for (int i = 0; i < N; ++i){for (int j = 0; j < N; ++j){cout << arr[i][j] << " ";}cout << endl;}cout << "矩阵B\n";for (int i = 0; i < N; ++i){for (int j = 0; j < N; ++j){cout << brr[i][j] << " ";}cout << endl;}cout << "相乘后的矩阵C\n";for (int i = 0; i < N; ++i){for (int j = 0; j < N; ++j){cout << crr[i][j] << " ";}cout << endl;}cout << "所用时间为:" << duration << endl;}//主函数int main(){N = 2;//矩阵的阶数do{N = N * 2;int **arr = new int*[N]; //定义数组,分别存放三个矩阵int **brr = new int*[N];int **crr = new int*[N];//获取矩阵for (int i = 0; i < N; ++i){arr[i] = new int[N];brr[i] = new int[N];crr[i] = new int[N];。