二叉树遍历

二叉树前序遍历、中序遍历、后序遍历、层序遍历的直观理解

巧了我就是萌 提交于 2019-11-28 17:44:27
0. 写在最前面 复习到二叉树,看到网上诸多博客文章各种绕,记得头晕。个人觉得数学、算法这些东西都是可以更直观简洁地表示,然后被记住的,并不需要靠死记硬背。 本文的程序基本来源于《大话数据结构》,个人感觉是一本非常好的书,推荐去看。 1. 为什么叫前序、后序、中序? 一棵二叉树由根结点、左子树和右子树三部分组成,若规定 D、L、R 分别代表遍历根结点、遍历左子树、遍历右子树,则二叉树的遍历方式有 6 种:DLR、DRL、LDR、LRD、RDL、RLD。由于先遍历左子树和先遍历右子树在算法设计上没有本质区别,所以,只讨论三种方式: DLR--前序遍历(根在前,从左往右,一棵树的根永远在左子树前面,左子树又永远在右子树前面 ) LDR--中序遍历(根在中,从左往右,一棵树的左子树永远在根前面,根永远在右子树前面) LRD--后序遍历(根在后,从左往右,一棵树的左子树永远在右子树前面,右子树永远在根前面) 需要注意几点: 1 根是相对的,对于整棵树而言只有一个根,但对于每棵子树而言,又有自己的根。比如对于下面三个图,对于整棵树而言,A是根,A分别在最前面、中间、后面被遍历到。而对于D,它是G和H的根,对于D、G、H这棵小树而言,顺序分别是DGH、GDH、GHD;对于C,它是E和F的根,三种排序的顺序分别为: CEF、ECF、EFC。是不是根上面的DLR、LDR、LRD一模一样呢~~ 2

彻底理解递归,从递归的本质说起!

