二叉树的相关概念
二叉树的定义
二叉树(Binary Tree)是n(n>=0)个有限元素的集合,该集合或者为空,或者由一个称为根(root)的元素及两个不相交的,被称为左子树和右子树的二叉树组成。当集合为空时,称该二叉树为空二叉树,在二叉树中,一个元素也称为一个结点。
二叉树是有序的,即若将其左右子树颠倒,就称为另一颗不同的二叉树。
结点的度:结点所拥有的子树的个数称为该结点的度。
叶结点:度为0的结点称为叶结点,或者称为终端结点。
树的深度:树中所有结点的最大层数称为树的深度。
树的度:树中个结点度的最大值称为该树的度。
2.二叉树的三种遍历方式
二叉树有三种遍历方式:前序(父节点,左节点,右节点),中序(左节点,父节点,右节点),后序(左节点,右节点,父节点)。
如上图所示的一颗二叉树,按照三种遍历方式所打印的结果应该是:
前序:1 2 4 8 9 5 10 11 3 6 7
中序:8 4 9 2 10 5 11 1 6 3 7
后序:8 9 4 10 11 5 2 6 7 3 1
遍历方式的代码:
import java.util.ArrayList; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { TreeNode root =new TreeNode(0); TreeNode left=new TreeNode(1); TreeNode right=new TreeNode(2); TreeNode left2=new TreeNode(3); TreeNode right2=new TreeNode(4); TreeNode left3=new TreeNode(5); TreeNode right3=new TreeNode(6); TreeNode left4=new TreeNode(7); TreeNode right4=new TreeNode(8); left.left=left2; left.right=right2; right.left=left3; right.right=right3; root.left=left; root.right=right; left2.left=left4; left2.right=right4; Print.PrintTreeNode(root); System.out.println("先序遍历:"); PreOrderTraverse(root); System.out.println(); System.out.println("中序遍历:"); MidOrderTraverse(root); System.out.println(); System.out.println("后序遍历:"); LastOrderTraverse(root); System.out.println(); } public static void PreOrderTraverse(TreeNode root){ TreeNode node=root; if(node!=null){ System.out.print(node.val+" "); PreOrderTraverse(node.left); PreOrderTraverse(node.right); } } public static void MidOrderTraverse(TreeNode root){ TreeNode node=root; if(node!=null){ MidOrderTraverse(node.left); System.out.print(node.val+" "); MidOrderTraverse(node.right); } } public static void LastOrderTraverse(TreeNode root){ TreeNode node=root; if(node!=null){ LastOrderTraverse(node.left); LastOrderTraverse(node.right); System.out.print(node.val+" "); } } } class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int x) { val = x; } } class Print{ //打印TreeNode public static void PrintTreeNode(TreeNode root){ ArrayList arrayList=PrintFromTopToBottom(root); printTree(arrayList,arrayList.size()); } //转换TreeNode为ArrayList private static ArrayList<Integer> PrintFromTopToBottom(TreeNode root) { ArrayList<Integer> list = new ArrayList(); if(root == null) return list; Queue<TreeNode> queue = new LinkedList(); queue.offer(root); while(!queue.isEmpty()){ TreeNode treeNode = queue.poll(); list.add(treeNode.val); if(treeNode.left != null) queue.offer(treeNode.left); if(treeNode.right != null) queue.offer(treeNode.right); } return list; } //以树形打印ArrayList private static void printTree(ArrayList array,int len){ int layers = (int)Math.floor(Math.log((double)len)/Math.log((double)2))+1; //树的层数 int maxWidth = (int)Math.pow(2,layers)-1; //树的最大宽度 int endSpacing = maxWidth; int spacing; int numberOfThisLayer; for(int i=1;i<=layers;i++){ //从第一层开始,逐层打印 endSpacing = endSpacing/2; //每层打印之前需要打印的空格数 spacing = 2*endSpacing+1; //元素之间应该打印的空格数 numberOfThisLayer = (int)Math.pow(2, i-1); //该层要打印的元素总数 int j; for(j=0;j<endSpacing;j++){ System.out.print(" "); } int beginIndex = (int)Math.pow(2,i-1)-1; //该层第一个元素对应的数组下标 for(j=1;j<=numberOfThisLayer;j++){ System.out.print(array.get(beginIndex++)+""); for(int k=0;k<spacing;k++){ //打印元素之间的空格 System.out.print(" "); } if(beginIndex == len){ //已打印到最后一个元素 break; } } System.out.println(); } System.out.println(); } }
0 1 2 3 4 5 6 7 8 先序遍历: 0 1 3 7 8 4 2 5 6 中序遍历: 7 3 8 1 4 0 5 2 6 后序遍历: 7 8 3 4 1 5 6 2 0 Process finished with exit code 0
非遍历方式的代码:
先序遍历:
public static void PreOrderTraverse(TreeNode root) { TreeNode node = root; Stack<TreeNode> stack = new Stack<TreeNode>(); while(node!=null||!stack.isEmpty()){ while(node!=null){ System.out.print(node.val+" "); stack.push(node); node=node.left; } if(!stack.isEmpty()){ node=stack.pop(); node=node.right; } } } public static void PreOrderTraverse2(TreeNode root){ Stack<TreeNode> stack=new Stack<TreeNode>(); TreeNode node=root; stack.push(node); while(!stack.isEmpty()){ node=stack.pop(); System.out.print(node.val+" "); if(node.right!=null) { stack.push(node.right); } if(node.left!=null){ stack.push(node.left); } } }
第二种方式比较容易,效率也应该高一些。
中序遍历:
public static void MidOrderTraverse(TreeNode root){ TreeNode node = root; Stack<TreeNode> stack = new Stack<TreeNode>(); while(node!=null||!stack.isEmpty()){ while(node!=null){ stack.push(node); node=node.left; } if(!stack.isEmpty()){ node=stack.pop(); System.out.print(node.val+" "); node=node.right; } } }
后序遍历:
// 非递归后序遍历 public static void LastOrderTraverse(TreeNode root) { Stack<TreeNode> treeNodeStack = new Stack<TreeNode>(); TreeNode node = root; TreeNode lastVisit = root; while (node != null || !treeNodeStack.isEmpty()) { while (node != null) { treeNodeStack.push(node); node = node.left; } //查看当前栈顶元素 node = treeNodeStack.peek(); //如果其右子树也为空,或者右子树已经访问 //则可以直接输出当前节点的值 if (node.right == null || node.right == lastVisit) { System.out.print(node.val + " "); treeNodeStack.pop(); lastVisit = node; node = null; } else { //否则,继续遍历右子树 node = node.right; } } }
https://segmentfault.com/a/1190000004853442
http://www.jianshu.com/p/456af5480cee
https://segmentfault.com/a/1190000002606302
http://www.voidcn.com/blog/u013344815/article/p-4677425.html