树是数据结构中非常重要的一个结构,二叉树的遍历也是非常重要的知识。温故而知新,今天来复习下树的遍历方法。
二叉树的遍历分为:前序遍历,中序遍历,后序遍历,以及层序遍历。前序遍历、中序遍历、后序遍历可以分别通过递归方法和非递归方法实现。代码如下:
---------------------------------------------------------------------------------------
今天新加了层序遍历的实现,详见代码 layerTranverse。
package test;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
/**
* 该二叉树的原型如下:
* A
* / \
* B C
* / \ / \
* D E F G
* / \ \ /
* H I J P
**/
public class BinaryTree {
//打印节点信息
public static void printNode(Node<String> node){
System.out.print("" + node.getData() + " " );
}
//定义节点
class Node<T>{
private T data;
private Node<T> leftNode;
private Node<T> rightNode;
public Node( T data, Node<T> leftNode, Node<T> rightNode){
this.data = data;
this.leftNode = leftNode;
this.rightNode = rightNode;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public Node<T> getLeftNode() {
return leftNode;
}
public void setLeftNode(Node<T> leftNode) {
this.leftNode = leftNode;
}
public Node<T> getRightNode() {
return rightNode;
}
public void setRightNode(Node<T> rightNode) {
this.rightNode = rightNode;
}
}
// 初始化二叉树
public Node<String> init() {
Node<String> D = new Node<String>("D", null, null);
Node<String> H = new Node<String>("H", null, null);
Node<String> I = new Node<String>("I", null, null);
Node<String> J = new Node<String>("J", null, null);
Node<String> P = new Node<String>("P", null, null);
Node<String> G = new Node<String>("G", P, null);
Node<String> F = new Node<String>("F", null, J);
Node<String> E = new Node<String>("E", H, I);
Node<String> B = new Node<String>("B", D, E);
Node<String> C = new Node<String>("C", F, G);
Node<String> A = new Node<String>("A", B, C);
return A;
}
// 递归前序遍历
protected void preOrder(Node<String> node){
BinaryTree.printNode(node);
if(node.getLeftNode() != null){
this.preOrder(node.getLeftNode());
}
if(node.getRightNode() != null){
this.preOrder(node.getRightNode());
}
}
// 递归中序遍历
protected void middleOrder(Node<String> node){
if( node.getLeftNode() != null ){
this.middleOrder(node.getLeftNode());
}
BinaryTree.printNode(node);
if(node.getRightNode() != null){
this.middleOrder(node.getRightNode());
}
}
// 递归后序遍历
protected void afterOrder(Node<String> node){
if(node.getLeftNode() != null){
this.afterOrder(node.getLeftNode());
}
if(node.getRightNode() != null){
this.afterOrder(node.getRightNode());
}
BinaryTree.printNode(node);
}
// 层序遍历
public static void layerTranverse(Node<String> root){
if(root==null){
return;
}
Queue<Node> q = new LinkedList<Node>();
q.add(root);
while(!q.isEmpty()){
Node node = q.poll();
System.out.print(node.data+" ");
if(node.leftNode != null){
q.add(node.leftNode);
}
if(node.rightNode != null){
q.add(node.rightNode);
}
}
}
/**
* 非递归方式进行遍历,需要构造栈
* 以前序为例:
* 对于任一结点,其可看做是根结点,因此可以直接访问。
* 当访问完其根节点时,若其左孩子不为空,则再访问它的左子树;
* 当访问完其左子树时,若其有孩子不为空,则再访问它的右子树。
*
* 对于任一结点P:
* 1)访问结点P,并将结点P入栈;
* 2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);若不为空,则将P的左孩子置为当前的结点P;
* 3)直到P为NULL并且栈为空,则遍历结束。
*/
// 非递归方式前序遍历
protected static void preOrder1(Node node){
Stack<Node> stack = new Stack<Node>();
if(node!=null){
stack.push(node);
while(!stack.isEmpty()){
node = stack.pop();
BinaryTree.printNode(node);
if(node.getRightNode() != null){
stack.push(node.getRightNode());
}
if(node.getLeftNode() != null){
stack.push(node.getLeftNode());
}
}
}
}
// 非递归实现中序遍历
protected static void midOrder1(Node p) {
Stack<Node> stack = new Stack<Node>();
Node node = p;
while (node != null || stack.size() > 0) {
while (node != null) {
stack.push(node);
node = node.getLeftNode();
}
if (stack.size() > 0) {
node = stack.pop();
BinaryTree.printNode(node);
node = node.getRightNode();
}
}
}
// 非递归实现后序遍历 双栈法1
protected static void afterOrder1(Node p) {
Stack<Node> lstack = new Stack<Node>();
Stack<Node> rstack = new Stack<Node>();
Node node = p, right;
do {
while (node != null) {
right = node.getRightNode();
lstack.push(node);
rstack.push(right);
node = node.getLeftNode();
}
node = lstack.pop();
right = rstack.pop();
if (right == null) {
BinaryTree.printNode(node);
}
else {
lstack.push(node);
rstack.push(null);
}
node = right;
} while (lstack.size() > 0 || rstack.size() > 0);
}
// 非递归实现后序遍历 双栈法2
protected static void iterativePostorder4(Node p) {
Stack<Node> stack = new Stack<Node>();
Stack<Node> temp = new Stack<Node>();
Node node = p;
while (node != null || stack.size() > 0) {
while (node != null) {
temp.push(node);
stack.push(node);
node = node.getRightNode();
}
if (stack.size() > 0) {
node = stack.pop();
node = node.getLeftNode();
}
}
while (temp.size() > 0) {
node = temp.pop();
BinaryTree.printNode(node);
}
}
// 非递归实现后序遍历 单栈法
protected static void iterativePostorder3(Node p) {
Stack<Node> stack = new Stack<Node>();
Node node = p, prev = p;
while (node != null || stack.size() > 0) {
while (node != null) {
stack.push(node);
node = node.getLeftNode();
}
if (stack.size() > 0) {
Node temp = stack.peek().getRightNode();
if (temp == null || temp == prev) {
node = stack.pop();
BinaryTree.printNode(node);
prev = node;
node = null;
} else {
node = temp;
}
}
}
}
public static void main(String[] args){
BinaryTree binaryTree = new BinaryTree();
Node<String> node = binaryTree.init();
System.out.println("二叉树层序遍历的结果:-->");
BinaryTree.layerTranverse(node);
System.out.println("递归前序遍历的结果:-->");
binaryTree.preOrder(node);
System.out.println('\n');
System.out.println("非递归前序遍历的结果:-->");
BinaryTree.preOrder1(node);
System.out.println('\n');
System.out.println("------------------------------------------");
System.out.println("递归中序遍历的结果:-->");
binaryTree.middleOrder(node);
System.out.println("非递归中序遍历方法的结果:-->");
BinaryTree.midOrder1(node);
System.out.println('\n');
System.out.println("------------------------------------------");
System.out.println("递归后序遍历的结果:-->");
binaryTree.afterOrder(node);
System.out.println('\n');
System.out.println("非递归后序遍历的结果:-->");
binaryTree.iterativePostorder4(node);
System.out.println('\n');
}