递归函数

DFS深度优先算法学习

佐手、 提交于 2019-12-04 14:25:58
刚开始学习算法,参考大佬博客还是有很多不明白的,于是一步步解析,写下笔记记录。 大佬博客地址: https://blog.csdn.net/fuzekun/article/details/85220468 问题描述   n个人参加某项特殊考试。   为了公平,要求任何两个认识的人不能分在同一个考场。   求是少需要分几个考场才能满足条件。 输入格式   第一行,一个整数n(1<n<100),表示参加考试的人数。   第二行,一个整数m,表示接下来有m行数据   以下m行每行的格式为:两个整数a,b,用空格分开 (1<=a,b<=n) 表示第a个人与第b个人认识。 输出格式   一行一个整数,表示最少分几个考场。 样例输入 5 8 1 2 1 3 1 4 2 3 2 4 2 5 3 4 4 5 样例输出 4 样例输入 5 10 1 2 1 3 1 4 1 5 2 3 2 4 2 5 3 4 3 5 4 5 样例输出 5 因为数据量很小可以使用回溯算法。 应用两层回溯: 第一层回溯是将考生放在不同考场里面产生的效果,比如学生3号可以放在教室1和教室2中那么放在那一个教室会产生更好的效果这是一层回溯。 第二层回溯是考生放入以前的考场还是考生自己重新用一个考场。比如考生3号可以放进教室1和教室2,也可以放进教室3。 应用简单的剪枝技巧:

用非递归的方法中序遍历二叉树

半世苍凉 提交于 2019-12-04 10:33:19
写这篇纯属个人兴趣了😂 要遍历二叉树的话优先推荐用递归的方法 在传统的遍历二叉树时,如果要使用递归的方法 前序遍历: void FrontOrder(biTree *s) {   if(s){     printf("%d",s->data);     FrontOrder(s->lchild);     FrontOrder(s->rchild);   } } 中序遍历: void InOrder(biTree *s) {   if(s){     InOrder(s->lchild);     printf("%d",s->data);     InOrder(s->rchild);   } } 后续遍历: void PostOrder(biTree *s) {   if(s){     PostOrder(s->lchild);     PostOrder(s->rchild);     printf("%d",s->data);   } } 用栈的话👇,话不多说,上代码 #include <stdio.h> #define maxsize 24 typedef struct node{ char data; struct node *lchild; struct node *rchild; }biTree; biTree * Q[maxsize]; biTree *

树和二叉树一篇就搞定!

[亡魂溺海] 提交于 2019-12-04 03:42:46
二叉树铺垫——树 前面几篇文章我们主要介绍的线性表,栈,队列,串,等等,都是一对一的 线性结构 ,而今天我们所讲解的 “树” 则是一种典型的 非线性结构 ,非线性结构的特点就是,任意一个结点的直接前驱,如果存在,则一定是唯一的,直接后继如果存在,则可以有多个,也可以理解为一对多的关系,下面我们就先来认识一下树 树的概念 下图我们日常生活中所见到的树,可以看到,从主树干出发,向上衍生出很多枝干,而每一根枝干,又衍生出一些枝丫,就这样组成了我们在地面上可以看到的树的结构,但对于每一个小枝丫来讲,归根结底,还是来自于主树干的层层衍生形成的。 我们往往需要在计算机中解决这样一些实际问题 例如: 用于保存和处理树状的数据,例如家谱,组织机构图 进行查找,以及一些大规模的数据索引方面 高效的对数据排序 先不提一些复杂的功能,就例如对于一些有树状层级结构的数据进行建模,解决实际问题,我们就可以利用 “树” 这种结构来进行表示,为了更符合我们的习惯,我们一般把 “树” 倒过来看,我们就可以将其归纳为下面这样的结构,这也就是我们数据结构中的 “ 树” 树中的常见术语 结点 :包含数据项以及指向其他结点的分支,例如上图中圆 A 中,既包含数据项 A 又指向 B 和 C 两个分支 特别的,因为 A 没有前驱,且有且只有一个,所以称其为根结点 子树 :由根结点以及根结点的所有后代导出的子图称为树的子树

递归理解-汉诺塔问题

