遍历二叉树老师的程序(绝对正确,实现先序、中序、后序遍历)

合集下载

二叉树前序中序后序遍历算法

二叉树前序中序后序遍历算法

一、背景介绍在计算机科学中,二叉树是一种非常常见且重要的数据结构。

它由节点组成,每个节点最多有两个子节点:左子节点和右子节点。

而二叉树的遍历算法,即前序、中序和后序遍历,是对二叉树进行深度优先搜索的方法,它们在解决树相关问题时发挥着重要作用。

二、前序、中序和后序遍历算法的基本原理1. 前序遍历前序遍历算法是指先访问根节点,然后依次递归地前序遍历左子树和右子树。

在前序遍历中,节点的访问顺序是根节点 -> 左子树 -> 右子树。

这种遍历方式可以帮助我们快速了解二叉树的整体结构。

2. 中序遍历中序遍历算法是指先递归地中序遍历左子树,然后访问根节点,最后递归地中序遍历右子树。

在中序遍历中,节点的访问顺序是左子树 -> 根节点 -> 右子树。

通过中序遍历,我们可以按照从小到大的顺序访问二叉树的节点,用于排序和搜索相关的问题。

3. 后序遍历后序遍历算法是指先递归地后序遍历左子树和右子树,然后访问根节点。

在后序遍历中,节点的访问顺序是左子树 -> 右子树 -> 根节点。

这种遍历方式常常用于计算二叉树的高度和判断是否为平衡二叉树等问题。

以上三种遍历算法都是基于递归的思想来实现的,它们可以帮助我们深入理解二叉树的结构和特性,解决与二叉树相关的各种问题。

三、深度和广度的有机结合在实际应用中,了解和掌握二叉树的遍历算法不仅有助于我们解决特定的问题,还可以帮助我们提高对算法和数据结构的理解和认识。

通过深度的研究和广度的应用,我们可以更好地应对各种复杂情况,提高我们解决问题的效率和准确性。

四、总结与回顾通过本文的介绍,我们对二叉树的前序、中序和后序遍历算法有了更深入的了解。

这些算法不仅仅是一种方法,更是一种思想和理念。

在编程和技术领域,我们经常需要用到这些算法来解决各种问题,因此深入理解和掌握它们是非常重要的。

五、个人理解与观点对于我个人而言,通过学习和使用二叉树的遍历算法,我深深地体会到了算法和数据结构的重要性。

二叉树的遍历(先序、中序、后序)

二叉树的遍历(先序、中序、后序)

实践三:树的应用1.实验目的要求通过本实验使学生深刻理解二叉树的性质和存储结构,熟练掌握二叉树的遍历算法。

认识哈夫曼树、哈夫曼编码的作用和意义。

实验要求:建一个二叉树并按照前序、中序、后序三种方法遍历此二叉树,正确调试本程序。

能够建立一个哈夫曼树,并输出哈夫曼编码,正确调程序。

写出实验报告。

2.实验主要内容2.1 对二叉树进行先序、中序、后序递归遍历,中序非递归遍历。

2.2 根据已知的字符及其权值,建立哈夫曼树,并输出哈夫曼编码。

3.实验步骤2.1实验步骤●输入p127二叉链表的定义●录入调试p131算法6.4,实现二叉树的构造函数●编写二叉树打印函数,可以通过递归算法将二叉树输出为广义表的形式,以方便观察树的结构。

●参考算法6.1,实现二叉树的前序、中序和后序的递归遍历算法。

为简化编程,可以将visit函数直接使用printf函数输出结点内容来代替。

#include<stdio.h>#include<stdlib.h>#include<malloc.h>#define OK 1#define ERROR 0#define STACK_INIT_SIZE 100#define STACKINCREMENT 10typedef char TElemType;typedef char Status;// 构造书的结构体typedef struct BiTNode{TElemType data;struct BiTNode *lchild, *rchild;}BiTNode, *BiTree;// 构造栈的结构体typedef BiTree SElemType;typedef struct{SElemType *base;SElemType *top;int stacksize;}SqStack;Status InitStack(SqStack &S){//构造一个空栈S.base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType)); if(!S.base)exit(-2);S.top = S.base;S.stacksize = STACK_INIT_SIZE;return OK;}Status StackEmpty(SqStack S){//若栈S为空栈,则返回TRUE,否则返回FALSEif(S.top==S.base)return 1;elsereturn 0;}Status Push(SqStack &S,SElemType e){//插入元素e为新的栈顶元素if(S.top - S.base >= S.stacksize){S.base = (SElemType *)realloc(S.base,(S.stacksize + STACKINCREMENT) * sizeof(SElemType));if(!S.base)exit(-2);S.top = S.base + S.stacksize;S.stacksize += STACKINCREMENT;}*S.top++ = e;return OK;}Status Pop(SqStack &S,SElemType &e){//若栈不空,则删除S的栈顶元素,用e返回其值并返回OK,否则返回ERRORif(S.top == S.base) return ERROR;e = * --S.top;return OK;}Status InOrderTraverse(BiTree T,Status(*Visit)(TElemType e)){//非递归中序遍历二叉树SqStack S;BiTNode * p;InitStack(S);p = T;while(p||!StackEmpty(S)){if(p){Push(S,p); p=p->lchild; }else {Pop(S,p); if(!Visit(p->data)) return 0;p=p->rchild;}}return 1;}//以下是递归遍历Status CreateBiTree(BiTree &T){//构造二叉树Tchar ch;scanf("%c",&ch);if(ch == ' ') T=NULL;else{if(!(T=(BiTNode*)malloc(sizeof(BiTNode)))) exit(-2);T->data=ch;CreateBiTree(T->lchild);CreateBiTree(T->rchild);}return 1;}Status PreOrderTraverse(BiTree T, Status(* Visit)(TElemType e)){ //递归先序遍历if(T){if(Visit(T->data))if(PreOrderTraverse(T->lchild,Visit))if(PreOrderTraverse(T->rchild,Visit)) return 1;return 0;}else return 1;}Status MinOrderTraverse(BiTree T, Status(* Visit)(TElemType e)){ //递归中序遍历if(T){if(MinOrderTraverse(T->lchild,Visit))if(Visit(T->data))if(MinOrderTraverse(T->rchild,Visit)) return 1;return 0;}else return 1;}Status PostOrderTraverse(BiTree T, Status(* Visit)(TElemType e)){ //递归后续遍历if(T){if(PostOrderTraverse(T->lchild,Visit))if(PostOrderTraverse(T->rchild,Visit))if(Visit(T->data)) return 1;return 0;}else return 1;}Status PrintElement(TElemType e){//Visit函数,输出元素printf("%c ",e);return 1;}//主函数void main(){BiTNode* p;printf("Enter Node:\n");CreateBiTree(p);printf("递归先序遍历:");PreOrderTraverse(p,PrintElement);printf("\n递归中序遍历:");MinOrderTraverse(p,PrintElement);printf("\n递归后序遍历:");PostOrderTraverse(p,PrintElement);printf("\n");printf("\n非递归中序遍历:");InOrderTraverse(p,PrintElement);printf("\n");}输入:ABCE000DF00G00HJ00K0L00 (“0”表示空格) 输出:。