旧街凉风 提交于 2019-11-28 17:44:23
遍历二叉树,是学习树这种数据结构首先要理解的一种基本操作。比较简单地方式就是用递归去遍历,鉴于递归这种调用方法有一定的特殊性,今天还是想来讲讲怎么去理解递归遍历。本文针对想理解递归的过程的朋友,因为本人在学到这一部分的时候也纠结了很久,其实只要理解了过程,那以后写递归的代码再也不用“心虚”了,因为那个过程是可预测的,可证明的。 递归调用的特殊性在于自己调用自己,给人一种迷茫感,如果是递归调用“一次”,那还相对好理解,比如求阶乘的递归算法, int F(int n) { if(n==0)//递归边界 return 1; return n*F(n-1);//递归公式 } 一层一层调用,知道递归结束条件成立,再一层一层返回;但如果像二叉树是递归调用“两次”,似乎理解起来就不是很容易了。 void preorder(bintree t){ if(t){ printf("%c ",t->data); preorder(t->lchild); preorder(t->rchild); } } 对于一颗如下的二叉树,它的前序遍历顺序该怎么理解呢?我们今天来好好理一遍它的过程。 可以把递归看成是自己调用另一个和自己功能一样,但是函数名不同的函数来理解,或许看得更清楚明白,下面我们来看看这个前序遍历的过程是怎样的。 首先,我们记上面这个函数为F1,表示外层的函数,内层函数表示下一层的函数

二叉树的遍历非递归实现

断了今生、忘了曾经 提交于 2019-11-28 15:15:29
二叉树的遍历非递归实现 二叉树的非递归遍历使用栈来实现 由于才用先跟序,遇到节点就应该访问,下一步应该沿着该树的左支下行。 但节点的又支还没有访问,因此需要记录,将又节点压入栈中。 遇到空树就溯回,取出栈中的一个又分支,像一颗二叉树一样遍历它。 代码: 1 def preorder(t, proc): 2 s = Stack() 3 while t is not None or s not s.is_empty(): 4 while t is not None: 5 proc(t.data) 6 if t.right: 7 s.push(t.right) 8 t = t.left 9 t = s.pop() 来源: https://www.cnblogs.com/yang-he/p/11411961.html

别再翻了,面试二叉树看这 11 个就够了~

此生再无相见时 提交于 2019-11-28 14:29:22
写在前边 数据结构与算法: 不知道你有没有这种困惑,虽然刷了很多算法题,当我去面试的时候,面试官让你手写一个算法,可能你对此算法很熟悉,知道实现思路,但是总是不知道该在什么地方写,而且很多边界条件想不全面,一紧张,代码写的乱七八糟。如果遇到没有做过的算法题,思路也不知道从何寻找。面试吃了亏之后,我就慢慢的做出总结,开始分类的把数据结构所有的题型和解题思路每周刷题做出的系统性总结写在了 Github。欢迎关注和 star: 「 数据结构与算法仓库 」 PS:如果你刚刚在学习数据结构和算法,请务必把最简单的题弄懂,所有的入门的数据结构与算法从简单到复杂进行了全面的梳理。 「 初学者必会的 30 道数据结构与算法 」 如果你对数据结构和算法有了一定的了解和认识,上边的入门算法题已经可以轻松实现,那么可以尝试着解决 LeetCode 上总结的 30 道题,我把解题思路、测试用例、代码实现做了详细的整理,建议先自己尝试的解决哦,收藏 + 关注,欢迎 Star。「 必会的 30 道 LeetCode 经典算法题 」 如果你正在面试,经典的《剑指offer》所有的面试代码实现 (JavaScript 版)放在 Github 仓库,可自行查看。Github 地址「 剑指 offer 所有题目 JavaScript 版解题思路、总结、代码测试。✍️✍️✍️ 」 网络协议原理: 除了算法之外

树和二叉树

时间秒杀一切 提交于 2019-11-28 12:24:48
---恢复内容开始--- 树的逻辑结构表示有树形结构文氏图结构和凹入表示法和括号表示法 基本术语 结点的度:最大度 树的度:结点总度: 分支结点:有后继结点的结点 叶子结点:没有后继结点的结点 孩子结点:一个结点的后继结点 双亲结点:一个结点的前驱结点 子孙结点:一个结点的子树当中除去本身的结点 祖先结点:从树根结点到达某个结点经过的所有结点,不包括本身 兄弟结点: 结点层次:根节点为第一层 树的高:最大层次 森林:有零个或者多个不交错的树 性质: 树中的结点数=树的度+1 度为m的元素 第i层最多有m^(i-1)个结点 (满树的时候根节点有m度 第i-1有m^(i-1)度该度也就是第i层的结点数) m次树也就是最大度为m 但n个结点构造树 但为m次树或者接近满m次树的时候 树的高度层数最小 /* 高度为h的m次树最多有多少个结点? m+m^2+m^3+...+m^(h-1)总度数 再加上跟结点1 就是m的h-1次阶层 也就是m^0+m^1+m^2+m^3+...+m^(h-1) */ 因为树的结构为非线性结构因此树的运算较以前讨论的线性结构复杂 主要运算有: 寻找满足某种特定关系的结点 如寻找当前结点的双亲结点等等 插入或者删除某个结点 如在当前的结点上插入一个新的结点或者删除当前结点的第i个孩子结点等 遍历树中的每个结点 主要有先根遍历、后根遍历和层次遍历三种

程序员,你心里就没点树吗?

雨燕双飞 提交于 2019-11-28 06:26:32
看官,不要生气,我没有骂你也没有鄙视你的意思,今天就是想单纯的给大伙分享一下树的相关知识,但是我还是想说作为一名程序员,自己心里有没有点树?你会没点数吗?言归正传,树是我们常用的数据结构之一,树的种类很多有二叉树、二叉查找树、平衡二叉树、红黑树、B树、B+树等等,我们今天就来聊聊二叉树相关的树。 什么是树? 首先我们要知道什么是树?我们平常中的树是往上长有分支的而却不会形成闭环,数据结构中的树跟我们我们平时看到的树类似,确切的说是跟树根长得类似,我画了一幅图,让大家更好的理解树。 图1、图2都是树,图3不是树。每个红色的圆圈我们称之为元素也叫节点,用线将两个节点连接起来,这两个节点就形成了父子关系,同一个父节点的子节点成为兄弟节点,这跟我们家族关系一样,同一个父亲的叫做兄弟姐妹,在家族里面最大的称为老子,树里面也是一样的,只是不叫老子,叫做跟节点,没有子节点的叫做叶子节点。我们拿图1来做示例,A为根节点,B、C为兄弟节点,E、F为叶子节点。 一颗树还会涉及到三个概念 高度 、 深度 、 层 ,我们先来看看这三个名词的定义: 高度 :节点到叶子节点的最长路径,从0开始计数 深度 :跟节点到这个节点所经历的边数,从0开始计数 层 :节点距离根节点的距离,从1开始计数 知道了三个名词的概念之后,我们用一张图来更加形象的表示这三个概念。 以上就是树的基本概念,树的种类很多

二叉树基础知识

非 Y 不嫁゛ 提交于 2019-11-28 05:55:32
二叉树基础知识 1. 树定义 树(Tree) 是n(n>=0)个结点的有限集。n=0时称为空树。在任意一颗非空树中: 1)有且仅有一个特定的称为根(Root)的结点; 2)当n>1时,其余结点可分为m(m>0)个互不相交的有限集T1、T2、......、Tn,其中每一个集合本身又是一棵树,并且称为根的子树。 ​ 3)每一棵树有且只有一个根节点,子节点没有限制,但是每个节点都互不相交。 上图就是一个普通的数。 2. 树相关概念 ​ 2.1节点的度 ​ 节点的度就是节点拥有的子树的数目。上图A的节点的度为2。 ​ 2.2树的深度 ​ 树的深度就是树中节点的最大层次树。上图树的深度为4。 ​ 2.3节点关系 ​ 树只有一个根节点,其余的为树的孩子节点。分布在根节点的左边的节点称为左孩子,右边为右孩子,左右孩子在同一层次上称为兄弟节点。而根节点即为孩子节点的双亲节点。 3. 二叉树 ​ 二叉树定义 :二叉树是n(n>=0)个结点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根结点和两棵互不相交的、分别称为根结点的左子树和右子树组成。 以上即为一颗普通的二叉树。 二叉树特点 :1)每个结点最多有两颗子树,所以二叉树中不存在度大于2的结点。 2)左子树和右子树是有顺序的,次序不能任意颠倒。 3)即使树中某结点只有一棵子树,也要区分它是左子树还是右子树。 二叉树性质 : 1