梦想与她 提交于 2019-12-03 05:34:51
汉诺塔问题 汉诺塔问题的求解可以巧妙利用递归思想 以下摘自知乎上我认为阐述得很清除回答: 要用程序来解决这个问题,我们先定义一个移动函数:move(移动数,开始柱,中转柱,目标柱), 例如 move(2,A,B,C) 表示将2个盘子从A柱(开始柱)借助B柱(中转柱)移动到C柱(目标柱)。 关于开始柱,中转柱,目标柱这三个概念可以用移动过程中的某个状态来理解, 看下面一张图应该就能明白: 有三种状态的柱子,开始柱,中间柱,目标住,开始柱指的是开始状态时存放所有盘子的柱子,中转柱指的是中间状态时暂时存放n-1个(三层就是3-1个)盘子的柱子, 目标柱指的是盘子最终要移动到的柱子。这里需要注意,开始柱,中转柱,目标柱并不是一成不变的,而是会根据层次的不同而改变。(如果这里暂时不能理解的话,先读下去,再回头你就能明白了)。 接着我们分情况讨论一下盘子的移动: 情况一 当盘子只有1个(调用 move(1,A,B,C))当盘子只有一个的时候, 只要直接将盘子从开始柱移动到目标柱就可以了,并没有中间状态(即不用借助中转柱),在move方法中可以用一句话表示该移动动作 print('A--->C'); 情况二 当盘子有2个(调用 move(2,A,B,C))这个情况分三个步骤进行: step1. 把除了最大的盘子之外的盘子从A移到BA--->B (开始柱--->中转柱) 【相当于调用 move(1

PHP实现二叉树的深度优先遍历(前序、中序、后序)和广度优先遍历(层次)

大城市里の小女人 提交于 2019-12-03 04:29:51
前言: 深度优先遍历 :对每一个可能的分支路径深入到不能再深入为止,而且每个结点只能访问一次。要特别注意的是,二叉树的深度优先遍历比较特殊,可以细分为先序遍历、中序遍历、后序遍历。具体说明如下: 前序遍历:根节点->左子树->右子树 中序遍历:左子树->根节点->右子树 后序遍历:左子树->右子树->根节点 广度优先遍历 :又叫层次遍历,从上往下对每一层依次访问,在每一层中,从左往右(也可以从右往左)访问结点,访问完一层就进入下一层,直到没有结点可以访问为止。 例如对于一下这棵树: 深度优先遍历: 前序遍历:10 8 7 9 12 11 13 中序遍历:7 8 9 10 11 12 13 后序遍历:7 9 8 11 13 12 10 广度优先遍历: 层次遍历:10 8 12 7 9 11 13 二叉树的深度优先遍历的非递归的通用做法是采用栈,广度优先遍历的非递归的通用做法是采用队列。 深度优先遍历: 1、前序遍历: /** * 前序遍历(递归方法) */ private function pre_order1( $root ) { if ( ! is_null( $root )) { //这里用到常量__FUNCTION__,获取当前函数名,好处是假如修改函数名的时候,里面的实现不用修改 $function = __FUNCTION__; echo $root -> key . "

递归和循环----青蛙跳台阶

戏子无情 提交于 2019-12-03 04:24:26
青蛙跳台阶 题目 一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个n级的台阶总共有多少种跳法? 思路: 只有1级台阶,只有一种跳法 如果有2级台阶,那么就有两种跳法 如果有n(n>2)级台阶的话,n级台阶的跳法可以看成函数 f (n),那么第一次跳的时候有两种选择,一是跳1级,那么这种跳法的数目就等于 f (n-1)。二是跳2级的话,那么这种跳法的数目就等于 f (n-2)。所以n级台阶的跳法应该是等于 f (n-1) + f (n-2)。 /** * 递归写法 * 青蛙跳台阶 * @param n 几级台阶 * @return */ public static int frogStep(int n){ if (n == 1){ return 1; } if (n == 2){ return 2; } else{ return frogStep(n-1) + frogStep(n-2); } } /** * 循环写法 * @param n * @return */ public static int frogStepCycle(int n){ if (n ==1){ return 1; } if (n == 2){ return 2; } int FibOne = 1; int FibTwo = 1; int FibN = 0; for (int i = 1; i

递归与动态规划---汉诺塔问题

眉间皱痕 提交于 2019-12-03 03:19:51
【问题】   给定一个整数n,代表汉诺塔游戏中从小到大放置的n个圆盘,假设开始时所有的圆盘都放在左边的柱子上,想按照汉诺塔游戏的要求把所有的圆盘都移到右边的柱子上,实现函数打印最优移动轨迹。 【举例】   n = 2时,打印:   move from left to mid   move from left to right   move from mid to right 【基本思路】 假设有left柱子,mid柱子和right柱子,都在left柱子的圆盘1~i完全移动到right,最优的过程为: 将圆盘1~i-1从left移动到mid 将圆盘i从left移动到right 将圆盘1~i-1从mid移动到right 如果盘子只有一个,直接从left移动到right即可 下面是使用python3.5实现的代码 #汉诺塔问题 def hanoi (n) : def func (n, left, mid, right) : if n == 1 : print( "move from " + left + " to " + right) else : func(n- 1 , left, right, mid) func( 1 , left, mid, right) func(n- 1 , mid, left, right) if n < 1 : return return func(n,

递归和循环----汉诺塔

偶尔善良 提交于 2019-12-03 03:19:37
题目: 汉诺塔问题是一个经典的问题。汉诺塔(Hanoi Tower),又称河内塔,源于印度一个古老传说。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,任何时候,在小圆盘上都不能放大圆盘,且在三根柱子之间一次只能移动一个圆盘。问应该如何操作? 有两个限制条件,第一个是每次只能够移动一个圆盘,第二个是大圆盘只能在小圆盘下面 思路: 如果1个盘子,你直接可以从第一根柱子移动到最后一根柱子就可以了 如果有两个盘子,第一你需要先把上面的盘子,从start柱子移动到middle柱子去,第二需要把下面的盘子,移动到最后那个盘子中最后那个柱子上,最后把上面的盘子从middle柱子上移动到end柱子上。 假设n个盘子,即函数f(n),第一步把上面的n-1盘子通过end那个空柱子最终移动到middle柱子,第二步把下面的大盘子移动到end柱子上去,第三步把上面的n-1个盘子通过start这个空柱子按照限制条件移动到end柱子上去 /** * 汉诺塔 * * @param n 盘子的数量 * @param start 开始柱子 * @param middle 中介柱子 也就是那个空闲柱子 * @param end 放结果柱子 也就是你通过移动,将这个盘子移动到哪个柱子上 *

笔记:数据结构与算法

隐身守侯 提交于 2019-12-03 02:31:02
数据结构与算法 常用排序算法 实现比较丑陋,勿喷啊 冒泡排序 :从前向后比较相邻的元素。如果前一个比后一个大,就交换他们两个,每一轮把一个最大的数运到数组最后面。 public static int[] sort(int[] arr) { int len = arr.length; // 冒泡总次数 for (int i = 1; i < len; i++) { boolean flag = true; // 每次冒泡过程 for (int j = 0; j < len - i; j++) { if (arr[j] > arr[j + 1]) { MyUtils.swap(arr, j, j + 1); flag = false; } } if (flag) { // 如果一个冒泡过程没改变,退出返回已经有序 break; } } return arr; } 选择排序 :每次从未排序数组中找一个最小的元素,放到以有序数组后面 public static int[] sort(int[] arr) { int len = arr.length; // 选择次数 for (int i = 0; i < len - 1; i++) { int min = i; // 每次选择过程 for (int j = i + 1; j < len; j++) { if (arr[j] < arr

N皇后解题报告(14阶递归方式)

匿名 (未验证) 提交于 2019-12-03 00:21:02
n 1 queen[] 2 1queen[t]==queen[i]abs(queen[t]-queen[i])==abs(t-i) vc6.0 c++ #include<iostream> #include<cstdio> #include<cmath> usingnamespace std; #define N 15 intsum=0; intn; intqueen[N]; boolplace(int t)//放置判断函数(判断将该皇后放置的这个位置与前方的其他皇后有无冲突) { for(int i=1;i<t;i++) if(abs(i-t)==abs(queen[i]-queen[t])||queen[i]==queen[t])//核心(利用坐标判断) return false; return true; } intsearch(int t)//查找函数(每一层)从第一层开始,也是递归的本体 { if(t>n&&n>0) sum++;//放置了n行 for(int i=1;i<=n;i++) { queen[t]=i;//将第t行的皇后位置确定为i if(place(t))//如果当这时与前方的皇后无冲突 search(t+1);//查找下一个 } return sum; } intmain() { while(~scanf("%d",&n))//多次测试 { sum=0;/