数据结构—树二叉树前序遍历、中序遍历、后序遍历【图解实现】

数据结构—树二叉树前序遍历、中序遍历、后序遍历【图解实现】

数据结构—树二叉树前序遍历、中序遍历、后序遍历【图解实现】AI研习图书馆,发现不一样的精彩世界数据结构二叉树的遍历一、树在谈二叉树的知识点之前,我们首先来看一下树和图的基本概念。

树:不包含回路的连通无向图,树是一种简单的非线性结构。

由于树有一个不包含回路的特点,因此树被赋予了许多特性,如下所示:1、一棵树中任意的两个结点有且仅有唯一的一条路径连通2、一棵树如果有n个结点,那么它一定恰好有n-1条边3、在一棵树中加上一条边,将会构成一个回路4、一棵树中有且仅有一个没有前驱的结点,即为根结点通常情况下,我们在对树进行讨论的时候,将一棵树中的每个点称为结点:根结点:没有父结点的结点叶结点:没有子结点的结点内部结点:一个结点既不是根结点也不是叶结点每个结点有一个深度的概念,例如上图左边的树,4号结点深度是3。

二、二叉树1. 基本概念二叉树是一种非线性结构,二叉树是由递归定义的,其结点有左右子树之分。

2. 二叉树的存储结构二叉树一般采用链式存储结构,存储结点由数据域和指针域组成,二叉树的链式存储结构也称为二叉链表。

指针域:左指针域和右指针域特点:1、每个结点最多有两颗子树2、左子树和右子树是有顺序的,次序不能颠倒3、即使某个结点只有一颗子树,也要区分左右子树4、二叉树可为空,空的二叉树没有结点,非空二叉树有且仅有一个根节点二叉树中有两种比较特殊的二叉树:满二叉树、完全二叉树,对于满二叉树和完全二叉树可以按照层次进行顺序存储。

满二叉树:二叉树中每个内部结点都存在左子树和右子树满二叉树一定是完全二叉树,但完全二叉树不一定是满二叉树。

满二叉树的严格定义:一颗深度为h且具有2h-1个结点的二叉树。

完全二叉树:解释一:如果一颗二叉树除了最右边位置上有一个或几个叶结点缺少外,其他都是丰满的,那么这样的二叉树就是完全二叉树。

解释二:除第h层外,其他各层(1到h-1)的结点数都达到最大个数,第h层从右向左连续缺若干结点,则这个二叉树就是完全二叉树。

二叉树的先序遍历、中序遍历、后续遍历(采用递归和栈两种)层序遍历(使用队列)

二叉树的先序遍历、中序遍历、后续遍历(采用递归和栈两种)层序遍历(使用队列)

⼆叉树的先序遍历、中序遍历、后续遍历(采⽤递归和栈两种)层序遍历(使⽤队列)⾸先我们要先⾃⼰建⽴⼀个⼆叉树,我们先根据我⾃⼰随便写的⼆叉树建⽴⼀个列表保存⼆叉树的各个节点的信息,当然你也可以直接写个程序⾃⼰建⽴。

node_list = [{'data':'A', 'left':'B', 'right':'C', 'is_root':True},{'data':'B', 'left':'D', 'right':'E', 'is_root':False},{'data':'C', 'left':'F', 'right':'G', 'is_root':False},{'data':'D', 'left':None, 'right':None, 'is_root':False},{'data':'E', 'left':'H', 'right':None, 'is_root':False},{'data':'H', 'left':None, 'right':None, 'is_root':False},{'data':'F', 'left':None, 'right':None, 'is_root':False},{'data':'G', 'left':'I', 'right':'J', 'is_root':False},{'data':'I', 'left':None, 'right':None, 'is_root':False},{'data':'J', 'left':None, 'right':None, 'is_root':False}]然后根据建的列表建⽴⼀个⼆叉树1from collections import deque2class BinTreeNode(object):3def__init__(self, data, left=None, right=None):4 self.data, self.left, self.right = data, left, right56class BinTree(object):78def__init__(self, root=None):9 self.root = root1011 @classmethod12def build_form(cls, node_list):13 node_dict = {}14for node_data in node_list:15#这⼀步是把所有节点存在node_dict中16 data = node_data['data']17 node_dict[data] = BinTreeNode(data)18'''这⼀步是根据存在node_dict中的节点字典,把对应的左右节点对应上'''19for node_data in node_list:20 data = node_data['data']21if node_data['is_root']:22 root = node_dict[data]23 node_dict[data].left = node_dict.get(node_data['left'])24 node_dict[data].right = node_dict.get(node_data['right'])25return cls(root)接下来是⼏种遍历先序遍历:即先遍历根节点然后遍历左节点接着是右节点第⼀种:采⽤递归['A', 'B', 'D', 'E', 'H', 'C', 'F', 'G', 'I', 'J']def prevorder_trav(self, subtree):if subtree:yield subtreeyield from self.prevorder_trav(subtree.left)yield from self.prevorder_trav(subtree.right)我个⼈⽐较倾向于返回对应节点⽽不是直接返回值,这样我们还可以对⼆叉树的每个节点操作。

二叉树遍历的递归实现详解(先序、中序、后序和层次遍历)

二叉树遍历的递归实现详解(先序、中序、后序和层次遍历)

⼆叉树遍历的递归实现详解(先序、中序、后序和层次遍历)由⼆叉树的定义可知,⼀棵⼆叉树由根结点、左⼦树和右⼦树三部分组成。

因此,只要遍历了这三个部分,就可以实现遍历整个⼆叉树。

