该文主要介绍2叉数的基本遍历的实现,在此以前,首先应该知道2叉数有哪些遍历?java
先序遍历:根-->左-->右 即先访问根结点,而后访问左子树,最后访问右子树。在遍历左、右子树时,仍然如此。node
上图遍历结果:A,B,D,E,C,F,G。数据结构
中序遍历:左-->根-->右 即先访问左子树,而后访问根结点,最后访问右子树。在遍历左、右子树时,仍然如此。post
上图遍历结果:D,B,E,A,F,C,G。测试
后序遍历:左-->右-->根 即先访问左子树,而后访问右子树,最后访问根结点。在遍历左、右子树时,仍然如此。this
上图遍历结果:D,E,B,F,G,C,A。spa
层次遍历:1层,2层,3层,依次访问下来,若是某一层元素超过两个,那么从先左后右访问。code
上图遍历结果:A,B,C,D,E,F,G。(这个已经简单不行了)递归
深度遍历:首先访问根结点(A),而后沿着它的左结点依次访问(B,D),至到访问到最后一层(也就是D),再返回到它的父亲(B),访问他的右结点(E)。而后这样重复地访问完全部结点。队列
上图遍历结果:A,B,D,E,C,F,G。
备注:
1.上面的先、中、后序遍历,主要看的就是根在访问顺序中所在的位置。“根左右”,根在前,因此叫先序遍历。“左根右”,根在中,因此叫中序遍历。
2.在中序遍历中,有一种很快得出其遍历的结果的方法。叫作投影法。(你觉得我会把这个方法的连接放在这里么?No,我只会告诉你,请百度百科“中序遍历”,这里有我想给你看的“投影法”。)
如何实现?
先序遍历:首先访问根,而后递归访问左子树,再递归访问右子树便可。
中/后序遍历:相似于先序遍历。等下看源码就明白了。
层次遍历
首先将根入队列(先进先出),而后就循环判断这个队列是否为空。只要队列不为空,就取出队列中的一个结点,访问这个结点的值,再将这个结点的左结点入队列,再将这个队列的右结点入队列。
层次遍历详细解释:
以上图的2叉数为例,首先将根A结点入队列,如今用while来循环判断队列是否为空。很明显,不为空。因此取出队列中的结点(A)来访问,而后,这个结点(A)的左结点(B)不为空,入队列,这个结点的右结点(C)也不为空,入队列。因此如今队列中就又有了B、C两个结点,因此循环继续。拿出B,访问B,再将B的左右结点D、E入队列。如今队列中就有了C、D、E了。队列不为空,因此循环继续,拿出C,访问C,再将F,G入队列。如今队列中就是D、E、F、G了。队列不为空,拿出D访问,D没有子结点,那么没有新的结点入队列,但队列尚未为空,因此接着拿出E来访问,E也没有子结点,因此也没有新的结点入队列,但队列尚未为空,接着再拿队列中的F来访问,依次类推了。(写得很罗嗦,但愿能把这个过程解释清楚。)
深度遍历
首先将根入栈(先进后出),而后就循环判断这个栈是否为空。只要栈不为空,就取出栈中的一个结点,访问这个结点的值,再将这个结点的右结点入栈,再将这个结点的左结点入栈。(很相似于层次遍历的实现,只是所用的数据结构由队列变成了栈,入队列是先左后右,入栈的顺序是先右后左)
深度遍历详细解释:
这个很相似于层次遍历的详细解释,我简单得说一下。首先根A入栈,而后循环判断栈是否为空,如今栈里有结点A,因此不为空,因此取出A,访问A,将C、B入栈(也就是将A的右结点入栈,而后左结点入栈,和层次遍历时是相反的)。再判断栈是否为空,如今栈中有C、B。因为栈是后进先出的结构,因此这里是B弹出栈,访问B,再将B的子结点E、D入栈,那现栈中就有了C、E、D。判断栈不空,又弹出D,访问D,将D的子结点入栈。这样类推下去,就完成了遍历。
java代码以下:(有点多,不过该代码可测试运行)
package com.cdu.binaryTree; import java.util.LinkedList; public class MyBinaryTree { public static void main(String[] args) { //初始化一棵2叉数 BinaryTree binaryTree = BinaryTree.initBinaryTree(); // 先序遍历 System.out.println("先序遍历:"); binaryTree.preOrderTraversal(binaryTree); System.out.println("\n"); // 中序遍历 System.out.println("中序遍历:"); binaryTree.midOrderTrversal(binaryTree); System.out.println("\n"); // 后序遍历 System.out.println("后序遍历:"); binaryTree.postOrderTrversal(binaryTree); System.out.println("\n"); // 层次遍历 System.out.println("层次遍历:"); binaryTree.levelTraversal(binaryTree); System.out.println("\n"); // 深度遍历 System.out.println("深度遍历:"); binaryTree.depthTraversal(binaryTree); System.out.println("\n"); } } class BinaryTree{ private int data; //结点值 private BinaryTree left; //左子结点 private BinaryTree right; //右子结点 public BinaryTree(int data){ this.data = data; } /** * @Description 初始化二叉数 * @param * @return 获得以下所示的二叉数 * 1 * * * * 2 3 * * * * * * 4 5 6 7 * * * * * 9 10 11 * * * 8 * * 先序遍历结果:1,2,4,9,5,10,8,11,3,6,7 * 中序遍历结果:4,9,2,8,10,5,11,1,6,3,7 * 后序遍历结果:9,4,8,10,11,5,2,6,7,3,1 * 层次遍历结果:1,2,3,4,5,6,7,9,10,11,8 * 深度遍历结果:1,2,4,9,5,10,8,11,3,6,7 */ public static BinaryTree initBinaryTree(){ BinaryTree root = new BinaryTree(1); BinaryTree node2 = new BinaryTree(2); BinaryTree node3 = new BinaryTree(3); BinaryTree node4 = new BinaryTree(4); BinaryTree node5 = new BinaryTree(5); BinaryTree node6 = new BinaryTree(6); BinaryTree node7 = new BinaryTree(7); BinaryTree node8 = new BinaryTree(8); BinaryTree node9 = new BinaryTree(9); BinaryTree node10 = new BinaryTree(10); BinaryTree node11 = new BinaryTree(11); root.setLeft(node2); root.setRight(node3); node2.setLeft(node4); node2.setRight(node5); node3.setLeft(node6); node3.setRight(node7); node4.setRight(node9); node5.setLeft(node10); node5.setRight(node11); node10.setLeft(node8); return root; } /** * @Description 先序遍历 * @param binaryTree 二叉数 * @return */ public void preOrderTraversal(BinaryTree binaryTree){ // 当2叉数为空时,递归结束。 if (binaryTree == null){ return ; }else{ System.out.print(binaryTree.getData() + ","); //访问结点 preOrderTraversal(binaryTree.getLeft()); //递归遍历左子树 preOrderTraversal(binaryTree.getRight()); //递归遍历右子树 } } /** * @Description 中序遍历 * @param binaryTree 二叉数 * @return */ public void midOrderTrversal(BinaryTree binaryTree){ if (binaryTree == null){ return ; }else{ midOrderTrversal(binaryTree.getLeft()); System.out.print(binaryTree.getData() + ","); midOrderTrversal(binaryTree.getRight()); } } /** * @Description 后序遍历 * @param binaryTree 二叉数 * @return */ public void postOrderTrversal(BinaryTree binaryTree){ if (binaryTree == null){ return ; }else{ postOrderTrversal(binaryTree.getLeft()); postOrderTrversal(binaryTree.getRight()); System.out.print(binaryTree.getData()+ ","); } } /** * @Description 层次遍历:先将根节点入队列,而后判断只要队列不为空, * 那么就从队列中poll一个结点来访问,而后再将该结点的左结点入队列,而后再将右结点入队列 * @param * @return */ public void levelTraversal(BinaryTree binaryTree){ LinkedList<BinaryTree> queue = new LinkedList<BinaryTree>(); if (binaryTree != null){ queue.offer(binaryTree); } // 只要队列不为空,则遍历队列中结点 while (!queue.isEmpty()){ BinaryTree node = queue.poll(); System.out.print(node.getData() + ","); // 若结点有子结点,那么将该结点的左、右结点存入队列 if (node.getLeft() != null){ queue.offer(node.getLeft()); } if (node.getRight() != null){ queue.offer(node.getRight()); } } } /** * @Description 深度遍历:先将根节点入队列,而后判断只要栈不为空, * 那么就在栈中pop一个结点来访问,而后再将该结点的右结点压栈,而后再将左结点压栈 * @param * @return */ public void depthTraversal(BinaryTree binaryTree){ LinkedList<BinaryTree> stack = new LinkedList<BinaryTree>(); if (binaryTree != null){ stack.push(binaryTree); } // 只要栈不为空,则遍历栈中结点 while(!stack.isEmpty()){ BinaryTree node = stack.pop(); System.out.print(node.getData() + ","); // 若结点有子结点,那么将该结点的右、左结点存入队列 if (node.getRight() != null){ stack.push(node.getRight()); } if (node.getLeft() != null){ stack.push(node.getLeft()); } } } /*--------------getter and setter--------------------*/ public int getData() { return data; } public void setData(int data) { this.data = data; } public BinaryTree getLeft() { return left; } public void setLeft(BinaryTree left) { this.left = left; } public BinaryTree getRight() { return right; } public void setRight(BinaryTree right) { this.right = right; } }