这是个常见的面试题,比如说通过二叉树的先序和中序遍历,得到二叉树的层序遍历等问题
先序+中序->建树
假设现在有个二叉树,如下:
此时遍历顺序是:
PreOrder: GDAFEMHZ InOrder: ADEFGHMZ PostOrder: AEFDHZMG
现在给出先序(preOrder)和中序(InOrder),建立一颗二叉树
或者给出中序(InOrder)和后序(PostOrder), 建立二叉树,其实是一样的
树节点的定义:
class Tree{ char val; Tree left; Tree right; Tree(char val, Tree left, Tree right){ this.val = val; this.left = left; this.right = right; } Tree(){ } Tree(char val){ this.val = val; this.left = null; this.right =null; } }
建树:
public static Tree buildTree(char[] preOrder, char[] inOrder){ //preOrder是先序序列 //inOrder是中序序列 if(preOrder == null || preOrder.length == 0){ return null; } Tree root = new Tree(preOrder[0]); //找到inOrder中的root的位置 int inOrderIndex = 0; for (char i = 0; i < inOrder.length; i++){ if(inOrder[i] == root.val){ inOrderIndex = i; } } //preOrder的左子树和右子树部分 char[] preOrderLeft = Arrays.copyOfRange(preOrder, 1, 1+inOrderIndex); char[] preOrderRight = Arrays.copyOfRange(preOrder, 1+inOrderIndex, preOrder.length); //inOrder的左子树和右子树部分 char[] inOrderLeft = Arrays.copyOfRange(inOrder, 0, inOrderIndex); char[] inOrderRight = Arrays.copyOfRange(inOrder, inOrderIndex+1, inOrder.length); //递归建立左子树和右子树 Tree leftChild = buildTree(preOrderLeft, inOrderLeft); Tree rightChild = buildTree(preOrderRight, inOrderRight); root.left = leftChild; root.right = rightChild; return root; }
中序+后序去建树其实是一样的,此处不写了
各种遍历
后序遍历
public static void postOrderPrint(Tree root){ //后续遍历 //左右根 if(root.left != null){ postOrderPrint(root.left); } if(root.right != null){ postOrderPrint(root.right); } System.out.print(root.val + " "); }
举一反三,先序和中序是一样的,此处不写了
层序遍历
可以用一个队列Queue,初始先把root节点加入到队列,当队列不为空的时候取队列头的节点node,打印node的节点值,如果node的左右孩子不为空将左右孩子加入到队列中即可
public static void layerOrderPrint(Tree root){ if(root == null){ return; } //层序遍历 Queue<Tree> qe = new LinkedList<Tree>(); qe.add(root); while(!qe.isEmpty()){ Tree node = qe.poll(); System.out.print(node.val + " "); if(node.left != null){ qe.add(node.left); } if(node.right != null){ qe.add(node.right); } } }
深度优先和广度优先
其实就是换个说法而已,深度优先不就是先序遍历嘛,广度优先就是层序遍历
public static void deepFirstPrint(Tree root){ //深度优先遍历等价于先序遍历 //所以可以直接使用先序遍历 if(root == null){ return; } System.out.print(root.val + " "); if(root.left != null){ deepFirstPrint(root.left); } if(root.right != null){ deepFirstPrint(root.right); } } public static void deepFirstPrintNoneRec(Tree root){ //深度优先遍历的非递归形式 if(root == null){ return; } Stack<Tree> st = new Stack<Tree>(); st.add(root); while(!st.isEmpty()){ Tree node = st.pop(); System.out.print(node.val + " "); //栈是后进先出的 //先加右孩子后加左孩子 if(node.right != null){ st.add(node.right); } if(node.left != null){ st.add(node.left); } } }
main函数:
public static void main(String[] args) { char[] preOrder = "GDAFEMHZ".toCharArray(); char[] inOrder = "ADEFGHMZ".toCharArray(); Tree root = Main.buildTree(preOrder, inOrder); // Main.postOrderPrint(root); //后序遍历 // Main.layerOrderPrint(root); //层序遍历 // Main.deepFirstPrint(root); //深度优先遍历 // Main.deepFirstPrintNoneRec(root); //深度优先遍历的非递归版本 }
总结
以上就是本文关于Java中二叉树的建立和各种遍历实例代码的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站:
《Java编程求二叉树的镜像两种方法介绍》
《Java语言描述二叉树的深度和宽度》
《Java二叉树路径和代码示例》
如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!
根据带虚结点的先序序列建立二叉树,输出该二叉树的中序、后序遍历序列。 输入格式: 测试数据有多组,处理到文件尾。每组测试数据在一行中输入一个字符串(不含空格且长度不超过80),表示二叉树的先序遍历序列,其中字符∗表示虚结点(对应的子树为空)。 输出格式: 对于每组测试,分别在两行输出所建立二叉树的中序遍历序列和后序遍历序列。 输入样例: HDAC*BGFE** 输出样例: ADCBHFEG ABC
本文向大家介绍javascript实现二叉树遍历的代码,包括了javascript实现二叉树遍历的代码的使用技巧和注意事项,需要的朋友参考一下 前言: 紧接着上篇 二叉树的javascript实现 ,来说一下二叉树的遍历。 本次一本正经的胡说八道,以以下这个二叉树为例子进行遍历: 接着是要引入二叉树实现的代码: 二叉树遍历的分类 二叉树的遍历分为先序、中序、后序遍历。这里说到的先序、中序、后序是相
中序遍历二叉树 按完全二叉树的层次遍历给出一棵二叉树的遍历序列(其中用0表示虚结点),要求输出该二叉树的深度及中序遍历该二叉树得到的序列。 输入格式: 首先输入一个整数T,表示测试数据的组数,然后是T组测试数据。每组测试数据首先输入一个正整数n(n≤1000),代表给出的二叉树的结点总数(当然,其中可能包含虚结点)。结点编号均为正整数,且各不相同。 然后输入n个正整数,表示按完全二叉树(即第1层1
给定一个数组,构建二叉树,并且按层次打印这个二叉树
主要内容:层次遍历的实现过程,实现代码前边介绍了 二叉树的先序、中序和后序的遍历算法,运用了 栈的 数据结构,主要思想就是按照先左子树后右子树的顺序依次遍历树中各个结点。 本节介绍另外一种遍历方式:按照二叉树中的层次从左到右依次遍历每层中的结点。具体的实现思路是:通过使用 队列的数据结构,从树的根结点开始,依次将其左孩子和右孩子入队。而后每次队列中一个结点出队,都将其左孩子和右孩子入队,直到树中所有结点都出队,出队结点的先后顺序就是层