递归算法

二叉树的非递归遍历

牧云@^-^@ 提交于 2020-01-29 04:41:47
二叉树是一种非常重要的数据结构,很多其它数据结构都是基于二叉树的基础演变而来的。对于二叉树,有前序、中序以及后序三种遍历方法。因为树的定义本身就是递归定义,因此采用递归的方法去实现树的三种遍历不仅容易理解而且代码很简洁。而对于树的遍历若采用非递归的方法,就要采用栈去模拟实现。在三种遍历中,前序和中序遍历的非递归算法都很容易实现,非递归后序遍历实现起来相对来说要难一点。 一.前序遍历 前序遍历按照“根结点-左孩子-右孩子”的顺序进行访问。 1.递归实现 void preOrder1(BinTree *root) //递归前序遍历 { if(root!=NULL) { cout<<root->data<<" "; preOrder1(root->lchild); preOrder1(root->rchild); }} 2.非递归实现 根据前序遍历访问的顺序,优先访问根结点,然后再分别访问左孩子和右孩子。即对于任一结点,其可看做是根结点,因此可以直接访问,访问完之后,若其左孩子不为空,按相同规则访问它的左子树;当访问其左子树时,再访问它的右子树。因此其处理过程如下: 对于任一结点P: 1)访问结点P,并将结点P入栈; 2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);若不为空,则将P的左孩子置为当前的结点P; 3

10 - 递归

我们两清 提交于 2020-01-28 12:54:07
1. 一个应用场景 2. 概述 递归就是方法自己调用自己 递归需要遵守的重要规则 执行一个方法时,就创建一个新的受保护的独立空间(栈空间) 方法的局部变量是独立的,不会相互影响;但如果方法中使用的是 引用类型变量 (比如数组),就会 共享 该引用类型的数据 递归必须向退出递归的条件逼近,即该函数所处理的数据规模必须在递减,否则就是无限递归,出现 StackOverflowError 当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者返回时,该方法也就执行完毕 理解 - 方法调用 逻辑 内存 https://www.jianshu.com/p/e7a22923867f 3. 过程 当在一个函数运行期间,调用另一个函数时,在运行被调用函数之前,系统需要先完成3件事 将所有实参,返回地址等信息传递给被调用函数保存 为被调用函数的局部变量分配存储区 将控制转移到被调函数的入口 从被调用函数返回调用函数之前,系统也应完成3件工作 保存被调函数的计算结果 释放被调函数的数据区 依照被调函数保存的返回地址将控制转移到调用函数 当有多个函数构成嵌套调用时,按照"后调用先返回"的原则,上述函数之间的信息传递和控制转移必须通过"栈"来实现,即系统将整个程序运行时所需的数据空间安排在一个栈中,每当调用一个函数,就为它在栈顶分配一个存储区

【数据结构与算法】二叉树的遍历

让人想犯罪 __ 提交于 2020-01-28 09:52:48
前序遍历是指,对于树中的任意节点来说,先打印这个节点,然后再打印它的左子树,最后打印它的右子树。 中序遍历是指,对于树中的任意节点来说,先打印它的左子树,然后再打印它本身,最后打印它的右子树。 后序遍历是指,对于树中的任意节点来说,先打印它的左子树,然后再打印它的右子树,最后打印这个节点本身。 层次遍历是指,对树中的节点一层一层的打印,其实就是广度优先算法(BFS)。 一、前序遍历 LeetCode: https://leetcode-cn.com/problems/binary-tree-preorder-traversal/ C语言代码实现: 1 /** 2 * Definition for a binary tree node. 3 * struct TreeNode { 4 * int val; 5 * struct TreeNode *left; 6 * struct TreeNode *right; 7 * }; 8 */ 9 10 11 /** 12 * Note: The returned array must be malloced, assume caller calls free(). 13 */ 14 15 /* 获取树的节点个数 */ 16 int getTreeNodeLen(struct TreeNode* root) 17 { 18 if (root

oracle中 connect by prior 递归算法

