递归算法

快速排序,归并排序,堆排序的数组和单链表实现

和自甴很熟 提交于 2019-12-03 07:11:42
原文链接: https://www.cnblogs.com/DarrenChan/p/8807112.html 这三个排序的时间复杂度都是O(nlogn),所以这里放到一起说。 回到顶部 1. 快速排序 # 快速排序(英语:Quicksort),又称划分交换排序(partition-exchange sort),通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。 步骤为: 从数列中挑出一个元素,称为"基准"(pivot), 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。 递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。 最优时间复杂度:O(nlogn) 最坏时间复杂度:O(n2) 稳定性:不稳定 从一开始快速排序平均需要花费O(n log n)时间的描述并不明显

算法第三章作业

谁说胖子不能爱 提交于 2019-12-03 07:10:06
1.对动态规划算法的理解 动态规划与分治法相似,都是将待求解的问题分解成若干个子问题,先求解子问题,然后从这些子问题的解中得到原问题的解。但是区别在于动态规划每个子问题并非独立,而是相互有联系。 动态规划可以用表格存储每个子问题的最优解,有需求时使用。 2.分别列出编程题1、2的递归方程 1.m[i]=max{m[i-1]+1|a[k]<a[i]} 1<=k<i 2.m[i]=min{c[i][k]+m[k]} i<k<=n 3. 说明结对编程情况 一同推理出递归方程,递归方程一推出就可以轻松解决问题。彼此交流学习经验。 来源: https://www.cnblogs.com/xiaozhao-/p/11782403.html

动态规划

为君一笑 提交于 2019-12-03 04:09:20
动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若⼲个⼦问题。但是经分解得到的⼦问题往往不是互相独⽴的 动态规划策略通常⽤于求解最优化问题。 – 在这类问题中,可能会有许多可⾏解。每⼀个解都对应于⼀个值,我们希望找到具有最优值的那个解,即最优解。 – 动态   • 在⼀定条件下,当前阶段的状态和下⼀阶段的状态之间的转移。 – 规划   • 建⽴状态转移⽅程(或称各阶段间的递推关系式),将各个阶段的状态以表格式⽅法存储。   • 表格式⽅法:⽤⼀个表来记录所有已解决的⼦问题的解 过程: • 阶段 stage   – 将所给问题的过程,按时间或空间特征分解成若⼲相互联系的阶段,以便按次序去求每阶段的解。 • 状态 state   – 各阶段开始时的客观条件叫做状态。 • 决策 decision   – 当各阶段的状态确定以后,就可以做出不同的决定,从⽽确定下⼀阶段的状态,这种决定称为决策。 • 状态转移 transition   – 根据上⼀阶段的状态和决策来导出本阶段的状态。 在分治法求解时,有些问题被重复计算了许多次 如果能够保存已解决的⼦问题的答案,⽽在需要时再找出已求得的答案,就可以避免⼤量重复计算,从⽽得到多项式时间算法。 基本要素 • 最优⼦结构(optimal substructure)   – 原问题的最优解包含了⼦问题的最优解。   – 该性质使我们能够以

汉诺塔(Hanoi)问题递归&非递归的C++实现及总结

时间秒杀一切 提交于 2019-12-03 03:21:24
汉诺塔(Hanoi)问题递归&非递归的C++实现及总结 由于刚入门不算很久,所以就那汉诺塔这种简单问题来练下手啦~~ 【汉诺塔问题内容】 (虽然路人皆知但还是写一下好了。。。)   相传在古印度圣庙中,有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置上,有三根杆(编号A、B、C),在A杆自下而上、由大到小按顺序放置64个金盘(如下图)。游戏的目标:把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。操作规则:每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于A、B、C任一杆上。   详细的背景可以去 百度百科 自己看~~ 【递归实现】 //汉诺塔问题最简单最经典的解决方法当然是递归解决啦~~ #include <iostream> using namespace std ; void hanoi( int n, int a, int b, int c) { if (n > 0 ) { hanoi(n- 1 , a, c, b); cout << "move " << a << " to " << b << endl; hanoi(n- 1 , c, b, a); } } int main() { int n; cin >> n; hanoi(n, 1 , 2 , 3 ); return 0 ; } //非常简单就搞定了