二叉树的非递归遍历

徘徊边缘 提交于 2019-11-28 05:50:53
二叉树的遍历我想大家都知道了,主要有先序、中序、后序,递归的遍历我就不说了,今天小编给大家主要介绍下二叉树的非递归遍历。 节点结构体: #include<stack> enum tag { L, R }; template<typename T>//可以变成类 struct BintNode { BintNode():left(nullptr),right(nullptr),value(0){} BintNode(T v) { left = nullptr; right = nullptr; value = v; } T value; BintNode<T> *left; BintNode<T> *right; }; template<typename E> struct stkNode { stkNode(BintNode<E>*N=nullptr):ptr(N), r(L){} BintNode<E>*ptr; tag r; }; 首先是先序遍历,借助栈实现的。 void nonrepreorder(BintNode<Y>*root)const//非递归先序 { if (root) { stack<BintNode<Y>*> bitr; bitr.push(root); BintNode<Y>*p; while (!bitr.empty()) { p = bitr.top();

二叉树——前序遍历、中序遍历、后序遍历、层序遍历详解(递归非递归)

Deadly 提交于 2019-11-28 05:15:45
前言 前面介绍了 二叉排序树的构造和基本方法 的实现。但是排序遍历也是比较重要的一环。所以笔者将 前中后序 .和层序遍历梳理一遍。 了解树的遍历,需要具有的只是储备有 队列,递归,和栈 。这里笔者都有进行过详细介绍,可以关注笔者 数据结构与算法专栏 。持续分享,共同学习。 层序遍历 层序遍历。听名字也知道是按层遍历。我们知道一个节点 有左右节点 。而每一层一层的遍历都和左右节点有着很大的关系。也就是我们选用的数据结构不能一股脑的往一个方向钻,而 左右应该均衡考虑 。这样我们就选用队列来实现。 对于队列,现进先出。从根节点的节点push到队列,那么队列中先出来的顺序是第二层的左右(假设有)。 第二层 每个执行的时候添 加到队列 ,那么添加的所有节点都在 第二层后面 。 同理,假设开始 pop遍历第n层 的节点,每个节点会 push左右两个节点进去 。但是队列先进先出。它会放到队尾( 下一层 )。直到第n层的 最后一个pop出来 ,第n+1层的还在队列中整齐排着。这就达到一个 层序 的效果。 实现的代码也很容易理解: public void cengxu(node t) {//层序遍历 Queue<node> q1 = new ArrayDeque<node>(); if (t == null) return; if (t != null) { q1.add(t); } while (

数据结构二叉树

僤鯓⒐⒋嵵緔 提交于 2019-11-28 01:39:25
1.二叉树的根节点,子节点,双亲,祖宗,孩子,层次编号,深度,有关兄弟关系? 度为2的树不是二叉树。 二叉树的定义与特征;二叉树的顺序存储和链式存储;二叉树的遍历;线索二叉树的基本概念和构造。 2.倾斜二叉树与完全二叉树 3.前中后序遍历 前根序遍历:先遍历根结点,然后遍历左子树,最后遍历右子树 中根序遍历:先遍历左子树,然后遍历根结点,最后遍历右子树 后根序遍历:先遍历左子树,然后遍历右子树,最后遍历根节点 4.中序线索二叉链表有子节点就用 f 无子节点就用 t 5.树和森林 双亲表示法 孩子表示法 长子-兄弟表示法 6.树和森林的遍历 先根遍历 后根遍历 7.BST树 AVL树 8.平衡二叉树 平衡状态:左右两侧度数相同 左倾:左边度数大于右边 右倾:右边度数大于左边 来源: https://www.cnblogs.com/gmkk/p/11386169.html