二叉树遍历

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:29:27
首先明白两个概念: 1. 深度遍历包括前中后序遍历三种; 2. 广度优先遍历就是层次遍历。 PS: 前中后序遍历,如果使用递归遍历,都很简单易理解; 如果使用非递归方式,首先想到的就应该是使用栈结构来控制整个过程,因为递归也是利用栈来实现的; 前中后序遍历的非递归方式中,后序遍历的非递归方式相比较而言,略复杂。 直接上代码: #include "stdlib.h" #include <iostream> #include <stack> #include <queue> using namespace std; struct BinaryTreeNode { int value; BinaryTreeNode* leftChild; BinaryTreeNode* rightChild; }; /* 前序遍历递归方式 步骤: 1.先处理当前节点 2.递归处理完左支 3.递归处理右支 */ void PreOrderRecursive(BinaryTreeNode* parent) { if(NULL == parent) return; cout<<parent->value<<" "; PreOrderRecursive(parent->leftChild); PreOrderRecursive(parent->rightChild); } /* 前序遍历非递归方式 说明:

二叉树遍历(前序、中序、后序、层次遍历、深度优先、广度优先)

有些话、适合烂在心里 提交于 2019-12-03 04:29:14
二叉树是一种非常重要的数据结构,很多其它数据结构都是基于二叉树的基础演变而来的。对于二叉树,有深度遍历和广度遍历,深度遍历有前序、中序以及后序三种遍历方法,广度遍历即我们平常所说的层次遍历。因为树的定义本身就是递归定义,因此采用递归的方法去实现树的三种遍历不仅容易理解而且代码很简洁,而对于广度遍历来说,需要其他数据结构的支撑,比如堆了。所以,对于一段代码来说,可读性有时候要比代码本身的效率要重要的多。 四种主要的遍历思想为: 前序遍历:根结点 ---> 左子树 ---> 右子树 中序遍历: 左子树 ---> 根结点 ---> 右子树 后序遍历: 左子树 ---> 右子树 ---> 根结点 层次遍历:只需按层次遍历即可 例如,求下面二叉树的各种遍历 前序遍历:1 2 4 5 7 8 3 6 中序遍历:4 2 7 5 8 1 3 6 后序遍历:4 7 8 5 2 6 3 1 层次遍历:1 2 3 4 5 6 7 8 一、前序遍历 1)根据上文提到的遍历思路: 根结点 ---> 左子树 ---> 右子树,很容易写出递归版本: public void preOrderTraverse1(TreeNode root) { if (root != null) { System.out.print(root.val+" "); preOrderTraverse1(root.left);

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

让人想犯罪 __ 提交于 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 00:40:02
1、树   树的常用术语 2、二叉树 3、查找节点 4、插入节点 5、遍历树 6、查找最大值和最小值 7、删除节点     ①、删除没有子节点的节点   ②、删除有一个子节点的节点   ③、删除有两个子节点的节点   ④、删除有必要吗? 8、二叉树的效率 9、用数组表示树 10、完整的BinaryTree代码 11、哈夫曼(Huffman)编码   ①、哈夫曼编码    ②、哈夫曼解码 12、总结   前面我们介绍数组的数据结构,我们知道对于有序数组,查找很快,并介绍可以通过二分法查找,但是想要在有序数组中插入一个数据项,就必须先找到插入数据项的位置,然后将所有插入位置后面的数据项全部向后移动一位,来给新数据腾出空间,平均来讲要移动N/2次,这是很费时的。同理,删除数据也是。   那么我们就希望一种数据结构能同时具备数组查找快的优点以及链表插入和删除快的优点,于是 树 诞生了。 回到顶部 1、树    树 ( tree)是一种抽象数据类型(ADT),用来模拟具有树状结构性质的数据集合。它是由n(n>0)个有限 节点 通过连接它们的 边 组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。      ①、节点:上图的圆圈,比如A,B,C等都是表示节点。节点一般代表一些实体,在java面向对象编程中,节点一般代表对象。   ②、边

数据结构――一些概念

匿名 (未验证) 提交于 2019-12-03 00:39:02
数据结构就是研究数据的 逻辑结构 和 物理结构 以及它们之间 相互关系 ,并对这种结构定义相应的运算,而且确保经过这些运算后所得到的新结构仍然是原来的结构类型。 数据:所有能被输入到计算机中,且能被计算机处理的符号的集合。是计算机操作的对象的总称。 数据元素:数据(集合)中的一个“个体”,数据及结构中讨论的 基本 单位 数据项:数据的不可分割的最小单位。一个数据元素可由若干个数据项组成。 数据类型:在一种程序设计语言中,变量所具有的数据种类。整型、浮点型、字符型等等 逻辑结构:数据之间的相互关系。 集合 结构中的数据元素除了同属于一种类型外,别无其它关系。 线性结构 数据元素之间一对一的关系 树形结构 数据元素之间一对多的关系 图状结构或网状结构 结构中的数据元素之间存在多对多的关系 物理结构/存储结构:数据在计算机中的表示。物理结构是描述数据具体在内存中的存储(如:顺序结构、链式结构、索引结构、哈希结构)等 在数据结构中,从逻辑上可以将其分为线性结构和非线性结构 数据结构的基本操作的设置的最重要的准则是, 实现应用程序与存储结构的独立 。实现应用程序是“逻辑结构”,存储的是“物理结构”。逻辑结构主要是对该结构操作的设定,物理结构是描述数据具体在内存中的存储(如:顺序结构、链式结构、索引结构、希哈结构)等。 顺序存储结构中,线性表的逻辑顺序和物理顺序总是一致的。但在链式存储结构中

剑指offer--重建二叉树

匿名 (未验证) 提交于 2019-12-03 00:37:01
题目描述:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。 必备知识点:前序遍历(根左右), 中序遍历(左根右),前序遍历第一个数1必是根节点,对应到中序遍历中根节点的位置,左边的数位于左子树,右边的数位于右子树;可以看出,1节点同时拥有左右子树;然后, 前序遍历中第二个数字2作为节点,对应到中序遍历中,左边为左子树,同时,右边没有数,所以2节点没有右子树。所以,可以通过递归实现二叉树重建。 TreeNode* reConstructBinaryTree(vector<int> pre, vector<int> vin) { if (pre.empty() == NULL || vin.empty() == NULL) return NULL; size_t index = 0; for (; index < vin.size(); index++) { if (vin[index] == pre[0]) break; } TreeNode* root = new TreeNode(pre[0]); vector<int> pre_left, vin_left; vector<int> pre

二叉搜索树及其相关操作

匿名 (未验证) 提交于 2019-12-03 00:30:01
二叉树(binary tree)是一种树型数据结构,其中它的每个节点最多有两个孩子(可以没有,也可以只有一个)。 二叉搜索树(binary search tree)是一种特殊的二叉树,对每个节点,其左孩子/左子树的关键字值该节点的关键字值;其右孩子/右子树的关键字值都大于该节点的关键字值。 二叉搜索树的平均深度为 O ( log N ) O ( log N ) 。其中, N N 为节点总数。 二叉搜索树的主要操作有:创建(初始化)二叉树,查找关键字Find,返回最大最小关键字FindMax, FindMin,向树中插入元素Insert,删除节点Delete,遍历二叉树。 涉及到二叉树的操作有两种方法实现:递归实现和非递归实现。 一、二叉(搜索)基本数据结构 树是由一个个节点构成,节点的构成成一般为:该节点包含的关键字值(data),left指针指向其左孩子,right指针指向其右孩子。 节点结构的一般声明如下: typedef struct _TreeNode { // 定义二叉查找树的结构 ElemType data; // 数据 struct _TreeNode* left; // 指向左孩子指针 struct _TreeNode* right; // 指向其右孩子指针 }TreeNode, *SearchBTree; // TreeNode表示节点别称,

二叉树的非递归遍历

匿名 (未验证) 提交于 2019-12-03 00:30:01
把栈中的每一个节点都当作是一棵完整的二叉树,每次pop出一个节点,访问,然后把右左两棵子树入栈。 把栈中的每一个节点当作是只有右子树的二叉树,这就需要每次入栈时处理好它的左子树,一路向左把所有的节点入栈,然后出栈,访问,然后把这个节点的右子树当作是二叉树按同样的方法处理(一路向左) 后序遍历的关键就在于如何判断一个节点是应该遍历它的两棵子树还是它自己, 后序遍历有这样的特点: 如果有右子树,那么它的右孩子一定正好在它之前 else 如果有左子树,那么它的左孩子一定正好在它之前 如果左右子树都没有那么说明它可以直接访问 所以我们在便利过程中设置一个变量保存刚刚遍历过的节点,然后根据上面的性质就可以判断是该访问栈顶元素还是它的两棵子树了。 文章来源: 二叉树的非递归遍历

树相关算法(一)

匿名 (未验证) 提交于 2019-12-03 00:30:01
前言:算法竞赛中常见的树问题 (二叉)树的遍历 树的重心 树的直径 最近公共祖先(LCA) 哈夫曼树 树链剖分 一、(二叉)树的遍历 这种遍历顺序和DFS入栈的顺序很像,这种二叉树遍历方式称为先序遍历。除了先序遍历外,还有另外两种遍历,中序遍历和后序遍历。 先序遍历:访问根节点,遍历左子树,遍历右子树; 中序遍历:遍历左子树,访问根节点,遍历右子树; 后序遍历:遍历左子树,遍历右子树,访问根节点。 对于上面的那棵树,给出三种遍历方式是: 先序遍历: A->B->D->F ->G->H->I->E->C; 中序遍历:F->D->H->G->I->B->E->A->C; 后序遍历:F->H->I->G->D->E->B->C->A。 说了这么多,二叉树的遍历有什么用呢?答案是,没太大用。一般情况下是用来当做题目中的信息。对于OIer来说这些是常识,初赛会考的。 二、树的重心 树的重心,也叫树的质心。对于一棵树来说,删去该树的重心后,所有的子树的大小不会超过原树大小的二分之一。树的重心还有一个性质,是相对于树上的其他点而言的,就是删去重心后形成的所有子树中最大的一棵节点数最少。换句话说,就是删去重心后生成的多棵子树是最平衡的。一棵树的重心至多有两个。 #include<cstdio> #include<vector> #include<cstring> #include