《程序员的数学》:汉诺塔问题(Hanoi问题)的递归算法与非递归算法总结

佐手、 提交于 2019-12-03 03:18:05
如果对汉诺塔算法的理解有困难,建议查看 《程序员的数学》:第6章 递归——自己定义自己 这一章作者详细用图形介绍了汉诺塔递归算法,便于理解,茅塞顿开! 现对该算法从递归和非递归两个方面做如下总结: 1.递归算法分析 如下, 设A上有n个盘子。 如果n=1,则将圆盘从A直接移动到C。 如果n=2,则: (1)将A上的n-1(等于1)个圆盘移到B上; (2)再将A上的一个圆盘移到C上; (3)最后将B上的n-1(等于1)个圆盘移到C上。 如果n=3,则: A)将A上的n-1(等于2,令其为n`)个圆盘移到B(借助于C),步骤如下: (1)将A上的n`-1(等于1)个圆盘移到C上。 (2)将A上的一个圆盘移到B。 (3)将C上的n`-1(等于1)个圆盘移到B。 B)将A上的一个圆盘移到C。 C)将B上的n-1(等于2,令其为n`)个圆盘移到C(借助A),步骤如下: (1)将B上的n`-1(等于1)个圆盘移到A。 (2)将B上的一个盘子移到C。 (3)将A上的n`-1(等于1)个圆盘移到C。到此,完成了三个圆盘的移动过程。 从上面分析可以看出,当n大于等于2时, 移动的过程可分解为三个步骤: 第一步 把A上的n-1个圆盘移到B上; 第二步 把A上的一个圆盘移到C上; 第三步 把B上的n-1个圆盘移到C上; 其中第一步和第三步是类同的。 当n=3时,第一步和第三步又分解为类同的三步,即把n`

【算法笔记】使用栈实现汉诺塔(Hanoi)经典算法

北慕城南 提交于 2019-12-03 03:16:19
汉诺塔(Hanoi)算法,应该是每一个程序员都会学习到的递推算法之一,汉诺塔是一个很著名的智力题,但是这里就不科普它的由来了,我们直接进入正题。 如上图,假设A棒有五个原盘,依次移动,每次移动一块,小的永远只能在上面,最终移动到C棒上,如何用算法实现呢? 从这里移动的逻辑我们很容易发现,A帮不就像一个栈吗,栈顶必须先出,网上看过很多汉诺塔算法,很少涉及到用栈实现,的确,算法拿出来了,用什么都一样,在我学习的时候,教材上是用的char,直接模拟推算,没用真正移动数据实现真正的Hanoi思想,所以,琢磨了一会,写了一个用栈实现的算法。 首先,既然是栈,为了方便跟踪,写了一个自己的MyStack包装了一下Java的Stack,贴上代码: class MyStack{ private String name; private Stack<Integer> data; public MyStack (String name){ this .name=name; data= new Stack<>(); } public String getName (){ return this .name; } public void push ( int data){ if (! this .data.isEmpty()&& this .data.peek()<data){ System. out

归和迭代的区别、联系、优缺点

只愿长相守 提交于 2019-12-03 02:48:19
1.概念区分 递归 的基本概念: 程序调用自身的编程技巧称为递归,是函数自己调用自己. 一个函数在其定义中直接或间接调用自身的一种方法,它通常把一个大型的复杂的问题转化为一个与原问题相似的规模较小的问题来解决,可以极大的减少代码量.递归的能力在于用有限的语句来定义对象的无限集合. 使用递归要注意的有两点: 1)递归就是在过程或函数里面调用自身; 2)在使用递归时,必须有一个明确的递归结束条件,称为递归出口. 递归分为两个阶段: 1)递推:把复杂的问题的求解推到比原问题简单一些的问题的求解; 2)回归:当获得最简单的情况后,逐步返回,依次得到复杂的解. 迭代 : 利用变量的原值推算出变量的一个新值.如果递归是自己调用自己的话,迭代就是A不停的调用B. 2.辩证看递归和迭代 所谓递归,简而言之就是应用程序自身调用自身,以实现层次数据结构的查询和访问。递归的使用可以使代码更简洁清晰,可读性更好(对于初学者到不见得),但由于递归需要系统堆栈,所以空间消耗要比非递归代码要大很多,而且,如果递归深度太大,可能系统资源会不够用。 往往有这样的观点:能不用递归就不用递归,递归都可以用迭代来代替。 诚然,在理论上,递归和迭代在时间复杂度方面是等价的(在不考虑函数调用开销和函数调用产生的堆栈开销),但实际上递归确实效率比迭代低,既然这样,递归没有任何优势,那么是不是就,没有使用递归的必要了

二叉排序树查找递归 非递归

我与影子孤独终老i 提交于 2019-12-03 02:41:38
算法思想 首先将待查关键字key与根结点关键字t进行比较,如果: 1)key=t,则返回根结点地址; 2)key<t,则进一步查找左子树; 3)key>t,则进一步查找右子树; 对应的递归算法如下: BSTree SearchBST(BSTree bst, ElemType key) { if (!bst) return NULL; else if (bst->key == key) return bst; else if (bst->key > key) return SearchBST(bst->lchild, key); else return SearchBST(bst->rchild, key); } 对应的非递归算法如下: BSTNode *BST_Search(Bitree T, ElemType key, BSTNode *&p) { p = NULL;//p指向待查找结点的双亲,用于插入和删除操作中 while(T!=NULL&&key!=T->data){ if (key < T->data) T = T->lchild; else T = T->rchild; } } 来源: https://www.cnblogs.com/brainstorm-yc/p/11774390.html

二叉树后序遍历 递归 非递归

让人想犯罪 __ 提交于 2019-12-03 02:39:08
后序遍历的操作如下: 1)后序遍历左子树; 2)后序遍历右子树; 3)访问根节点; 对应的递归算法如下: void PostOrder(Bitree T) { if (T != NULL) { PostOrder(T->lchild); PostOrder(T->rchild); visit(T); } } 非递归算法算法思想:当用堆栈来存储结点时,必须分清返回根结点时是从左子树返回的 还是从右子树返回的。所以,使用辅助指针r,指向其最近访问过的结点。也可在结点 增加一个标志域,记录是否已被访问。 对应的非递归算法如下: void PostOrder(Bitree T) { InitStack(S); p = T; r = NULL; while (p || !IsEmpty(S)) { if (p) { push(S, p); p = p->lchild; } else { Get(S, p); if (p->rchild&&p->rchild != r) { p = p->rchild; push(S, p); p = p->lchild; } else { pop(S, p); visit(p->data); r = p; p = NULL; } } } } 来源: https://www.cnblogs.com/brainstorm-yc/p/11774288.html

汉诺塔——递归

别说谁变了你拦得住时间么 提交于 2019-12-03 02:36:35
汉诺塔(Hanoi Tower),又称河内塔,源于印度一个古老传说。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,任何时候,在小圆盘上都不能放大圆盘,且在三根柱子之间一次只能移动一个圆盘。问应该如何操作? 假如有三根柱子: 1、过程分析: (1)当只有两个盘子的时候(移动两次): a--b a--c b--c (2)当有三个盘子的时候: 应该考虑将最上层的两个较小的盘子先从a移动到b,然后将a上的最大的盘子(最底层)移动到c。 将最上层的盘子移到c; 中间的盘子移到b; 再将第一步的c上的盘子移动到b; 至此,最上层的两个盘子已经成功的移动到了b。 现在,需要将a柱子上的最下层的盘子移动到c柱子上。 然后再将a柱子作为辅助位,b柱子作为起点,c柱子作为终点,将b上的两个盘子移动到c即可。 ...... (3)当有n个盘子的时候,需要先将c柱子作为辅助位,a为起始位,b为终点。将上面的n-1个盘子从a移动到b。 然后将最下层的盘子从a移动到c。 最后将b上面的n-1个盘子从b移动到c。 2、代码实现: #include<stdio.h> void hanoi(int n,char A,char B,char C){//n代表 a柱子上面的盘子数量 if(n==1)