半腔热情 提交于 2020-01-28 05:05:53
Oracle中start with...connect by prior子句使用方法 connect by 是结构化查询中用到的,其基本的语法是: select ... from tablename start with 条件1 connect by 条件2 where 条件3; 例: select * from table start with org_id = 'HBHqfWGWPy' connect by prior org_id = parent_id; 简单说来是将一个树状结构存储在一张表里,比方一个表中存在两个字段: org_id,parent_id那么通过表示每一条记录的parent是谁,就能够形成一个树状结构。 用上述语法的查询能够取得这棵树的全部记录。 当中: 条件1 是根结点的限定语句,当然能够放宽限定条件,以取得多个根结点,实际就是多棵树。 条件2 是连接条件,当中用PRIOR表示上一条记录,比方 CONNECT BY PRIOR org_id = parent_id就是说上一条记录的org_id 是本条记录的parent_id,即本记录的父亲是上一条记录。 条件3 是过滤条件,用于对返回的全部记录进行过滤。 简介例如以下: 早扫描树结构表时,须要依此訪问树结构的每一个节点,一个节点仅仅能訪问一次,其訪问的过程例如以下: 第一步:从根节点開始; 第二步

快排算法的非递归实现

怎甘沉沦 提交于 2020-01-28 02:26:10
我的Partition(),功能是以传入的finish序号的数的数值为分界线,把数组分成两部分,前半的数值都比他小,其余的都比那个值大,并返回分界的序号。这个过程中就操作数组换位,具体见算法注释。 而sort函数的工作就是反复的利用Partition函数查找那个中间值,在这个过程中就对数组进行操作,将其分成两段。把一个大的数列改为一个个小的,甚至长度为一的序列,当达到这个条件时,实际上已经排好序了。 这一点上和递归函数没区别,因为算法一样。建议按序看我的注释,并且自己举个数列的例子来操作。可以先看Partition()的,因为两个函数是独立的。 可以,我就写写算法了。因为这个代码是算法代码而其年久失修,你自己人工序列试试就知道了。关键在后面的交换顺序并找到分界点的地方 Sort() { stack s;//构造栈 start =arr;//arr为要排序的序列 finish = m_arr + m_len - 1; pivot = Partition(start, finish);//找到一个位置,使其前面的比他小,后面的比他大 s.push(pivot+1); // 后半段首尾存储仅存储序列号 s.push(finish); s.push(start); // 前半段首尾存储仅存储序列号 s.push(pivot-1); while (!s.empty())/

二叉树遍历 递归非递归

霸气de小男生 提交于 2020-01-27 22:06:12
二叉树是一种非常重要的数据结构,很多其它数据结构都是基于二叉树的基础演变而来的。对于二叉树,有前序、中序以及后序三种遍历方法。因为树的定义本身就是递归定义,因此采用递归的方法去实现树的三种遍历不仅容易理解而且代码很简洁。而对于树的遍历若采用非递归的方法,就要采用栈去模拟实现。在三种遍历中,前序和中序遍历的非递归算法都很容易实现,非递归后序遍历实现起来相对来说要难一点。 一.前序遍历 前序遍历按照“根结点-左孩子-右孩子”的顺序进行访问。 1.递归实现 void preOrder1(BinTree *root) //递归前序遍历 { if(root!=NULL) { cout<<root->data<<" "; preOrder1(root->lchild); preOrder1(root->rchild); }} 2.非递归实现 根据前序遍历访问的顺序,优先访问根结点,然后再分别访问左孩子和右孩子。即对于任一结点,其可看做是根结点,因此可以直接访问,访问完之后,若其左孩子不为空,按相同规则访问它的左子树;当访问其左子树时,再访问它的右子树。因此其处理过程如下: 对于任一结点P: 1)访问结点P,并将结点P入栈; 2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);若不为空,则将P的左孩子置为当前的结点P; 3

数据结构——递归(回溯算法实现八皇后问题)

a 夏天 提交于 2020-01-27 17:32:34
递归——回溯算法 八皇后问题介绍 八皇后问题,是一个古老而著名的问题,是回溯算法的经典案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8x8国际象棋棋盘上拜访8个皇后,使其不能够相互攻击,即:任意两个皇后都不能够处于同一行,同一列,同一斜线上,问共有多少种摆法? 解题思路: 1、第一个皇后先放在第一列上 2、第二个皇后在放在第二行的第一列上,然后判断是否符合条件,如果不符合,放在第二列,第三列。。。 如果符合,那么继续 3、继续第三个皇后,还是从第一列开始,然后第二列。。。当到最后第8个皇后也放在一个不冲突的位时,证明得到了一个正确的解 4、当有一个正确的解后,在栈退回到上一个栈时,回溯开始,最后就会将第一个皇后在第一列中所有解全部得到 5、然后在回头继续将第一个皇后放到第一行的第二列上,继续上面操作 注:我们通过一个一维数组就可以来解出八皇后的所有解,数组下标值可以认为是行,每个下标值对应的数据是在这一行中,皇后所在的列。因为数组下标为0,所以我们将行和列都从0开始 写三个方法: 1、用来放置皇后的方法 2、用来判断当前放置的皇后与已经放置的皇后是否冲突 3、打印方法 代码: package cn . littleworm ; /* 八皇后问题: 任意两个皇后不能够出现在同一行,同一列,同意斜线上 解题思路: 1、第一个皇后先放在第一列上 2

【算法】递归算法---作为树的基础知识点【待学习】

只愿长相守 提交于 2020-01-27 09:48:38
https://blog.csdn.net/feizaosyuacm/article/details/54919389 例题: https://blog.csdn.net/Leo1120178518/article/details/102703350 https://blog.csdn.net/qq_34039315/article/details/78679029 1.递归算法解决问题的特点: (1) 递归就是在过程或函数里调用自身。 (2) 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。 (3) 递归算法解题通常显得很简洁,但递归算法解题的运行效率较低。所以一般不提倡用递归算法设计程序。 (4) 在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成 栈溢出 等。所以一般不提倡用递归算法设计程序。 2.要求: 递归算法所体现的“重复”一般有三个要求: 一是每次调用在规模上都有所缩小(通常是减半); 二是相邻两次重复之间有紧密的联系,前一次要为后一次做准备( 通常前一次的输出就作为后一次的输入 ); 三是在问题的规模极小时必须用直接给出解答而不再进行递归调用,因而每次递归调用都是有条件的(以规模未达到直接解答的大小为条件),无条件递归调用将会成为死循环而不能正常结束。 3.递归算法的实现(3点:1.入参和递归参数 2.算法 3

函数参数,返回值,递归函数

人走茶凉 提交于 2020-01-27 03:53:47
函数进阶 目标 函数参数和返回值的作用 函数的返回值 进阶 函数的参数 进阶 递归函数 01. 函数参数和返回值的作用 函数根据 有没有参数 以及 有没有返回值 ,可以 相互组合 ,一共有 4 种 组合形式 无参数,无返回值 无参数,有返回值 有参数,无返回值 有参数,有返回值 定义函数时, 是否接收参数,或者是否返回结果 ,是根据 实际的功能需求 来决定的! 如果函数 内部处理的数据不确定 ,就可以将外界的数据以参数传递到函数内部 如果希望一个函数 执行完成后,向外界汇报执行结果 ,就可以增加函数的返回值 1.1 无参数,无返回值 此类函数,不接收参数,也没有返回值,应用场景如下: 只是单纯地做一件事情 ,例如 显示菜单 在函数内部 针对全局变量进行操作 ,例如: 新建名片 ,最终结果 记录在全局变量 中 注意: 如果全局变量的数据类型是一个 可变类型 ,在函数内部可以使用 方法 修改全局变量的内容 —— 变量的引用不会改变 在函数内部, 使用赋值语句 才会 修改变量的引用 1.2 无参数,有返回值 此类函数,不接收参数,但是有返回值,应用场景如下: 采集数据,例如 温度计 ,返回结果就是当前的温度,而不需要传递任何的参数 1.3 有参数,无返回值 此类函数,接收参数,没有返回值,应用场景如下: 函数内部的代码保持不变,针对 不同的参数 处理 不同的数据 例如 名片管理系统 针对

【LeetCode算法修炼指南】—— 96.不同的二叉搜索树

末鹿安然 提交于 2020-01-26 23:34:14
1. 题目 原题链接 给定一个整数 n,求以 1 … n 为节点组成的二叉搜索树有多少种? 示例: 输入: 3 输出: 5 解释: 给定 n = 3, 一共有 5 种不同结构的二叉搜索树: 1 3 3 2 1 \ / / / \ \ 3 2 1 1 3 2 / / \ \ 2 1 2 3 1.1. 要点 掌握二叉搜索树 假定每一个数字为根结点,并将剩余的数组分配到左右两边继续构造子树。 此时每一个根结点构成二叉树的数量总和为 左边*右边 。 1.2. 递归 这个版本的实现也是勉勉强强的通过的LeetCode,但是性能非常差。 但是毕竟用了二叉树递归特性来实现,所以还是体会一下吧。 1.2.1. 代码片段 func numTrees ( n int ) int { if n == 0 { return 0 } var numTreesMap = make ( map [ string ] int , 0 ) //如果不用一个hash map来记录已经运算过的结果,直接就导致运算超时。 return numTreesHelper ( 1 , n , numTreesMap ) //注意边界位置[1...n] } func numTreesHelper ( left , right int , numTreesMap map [ string ] int ) int { if left