若以D、L、R分别表⽰遍历根结点、左⼦树、右⼦树,则⼆叉树的递归遍历可以有⼀下四种⽅式:先序遍历(DLR)先序遍历的递归过程为(1)访问根结点(2)先序遍历根结点的左⼦树(3)先序遍历根结点的右⼦树举例:代码:void PreOrder(BiTree bt){if(bt ==NULL)return; //递归的结束条件----某结点为空时printf("%d",bt->data); //这⾥⽤printf data表⽰访问结点的数据域PreOrder(bt->lchild); //递归遍历左孩⼦PreOrder(bt->rclild); //递归遍历右孩⼦}中序遍历(LDR)(1)中序遍历根结点的左⼦树(2)访问根结点(3)中序遍历根结点的右⼦树举例:代码:void InOrder(BiTree bt){if(bt ==NULL)return; //递归的结束条件----某结点为空时InOrder(bt->lchild); //递归遍历左孩⼦printf("%d",bt->data); //这⾥⽤printf data表⽰访问结点的数据域InOrder(bt->rclild); //递归遍历右孩⼦}后序遍历(LRD)(1)后序遍历⼆叉树的左⼦树(2)后序遍历⼆叉树的右⼦树(3)访问根结点。

举例:代码:void PostOrder(BiTree bt){if(bt ==NULL)return; //递归的结束条件----某结点为空时PostOrder(bt->lchild); //递归遍历左孩⼦PostOrder(bt->rclild); //递归遍历右孩⼦printf("%d",bt->data); //这⾥⽤printf data表⽰访问结点的数据域}层次遍历(1)根结点⼊队列(2)根结点出队列,根结点的左⼦树、右⼦树相继⼊队列(3)根结点的左⼦树结点出队列,左⼦树结点的左⼦树、右⼦树相继⼊队列(4).......举例:代码://层次遍历⼆叉树void LevelOrder(BiTree T){BiTree Queue[MAX],b; //⽤⼀维数组表⽰队列,front和rear表⽰队⾸和队尾的指针int front,rear;front=rear=0;if(T)//若树为空{Queue[rear++]=T; //根节点⼊队列while(front!=rear) //当队列⾮空{b=Queue[front++]; //队⾸元素出队列,并访问这个节点printf("%2c",b->data);if(b->lchild!=NULL) Queue[rear++]=b->lchild ; //若左⼦树⾮空,则⼊队列if(b->rchild!=NULL) Queue[rear++]=b->rchild ; //若右⼦树⾮空,则⼊队列}}}最终代码:#include<stdio.h>#include<stdlib.h>#define MAX 20typedef char TElemType;typedef int Status;typedef struct BiTNode{TElemType data;struct BiTNode *lchild,*rchild; //左右孩⼦的指针} BiTNode,*BiTree;//先序创建⼆叉树void CreateBiTree(BiTree *T){char ch;ch=getchar();if(ch=='#')(*T)=NULL; //#代表空指针else{(*T)=(BiTree)malloc(sizeof(BiTNode)); //申请节点(*T)->data=ch; //⽣成跟节点CreateBiTree(&(*T)->lchild);CreateBiTree(&(*T)->rchild);}}//先序输出⼆叉树void PreOrder(BiTree T){if(T){printf("%2c",T->data); //访问根节点,此处为输出根节点的数据值PreOrder(T->lchild); //先序遍历左⼦树PreOrder(T->rchild); //先序遍历右⼦树}}//中序输出⼆叉树void InOrder(BiTree T){if(T){InOrder(T->lchild);printf("%2c",T->data);InOrder(T->rchild);}}//后序输出⼆叉树void PostOrder(BiTree T){if(T){PostOrder(T->lchild);PostOrder(T->rchild);printf("%2c",T->data);}}//层次遍历⼆叉树void LevelOrder(BiTree T){BiTree Queue[MAX],b; //⽤⼀维数组表⽰队列,front和rear表⽰队⾸和队尾的指针 int front,rear;front=rear=0;if(T)//若树为空{Queue[rear++]=T; //根节点⼊队列while(front!=rear) //当队列⾮空{b=Queue[front++]; //队⾸元素出队列,并访问这个节点printf("%2c",b->data);if(b->lchild!=NULL) Queue[rear++]=b->lchild ; //若左⼦树⾮空,则⼊队列if(b->rchild!=NULL) Queue[rear++]=b->rchild ; //若右⼦树⾮空,则⼊队列}}}//求树的深度int depth(BiTree T){int dep1,dep2;if(T==NULL) return 0;else{dep1=depth(T->lchild);dep2=depth(T->rchild);return dep1>dep2?dep1+1:dep2+1;}}int main(){BiTree T=NULL;printf("\n 创建⼀棵⼆叉树: \n");CreateBiTree(&T); //创建⼆叉树printf("\n先序遍历的结果为:\n");PreOrder(T); //先序遍历printf("\n中序遍历的结果为:\n");InOrder(T); //中序遍历printf("\n 后序遍历的结果为: \n");PostOrder(T);printf("\n 层次遍历的结果为: \n");LevelOrder(T); //层次遍历printf("\n 树的深度为:%d\n",depth(T));}结果⽰例:⼤家喜欢的话可以点个赞,有错误的地⽅请务必在评论区指出哟。

二叉树前中后序遍历做题技巧

二叉树前中后序遍历做题技巧

二叉树前中后序遍历做题技巧在计算机科学中,二叉树是一种重要的数据结构,而前序、中序和后序遍历则是二叉树遍历的三种主要方式。

下面将分别对这三种遍历方式进行解析,并提供一些解题技巧。

1.理解遍历顺序前序遍历顺序是:根节点->左子树->右子树中序遍历顺序是:左子树->根节点->右子树后序遍历顺序是:左子树->右子树->根节点理解每种遍历顺序是解题的基础。

2.使用递归或迭代二叉树的遍历可以通过递归或迭代实现。

在递归中,每个节点的处理函数会调用其左右子节点的处理函数。

在迭代中,可以使用栈来模拟递归过程。

3.辨析指针指向在递归或迭代中,需要正确处理指针的指向。

在递归中,通常使用全局变量或函数参数传递指针。

在迭代中,需要使用栈或其他数据结构保存指针。

4.学会断点续传在处理大规模数据时,为了避免内存溢出,可以采用断点续传的方式。

即在遍历过程中,将中间结果保存在文件中,下次遍历时从文件中读取上一次的结果,继续遍历。

5.识别循环和终止条件在遍历二叉树时,要识别是否存在循环,并确定终止条件。

循环可以通过深度优先搜索(DFS)或广度优先搜索(BFS)避免。

终止条件通常为达到叶子节点或达到某个深度限制。

6.考虑边界情况在处理二叉树遍历问题时,要考虑边界情况。

例如,对于空二叉树,需要进行特殊处理。

又如,在处理二叉搜索树时,需要考虑节点值的最小和最大边界。

7.优化空间使用在遍历二叉树时,需要优化空间使用。

例如,可以使用in-place排序来避免额外的空间开销。

此外,可以使用懒加载技术来延迟加载子节点,从而减少内存占用。

8.验证答案正确性最后,验证答案的正确性是至关重要的。

可以通过检查输出是否符合预期、是否满足题目的限制条件等方法来验证答案的正确性。

如果可能的话,也可以使用自动化测试工具进行验证。

JAVA实现二叉树的前序遍历、中序遍历、后序遍历和层次遍历算法

JAVA实现二叉树的前序遍历、中序遍历、后序遍历和层次遍历算法

本文由我司收集整编,推荐下载,如有疑问,请与我司联系JAVA 实现二叉树的前序遍历、中序遍历、后序遍历和层次遍历算法JAVA 实现二叉树的前序遍历、中序遍历、后序遍历和层次遍历算法如图所示一颗二叉树,用JAVA 实现二叉树的前序遍历、中序遍历、后序遍历和层次遍历算法定义树节点public class TreeNode { int data; TreeNode leftChild; TreeNode rightChild; TreeNode(){ this.leftChild=null; this.rightChild=null; this.data=-1; TreeNode(int data){ this.leftChild=null; this.rightChild=null; this.data=data; public TreeNode(int data, TreeNode leftChild, TreeNode rightChild) { this.data = data; this.leftChild = leftChild; this.rightChild = rightChild; //其它代码省略……二叉树的前序遍历、中序遍历、后序遍历和层次遍历算法设计package com.bean.binarytreedemo;import java.util.ArrayList;import java.util.LinkedList;import java.util.List;import java.util.Queue;import java.util.Stack; //给定一个一维数组,表示二叉树节点的值private int[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; private static List TreeNode nodeList = null; public void createBinTree() { nodeList = new LinkedList TreeNode // 将一个数组的值依次转换为Node 节点for (int nodeIndex = 0; nodeIndex array.length; nodeIndex++) { nodeList.add(new TreeNode(array[nodeIndex])); // 对前lastParentIndex-1 个父节点按照父节点与孩子节点的数字关系建立二叉树for (int parentIndex = 0; parentIndex array.length / 2 - 1; parentIndex++) { // 左孩子nodeList.get(parentIndex).leftChild = nodeList .get(parentIndex * 2 + 1); // 右孩子nodeList.get(parentIndex).rightChild = nodeList .get(parentIndex * 2 + 2); // 最后一个父节点:因为最后一个父节点可能没有右孩子,因此单独拿出来处理int lastParentIndex = array.length / 2 - 1; // 左孩子nodeList.get(lastParentIndex).leftChild = nodeList .get(lastParentIndex * 2 + 1); // 右孩子,如果数组的长度为奇数才建立右孩子if (array.length % 2 == 1) {。

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

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

⼆叉树的深度优先遍历(前序、中序、后序)⼆叉树是⼀种⾮常重要的数据结构,很多其他数据机构都是基于⼆叉树的基础演变过来的。

⼆叉树有前、中、后三种遍历⽅式,因为树的本⾝就是⽤递归定义的,因此采⽤递归的⽅法实现三种遍历,不仅代码简洁且容易理解,但其开销也⽐较⼤,⽽若采⽤⾮递归⽅法实现三种遍历,则要⽤栈来实现(递归也是⽤栈实现的)。

下⾯先简要介绍三种遍历⽅式的递归实现,再详细介绍三种遍历⽅式的⾮递归实现。

⼀、三种遍历⽅式的递归实现(⽐较简单,这⾥不详细讲解)1、先序遍历——按照“根节点-左孩⼦-右孩⼦”的顺序进⾏访问。

[cpp]1. void pre_traverse(BTree pTree)2. {3. if(pTree)4. {5. printf(”%c ”,pTree->data);6. if(pTree->pLchild)7. pre_traverse(pTree->pLchild);8. if(pTree->pRchild)9. pre_traverse(pTree->pRchild);10. }11. }2、中序遍历——按照“左孩⼦-根节点-右孩⼦”的顺序进⾏访问。

[cpp]1. void in_traverse(BTree pTree)2. {3. if(pTree)4. {5. if(pTree->pLchild)6. in_traverse(pTree->pLchild);7. printf(”%c ”,pTree->data);8. if(pTree->pRchild)9. in_traverse(pTree->pRchild);10. }11. }3、后序遍历——按照“左孩⼦-右孩⼦-根节点”的顺序进⾏访问。

[cpp]1. void beh_traverse(BTree pTree)2. {3. if(pTree)4. {5. if(pTree->pLchild)6. beh_traverse(pTree->pLchild);7. if(pTree->pRchild)8. beh_traverse(pTree->pRchild);9. printf(”%c ”,pTree->data);10. }⼆、三种遍历⽅式的⾮递归实现为了便于理解,这⾥以下图的⼆叉树为例,分析⼆叉树的三种遍历⽅式的实现过程。

二叉树的遍历算法

二叉树的遍历算法

二叉树的遍历算法二叉树是一种常见的数据结构,它由节点组成,每个节点最多有两个子节点。

二叉树的遍历算法是对二叉树中的节点进行访问的过程,可以分为三种遍历方式:前序遍历、中序遍历和后序遍历。

下面将详细介绍这三种遍历算法,涵盖二叉树的基本操作和应用。

1.前序遍历:前序遍历是指在访问节点值之前先访问根节点,然后按照先左后右的顺序遍历子树。

具体步骤如下:-访问根节点-前序遍历左子树-前序遍历右子树前序遍历的应用场景包括二叉树的构建、表达式求值和打印目录结构等。

2.中序遍历:中序遍历是指按照先左后根再右的顺序遍历子树。

具体步骤如下:-中序遍历左子树-访问根节点-中序遍历右子树中序遍历可以用于查找二叉树中的元素,以及将二叉树转换为有序数组等。

3.后序遍历:后序遍历是指在访问节点值之后遍历左右子树,最后访问根节点。

具体步骤如下:-后序遍历左子树-后序遍历右子树-访问根节点后序遍历常用于计算二叉树的节点个数、深度或树的高度等。

除了上述三种基本遍历方式,还有层序遍历、Morris遍历等其他遍历算法,这里不再详细介绍。

在实现二叉树的遍历算法时,可以使用递归或迭代的方法。

递归算法是基于函数的自我调用实现的,而迭代算法则使用栈或队列等数据结构来模拟递归的过程。

下面以前序遍历为例,给出递归算法和迭代算法的示例代码。

1.递归算法:```pythonclass TreeNode:def __init__(self, value):self.val = valueself.left = Noneself.right = Nonedef preorderTraversal(root):if not root:return []res = []res.append(root.val)res += preorderTraversal(root.left) res += preorderTraversal(root.right) return res```2.迭代算法(使用栈):```pythondef preorderTraversal(root):if not root:return []res = []stack = [root]while stack:node = stack.popres.append(node.val)if node.right:stack.append(node.right) if node.left:stack.append(node.left) return res```。

二叉树的5种遍历方式

二叉树的5种遍历方式

二叉树的5种遍历方式一、前序遍历前序遍历是指在二叉树中,先访问根节点,然后按照先左后右的顺序遍历左右子树。

具体步骤如下:1. 访问根节点;2. 递归遍历左子树;3. 递归遍历右子树。

前序遍历的应用场景非常广泛。

例如,在二叉搜索树中,前序遍历可以用来实现树的查找操作;在表达式树中,前序遍历可以用来将表达式转换为前缀表达式。

二、中序遍历中序遍历是指在二叉树中,先按照中序遍历左子树,然后访问根节点,最后按照中序遍历右子树的顺序遍历整个二叉树。

具体步骤如下:1. 递归遍历左子树;2. 访问根节点;3. 递归遍历右子树。

中序遍历的一个重要应用是对二叉搜索树进行排序,因为中序遍历可以按照升序输出二叉搜索树中的节点值。

三、后序遍历后序遍历是指在二叉树中,先按照后序遍历左子树,然后按照后序遍历右子树,最后访问根节点的顺序遍历整个二叉树。

具体步骤如下:1. 递归遍历左子树;2. 递归遍历右子树;3. 访问根节点。

后序遍历的一个常见应用是计算表达式树的值,因为后序遍历可以按照逆波兰表达式的顺序遍历表达式树。

四、层序遍历层序遍历是指按照从上到下、从左到右的顺序逐层遍历二叉树的节点。

具体步骤如下:1. 将根节点入队;2. 循环执行以下步骤,直到队列为空:a. 出队一个节点,访问该节点;b. 将该节点的左子节点入队(如果存在);c. 将该节点的右子节点入队(如果存在)。

层序遍历可以用来按层打印二叉树的节点值,也可以用来判断二叉树的深度。

五、深度优先遍历深度优先遍历是指在二叉树中,先访问根节点,然后按照深度优先的顺序遍历左右子树。

具体步骤如下:1. 访问根节点;2. 递归遍历左子树;3. 递归遍历右子树。

深度优先遍历的一个常见应用是判断二叉树是否对称。

通过比较左子树和右子树的节点值,可以判断二叉树是否对称。

深度优先遍历还可以用来解决一些搜索问题,例如在二叉树中查找路径等。

在实际应用中,根据具体的问题场景和需求,选择合适的遍历方式非常重要。

二叉树遍历前序中序后序 java 非递归

二叉树遍历前序中序后序 java 非递归

二叉树的前序、中序和后序遍历是二叉树的基本遍历方式。

前序遍历的顺序是根-左-右,中序遍历的顺序是左-根-右,后序遍历的顺序是左-右-根。

以下是在Java 中实现非递归版本的二叉树遍历:前序遍历(根-左-右)前序遍历可以直接使用栈实现。

首先将根节点入栈,然后进入一个循环,每次循环中,先弹出栈顶元素并访问,然后将其右子节点和左子节点依次入栈(注意顺序)。

javapublic void preOrderTraversal(TreeNode root) {if (root == null) {return;}Stack<TreeNode> stack = new Stack<>();stack.push(root);while (!stack.isEmpty()) {TreeNode node = stack.pop();System.out.print(node.val + " ");if (node.right != null) {stack.push(node.right);}if (node.left != null) {stack.push(node.left);}}}中序遍历(左-根-右)中序遍历稍微复杂一些,因为我们需要保持正确的左右子节点的访问顺序。

这可以通过使用两个栈来实现。

首先将根节点入栈1,然后进入循环。

在每次循环中,先判断栈1是否为空,如果不为空,则弹出栈顶元素并访问,然后将其右子节点入栈1。

如果栈1为空,则将栈2中的元素依次弹出并访问,然后将其左子节点入栈1。

javapublic void inOrderTraversal(TreeNode root) {if (root == null) {return;}Stack<TreeNode> stack1 = new Stack<>();Stack<TreeNode> stack2 = new Stack<>();stack1.push(root);while (!stack1.isEmpty()) {TreeNode node = stack1.pop();stack2.push(node);if (node.right != null) {stack1.push(node.right);}}while (!stack2.isEmpty()) {TreeNode node = stack2.pop();System.out.print(node.val + " ");if (node.left != null) {stack1.push(node.left);}}}后序遍历(左-右-根)后序遍历是最复杂的,因为我们需要先访问左右子节点,再访问根节点。

简述二叉树的遍历的方法及其概念

简述二叉树的遍历的方法及其概念

二叉树的遍历是指按照一定的顺序依次访问二叉树中的所有节点的过程。

二叉树的遍历方法有三种,分别是前序遍历、中序遍历和后序遍历。

前序遍历:前序遍历是指先访问根节点,然后再访问左子树,最后访问右子树的过程。

前序遍历的访问顺序为:根节点→左子树→右子树。

中序遍历:中序遍历是指先访问左子树,然后再访问根节点,最后访问右子树的过程。

中序遍历的访问顺序为:左子树→根节点→右子树。

后序遍历:后序遍历是指先访问左子树,然后再访问右子树,最后访问根节点的过程。

后序遍历的访问顺序为:左子树→右子树→根节点。

在二叉树的遍历过程中,每个节点会被访问三次,分别是在前序遍历、中序遍历和后序遍历中。

这三种遍历方法的访问顺序不同,因此它们访问节点的顺序也不同,可以根据具体的需求选择不同的遍历方法。

二叉树的遍历(前序、中序、后序、已知前中序求后序、已知中后序求前序)

二叉树的遍历(前序、中序、后序、已知前中序求后序、已知中后序求前序)

⼆叉树的遍历(前序、中序、后序、已知前中序求后序、已知中后序求前序)之前的⼀篇随笔()只对⼆叉树的遍历进⾏了笼统的描述,这篇随笔重点对前、中、后序的遍历顺序进⾏分析⼆叉树的遍历⼆叉树的深度优先遍历可细分为前序遍历、中序遍历、后序遍历,这三种遍历可以⽤递归实现(本篇随笔主要分析递归实现),也可使⽤⾮递归实现的前序遍历:根节点->左⼦树->右⼦树(根->左->右)中序遍历:左⼦树->根节点->右⼦树(左->根->右)后序遍历:左⼦树->右⼦树->根节点(左->右->根)在进⾏已知两种遍历顺序求另⼀种遍历顺序前,先看⼀下不同遍历顺序对应的代码前序遍历1/* 以递归⽅式前序遍历⼆叉树 */2void PreOrderTraverse(BiTree t, int level)3 {4if (t == NULL)5 {6return ;7 }8 printf("data = %c level = %d\n ", t->data, level);9 PreOrderTraverse(t->lchild, level + 1);10 PreOrderTraverse(t->rchild, level + 1);11 }中序遍历1/* 以递归⽅式中序遍历⼆叉树 */2void PreOrderTraverse(BiTree t, int level)3 {4if (t == NULL)5 {6return ;7 }8 PreOrderTraverse(t->lchild, level + 1);9 printf("data = %c level = %d\n ", t->data, level);10 PreOrderTraverse(t->rchild, level + 1);11 }后序遍历1/* 以递归⽅式后序遍历⼆叉树 */2void PreOrderTraverse(BiTree t, int level)3 {4if (t == NULL)5 {6return ;7 }8 PreOrderTraverse(t->lchild, level + 1);9 PreOrderTraverse(t->rchild, level + 1);10 printf("data = %c level = %d\n ", t->data, level);11 }三种遍历⽅式对应的代码⼏乎相同,只是⼀条语句的位置发⽣了变化printf("data = %c level = %d\n ", t->data, level);只看⽂字和代码来理解遍历的过程是⽐较困难的,建议读者亲⾃去遍历,为了理清遍历的过程下⾯上题(图⽚来源:)前序遍历前序的遍历的特点,根节点->左⼦树->右⼦树,注意看前序的遍历的代码printf语句是放在两条递归语句之前的,所以先访问根节点G,打印G,然后访问左⼦树D,此时左⼦树D⼜作为根节点,打印D,再访问D的左⼦树AA⼜作为根节点,打印A,A没有左⼦树或者右⼦树,函数调⽤结束返回到D节点(此时已经打印出来的有:GDA)D节点的左⼦树已经递归完成,现在递归访问右⼦树F,F作为根节点,打印F,F有左⼦树访问左⼦树E,E作为根节点,打印E,(此时已经打印出来的有:GDAFE),E没有左⼦树和右⼦树,函数递归结束返回F节点,F的左⼦树已经递归完成了,但没有右⼦树,所以函数递归结束,返回D节点,D节点的左⼦树和右⼦树递归全部完成,函数递归结束返回G节点,访问G节点的右⼦树M,M作为根节点,打印M,访问M的左⼦树H,H作为根节点,打印H,(此时已经打印出来的有:GDAFEMH)H没有左⼦树和右⼦树,函数递归结束,返回M节点,M节点的左⼦树已经递归完成,访问右⼦树Z,Z作为根节点,打印Z,Z没有左⼦树和右⼦树,函数递归结束,返回M节点,M节点的左⼦树右⼦树递归全部完成,函数递归结束,返回G节点,G节点的左右⼦树递归全部完成,整个⼆叉树的遍历就结束了(MGJ,终于打完了··)前序遍历结果:GDAFEMHZ总结⼀下前序遍历步骤第⼀步:打印该节点(再三考虑还是把访问根节点这句话去掉了)第⼆步:访问左⼦树,返回到第⼀步(注意:返回到第⼀步的意思是将根节点的左⼦树作为新的根节点,就好⽐图中D是G的左⼦树但是D也是A节点和F节点的根节点)第三步:访问右⼦树,返回到第⼀步第四步:结束递归,返回到上⼀个节点前序遍历的另⼀种表述:(1)访问根节点(2)前序遍历左⼦树(3)前序遍历右⼦树(在完成第2,3步的时候,也是要按照前序遍历⼆叉树的规则完成)前序遍历结果:GDAFEMHZ中序遍历(详细遍历过程就不再赘述了,(┬_┬))中序遍历步骤第⼀步:访问该节点左⼦树第⼆步:若该节点有左⼦树,则返回第⼀步,否则打印该节点第三步:若该节点有右⼦树,则返回第⼀步,否则结束递归并返回上⼀节点(按我⾃⼰理解的中序就是:先左到底,左到不能在左了就停下来并打印该节点,然后返回到该节点的上⼀节点,并打印该节点,然后再访问该节点的右⼦树,再左到不能再左了就停下来)中序遍历的另⼀种表述:(1)中序遍历左⼦树(2)访问根节点(3)中序遍历右⼦树(在完成第1,3步的时候,要按照中序遍历的规则来完成)所以该图的中序遍历为:ADEFGHMZ后序遍历步骤第⼀步:访问左⼦树第⼆步:若该节点有左⼦树,返回第⼀步第三步:若该节点有右⼦树,返回第⼀步,否则打印该节点并返回上⼀节点后序遍历的另⼀种表述:(1)后序遍历左⼦树(2)后序遍历右⼦树(3)访问根节点(在完成1,2步的时候,依然要按照后序遍历的规则来完成)该图的后序遍历为:AEFDHZMG(读者如果在纸上遍历⼆叉树的时候,仍然容易将顺序搞错建议再回去看⼀下三种不同遍历对应的代码)进⼊正题,已知两种遍历结果求另⼀种遍历结果(其实就是重构⼆叉树)第⼀种:已知前序遍历、中序遍历求后序遍历前序遍历:ABCDEF中序遍历:CBDAEF在进⾏分析前读者需要知道不同遍历结果的特点1、前序遍历的第⼀元素是整个⼆叉树的根节点2、中序遍历中根节点的左边的元素是左⼦树,根节点右边的元素是右⼦树3、后序遍历的最后⼀个元素是整个⼆叉树的根节点(如果读者不明⽩上述三个特点,建议再回去看⼀下三种不同遍历对应的代码,并在纸上写出⼀个简单的⼆叉树的三种不同的遍历结果,以加深对三种不同遍历的理解)⽤上⾯这些特点来分析遍历结果,第⼀步:先看前序遍历A肯定是根节点第⼆步:确认了根节点,再来看中序遍历,中序遍历中根节点A的左边是CBD,右边是EF,所有可以确定⼆叉树既有左⼦树⼜有右⼦树第三步:先来分析左⼦树CBD,那么CBD谁来做A的左⼦树呢?这个时候不能直接⽤中序遍历的特点(左->根->右)得出左⼦树应该是这个样⼦因为有两种情况都满⾜中序遍历为CBD⽆法直接根据中序遍历来直接得出左⼦树的结构,这个时候就要返回到前序遍历中去观察前序遍历ABCDEF,左⼦树CBD在前序遍历中的顺序是BCD,意味着B是左⼦树的根节点(这么说可能不太好理解,换个说法就是B是A的左⼦树),得出这个结果是因为如果⼀个⼆叉树的根节点有左⼦树,那么这个左⼦树⼀定在前序遍历中⼀定紧跟着根节点(这个是⽤前序遍历的特点(根->左->右)得出的),到这⾥就可以确认B是左⼦树的根节点第四步:再观察中序遍历CBDAEF,B元素左边是C右边是D,说明B节点既有左⼦树⼜有右⼦树,左右⼦树只有⼀个元素就可以直接确定了,不⽤再返回去观察前序遍历第五步:到这⾥左⼦树的重建就已经完成了,现在重建右⼦树,因为重建右⼦树的过程和左⼦树的过程⼀模⼀样,步骤就不像上⾯写这么细了((┬_┬)),观察中序遍历右⼦树为EF,再观察前序遍历ABCDEF中右⼦树的顺序为EF,所以E为A的右⼦树,再观察中序便利中E只有右边有F,所有F为E的右⼦树,最后得到的⼆叉树是这个样⼦的所有求得的后序遍历为:CDBFEA总结⼀下上述步骤:先观察前序遍历找到根节点->观察中序遍历将根节点左边归为左⼦树元素,右边归为右⼦树元素(可能会出现只有左⼦树或者右⼦树的情况)->观察前序遍历中左\右⼦树⼏个元素的顺序,最靠前的为左\右⼦树的根节点->重复前⾯的步骤第⼆种:已知中序遍历、后序遍历求前序遍历(题还是上⾯这道)中序遍历:CBDAEF后序遍历为:CDBFEA仍然是根据不同遍历⽅式结果的特点来重构⼆叉树,过程很相似这⾥就不详细说了,后序遍历的最后⼀个元素A是根节点,在中序遍历中以根节点A作为分界将元素分为左⼦树(CBD)和右⼦树(EF),再观察后序遍历中左⼦树的顺序是CDB,可以判断出B是左⼦树的根节点(因为后序遍历是:左->右->根),再观察中序遍历,B元素左边是C右边是D,说明B节点既有左⼦树⼜有右⼦树,左右⼦树只有⼀个元素就可以直接确定了,不⽤再返回去观察后序遍历,左⼦树重建完成,现在来看右⼦树,右⼦树有两个元素EF,观察后序遍历E在F的后⾯,所以E是右⼦树的根节点,然后看中序遍历中E只有右边⼀个F元素了,即F是E的右⼦树,此时整个⼆叉树重构完成总结⼀下上述步骤:先观察后序遍历找到根节点->观察中序遍历将根节点左边归为左⼦树元素,右边归为右⼦树元素(可能会出现只有左⼦树或者右⼦树的情况)->观察后序遍历中左\右⼦树⼏个元素的顺序,最靠后的为左\右⼦树的根节点->重复前⾯的步骤注意:已知前序遍历、后序遍历⽆法求出中序遍历(因为由前序后序重构出来的⼆叉树不⽌⼀种)举个栗⼦左图这两种⼆叉树前序(BEFA)和后序(AFEB)⼀样,但对应的中序遍历结果不⼀样(左边的是AFEB右边的是BEFA),所以仅靠前序后序是重构出唯⼀的⼆叉树。

二叉树的遍历运算

二叉树的遍历运算

二叉树的遍历运算二叉树是一种常见的数据结构,它由节点和边组成,每个节点最多有两个子节点,分别为左子节点和右子节点。

对于二叉树的遍历运算,主要包括前序遍历、中序遍历和后序遍历。

本文将为读者详细介绍这三种遍历方式,并给出相应的代码示例,希望能够帮助读者更好地理解和应用二叉树的遍历运算。

首先是前序遍历,顾名思义,前序遍历是先遍历根节点,然后遍历左子树,最后遍历右子树。

具体步骤如下:1. 如果当前节点为空,返回上一级。

2. 访问当前节点。

3. 遍历当前节点的左子树。

4. 遍历当前节点的右子树。

下面是前序遍历的代码示例:```pythondef pre_order(root):if root:print(root.value)pre_order(root.left)pre_order(root.right)```接下来是中序遍历,中序遍历的顺序是先遍历左子树,然后遍历根节点,最后遍历右子树。

具体步骤如下:1. 如果当前节点为空,返回上一级。

2. 遍历当前节点的左子树。

3. 访问当前节点。

4. 遍历当前节点的右子树。

下面是中序遍历的代码示例:```pythondef in_order(root):if root:in_order(root.left)print(root.value)in_order(root.right)```最后是后序遍历,后序遍历的顺序是先遍历左子树,然后遍历右子树,最后遍历根节点。

具体步骤如下:1. 如果当前节点为空,返回上一级。

2. 遍历当前节点的左子树。

3. 遍历当前节点的右子树。

4. 访问当前节点。

下面是后序遍历的代码示例:```pythondef post_order(root):if root:post_order(root.left)post_order(root.right)print(root.value)```通过以上代码示例,我们可以清晰地看到了前序遍历、中序遍历和后序遍历的实现过程。

先序中序后序遍历算法

先序中序后序遍历算法

先序中序后序遍历算法
先序、中序和后序遍历是二叉树遍历的三种基本方法,它们可以帮助我们按照不同顺序访问树中的节点。

下面我会分别介绍这三种遍历算法。

1. 先序遍历:
先序遍历是指先访问根节点,然后递归地对左子树进行先序遍历,最后递归地对右子树进行先序遍历。

因此,先序遍历的顺序是根-左-右。

2. 中序遍历:
中序遍历是指先递归地对左子树进行中序遍历,然后访问根节点,最后递归地对右子树进行中序遍历。

因此,中序遍历的顺序是左-根-右。

3. 后序遍历:
后序遍历是指先递归地对左子树进行后序遍历,然后递归地
对右子树进行后序遍历,最后访问根节点。

因此,后序遍历的顺序
是左-右-根。

这三种遍历算法都是基于递归的思想实现的,它们在不同的应
用场景下都有各自的优势。

例如,先序遍历常用于复制整棵树,中
序遍历常用于二叉搜索树的查找操作,后序遍历常用于计算表达式
树的值等。

除了递归实现外,这三种遍历算法也可以通过迭代的方式实现,通常使用栈来辅助实现。

在实际应用中,根据具体的问题和数据结
构的特点,选择合适的遍历算法可以提高算法的效率和准确性。

总之,先序、中序和后序遍历算法是树结构中常用的基本算法,它们在数据结构和算法领域具有重要的意义,对于理解树的结构和
实现树相关的操作非常重要。

希望以上介绍能够帮助你更好地理解
这三种遍历算法。

树——二叉树的先序、中序和后序遍历

树——二叉树的先序、中序和后序遍历

树——⼆叉树的先序、中序和后序遍历1,⼆叉树是否只有⼀种遍历⽅式(层次遍历)?2,典型的⼆叉树的遍历⽅式:1,先序遍历(Pre-Order Traversal);2,中序遍历(In-Order Traversal);3,后序遍历(Post-Order Traversal);3,先序遍历(“先序”指最先访问根结点中的数据元素): 1,⼆叉树为空:1,⽆操作,直接返回;2,⼆叉树不为空:1,访问根结点中的数据元素;2,先序遍历左⼦树;3,先序遍历右⼦树;4,先序遍历功能定义及其代码实现:1,代码⽰例:1 preOrderTraversal(node)2 {3if( noe != NULL )4 {5 access(node->value);6 preOrderTraversal(node->left);7 preOrderTraversal(node->right);8 }9 } 2,功能函数代码实现:1 /* 实现先序遍历,队⾥⾥⾯保存的数据元素⽤来反应遍历时候结点次序 */2void PreOrderTraversal(BTreeNode<T>* node, LinkQueue<BTreeNode<T>*>& queue)3 {4if( node != NULL )5 {6 queue.add(node); // 访问中间结点7 PreOrderTraversal(node->left, queue);8 PreOrderTraversal(node->right, queue);9 }10 }5,中序遍历(“中序”指中间访问根结点中的数据元素): 1,⼆叉树为空:1,⽆操作,直接返回;2,⼆叉树不为空:1,中序遍历左⼦树;2,访问根结点中的数据元素;3,中序遍历右⼦树;6,中序遍历功能定义:1,代码⽰例:1 inOrderTraversal(node)2 {3if(node != NULL)4 {5 inOrderTraversal(node->left);6 access(node->value);7 inOrderTraversal(node->right);8 }9 } 2,功能函数代码实现:1 /* 实现中序遍历,队⾥⾥⾯保存的数据元素⽤来反应遍历时候结点次序 */2void inOrderTraversal(BTreeNode<T>* node, LinkQueue<BTreeNode<T>*>& queue) 3 {4if( node != NULL )5 {6 inOrderTraversal(node->left, queue);7 queue.add(node); // 访问中间结点8 inOrderTraversal(node->right, queue);9 }10 }7,后续遍历(“后序”指最后访问根结点中的数据元素):1,⼆叉树为空:1,⽆操作,直接返回;2,⼆叉树不为空:1,后序遍历左⼦树;2,后序遍历右⼦树;3,访问根结点中的数据元素;8,后续遍历功能定义:1,代码⽰例:1 postOrderTraversal(node)2 {3if( node != NULL )4 {5 postOrderTraversal(node->left);6 postOrderTraversal(node->right);7 access(node->value);8 }9 } 2,功能函数代码实现:1 /* 实现后序遍历,队⾥⾥⾯保存的数据元素⽤来反应遍历时候结点次序 */2void postOrderTraversal(BTreeNode<T>* node, LinkQueue<BTreeNode<T>*>& queue)3 {4if( node != NULL )5 {6 postOrderTraversal(node->left, queue);7 postOrderTraversal(node->right, queue);8 queue.add(node); // 访问中间结点9 }10 }9,需要考虑的问题:1,是否可以将⼆叉树的典型便利算法集成到 BTree 中?如果可以,代码需要做怎样的改动?10,设计要点:1,不能与层次遍历函数冲突,必须设计新的函数接⼝;2,算法执⾏完成后,能够⽅便的获取遍历结果;3,遍历结果能够反映结点访问的先后次序;11,函数接⼝设计:1,SharedPointer<Array<T> > traversal(BTTraversal order):1,根据参数 order 选择执⾏遍历算法(先序,中序,后序);2,返回值为堆空间中的数组对象(⽣命周期由智能指针管理);3,数组元素的次序反映遍历的先后次序;12,典型遍历⽰例:13,遍历算法成员函数实现: 1,定义遍历⽅式:1/* 定义排序的⽅式 */2enum BTTraversal3 {4 PreOrder,5 InOrder,6 PostOrder,7 LevelOrder // 重构了“树——⼆叉树线索化”中的层次遍历次序8 }; 2,遍历的功能函数:1 /* 遍历的功能函数,第⼆个参数⽤于保存访问时,结点的先后顺序 */2void traversal(BTTraversal order, LinkQueue<BTreeNode<T>*>& queue)3 {4switch(order)5 {6case PreOrder:7 PreOrderTraversal(root(), queue);8break;9case InOrder:10 inOrderTraversal(root(), queue);11break;12case PostOrder:13 postOrderTraversal(root(), queue);14 Break;15default:16 THROW_EXCEPTION(InvalidParameterException, "Parameter order is invalid ...");17break;18 }19 } 3,遍历的实现:1 /* 典型的⼆叉树遍历,前序、中序、后续 */2 SharedPointer< Array<T> > traversal(BTTraversal order)3 {4 DynamicArray<T>* ret = NULL;5 LinkQueue<BTreeNode<T>*> queue; // 保存遍历结点次序,⽤ queue 来传递元素的值是⼀个很好的抉择; 67 traversal(order, queue); // 执⾏功能函数89 ret = new DynamicArray<T>(queue.length()); // 申请动态数组1011if( ret != NULL ) // 保存遍历所得的动态数组12 {13 /* 将队列中,结点⾥⾯数据元素的值,依次放到返回数组⾥⾯ */14for(int i=0; i<ret->length(); i++, queue.remove()) // 这⾥不要忘了将队列依次删除⾸元素15 {16 ret->set(i, queue.front()->value); // 将结点⾥⾯数据元素值依次放到返回数组⾥⾯17 }18 }19else20 {21 THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create return array ...");22 }2324return ret;25 }14,⼩结:1,⼆叉树的典型遍历都是以递归⽅式执⾏的;2,BTree 以不同的函数接⼝⽀持典型遍历;3,层次遍历与典型遍历互不冲突;4,遍历结果能够反映树结点访问的先后次序;。

二叉树(前序,中序,后序,层序)遍历递归与循环的python实现

二叉树(前序,中序,后序,层序)遍历递归与循环的python实现

⼆叉树(前序,中序,后序,层序)遍历递归与循环的python实现⼆叉树的遍历是在⾯试使⽐较常见的项⽬了。

对于⼆叉树的前中后层序遍历,每种遍历都可以递归和循环两种实现⽅法,且每种遍历的递归实现都⽐循环实现要简洁。

下⾯做⼀个⼩结。

⼀、中序遍历前中后序三种遍历⽅法对于左右结点的遍历顺序都是⼀样的(先左后右),唯⼀不同的就是根节点的出现位置。

对于中序遍历来说,根结点的遍历位置在中间。

所以中序遍历的顺序:左中右1.1 递归实现每次递归,只需要判断结点是不是None,否则按照左中右的顺序打印出结点value值。

class Solution:def inorderTraversal(self, root):""":type root: TreeNode:rtype: List[int]"""if not root:return []return self.inorderTraversal(root.left) + [root.val] + self.inorderTraversal(root.right)1.2 循环实现循环⽐递归要复杂得多,因为你得在⼀个函数中遍历到所有结点。

但是有句话很重要:对于树的遍历,循环操作基本上要⽤到栈(stack)这个结构对于中序遍历的循环实现,每次将当前结点(curr)的左⼦结点push到栈中,直到当前结点(curr)为None。

这时,pop出栈顶的第⼀个元素,设其为当前结点,并输出该结点的value值,且开始遍历该结点的右⼦树。

例如,对于上图的⼀个⼆叉树,其循环遍历过程如下表:No.输出列表sol栈stack当前结点curr1[][]12[][1]23[][1,2]44[][1,2,4]None5[4][1,2] 4 -> None(4的右结点)6[4,2][1] 2 -> 57[4,2][1,5]None(5的左结点)8[4,2,5][1] 5 -> None(5的右结点)9[4,2,5,1][]310[4,2,5,1][3]NoneNo.输出列表sol栈stack当前结点curr11[4,2,5,1,3][]None可见,规律为:当前结点curr不为None时,每⼀次循环将当前结点curr⼊栈;当前结点curr为None时,则出栈⼀个结点,且打印出栈结点的value值。

二叉树的前、中、后、层序遍历的递归实现

二叉树的前、中、后、层序遍历的递归实现

⼆叉树的前、中、后、层序遍历的递归实现前中后序三种遍历⽅法对于左右结点的遍历顺序都是⼀样的(先左后右),唯⼀不同的就是根节点的出现位置。

1.前序:前序遍历指根结点在最前⾯输出,所以前序遍历的顺序是:中左右。

递归:class Solution: def preorderTraversal(self, root): ##前序遍历 """ :type root : TreeNode :rtype: List[int] """ if not root: return [] return [root.val] + self.inorderTraversal(root.left) + self.inorderTraversal(root.right)循环class Solution:def preorderTraversal(self, root): ## 前序遍历stack = []sol = []curr = rootwhile stack or curr:if curr:sol.append(curr.val)stack.append(curr.right)curr = curr.leftelse:curr = stack.pop()return sol2.中序:对于中序遍历来说,根结点的遍历位置在中间,所以中序遍历的顺序:左中右。

递归class Solution:def inorderTraversal(self, root):""":type root: TreeNode:rtype: List[int]"""if not root:return []return self.inorderTraversal(root.left) + [root.val] + self.inorderTraversal(root.right)循环class Solution: def inorderTraversal(self, root): stack = [] sol = [] curr = root while stack or curr: if curr: stack.append(curr) curr = curr.left else: curr = stack.pop() sol.append(curr.val) curr = curr.right return sol3.后序:后序遍历指根结点在最后⾯输出,所以后序遍历的顺序是:左右中。

LeetCode二叉树的前序、中序、后序遍历(递归实现)

LeetCode二叉树的前序、中序、后序遍历(递归实现)

LeetCode⼆叉树的前序、中序、后序遍历(递归实现)本⽂⽤递归算法实现⼆叉树的前序、中序和后序遍历,提供Java版的基本模板,在模板上稍作修改,即可解决LeetCode144. Binary Tree Preorder Traversal(⼆叉树前序遍历),94. Binary Tree Inorder Traversal(⼆叉树中序遍历),145. Binary Tree Postorder Traversal(⼆叉树后序遍历)。

基本概念⼆叉树的遍历是根据访问结点操作发⽣位置命名:前序:访问根结点的操作发⽣在遍历其左右⼦树之前。

中序:访问根结点的操作发⽣在遍历其左右⼦树之中。

后序:访问根结点的操作发⽣在遍历其左右⼦树之后。

模板准备模板⽐较简单,废话不说了,直接上代码。

⼆叉树节点定义://Definition for a binary tree node.public class TreeNode {int val;TreeNode left;TreeNode right;TreeNode(int x) { val = x; }}前序遍历:public void preOrder(TreeNode node){if(node == null){return;}System.out.println(node.val);preOrder(node.left);preOrder(node.right);}中序遍历:public void inOrder(TreeNode node){if(node == null){return;}inOrder(node.left);System.out.println(node.val);inOrder(node.right);}后序遍历:public void postOrder(TreeNode node){if(node == null){return;}postOrder(node.left);postOrder(node.right);System.out.println(node.val);}LeetCode题解LeetCode上⾯关于⼆叉树遍历的问题有:#Title14494145解答以上问题,只需要在遍历模板上稍作修改即可:题⽬要求返回类型是List,所以只需要在访问元素的时候把元素添加到结果列表中。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档