二叉樹是一種非常重要的數據結構,很多其他數據機構都是基於二叉樹的基礎演變過來的。二叉樹有前、中、后三種遍歷方式,因為樹的本身就是用遞歸定義的,因此采用遞歸的方法實現三種遍歷,不僅代碼簡潔且容易理解,但其開銷也比較大,而若采用非遞歸方法實現三種遍歷,則要用棧來模擬實現(遞歸也是用棧實現的)。下面先簡要介紹三種遍歷方式的遞歸實現,再詳細介紹三種遍歷方式的非遞歸實現--基於Java實現的。
//package com.xforg.dataStructure;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
/**
* Created by Administrator on 2016/9/5.
* By XFORG
*/
class TreeNode{// 節點的定義
int value;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int value){
this.value = value;
}
}
/**
* 二叉樹的前序遍歷的遞歸調用 --- 根節點 -- 左孩子--右孩子
* 該方法很簡單,根據需要遍歷節點的順序,遞歸的將遍歷到的節點值放入list中。
* 即:每次遞歸都是先放頭結點,再遍歷左子樹,最后是右子樹。
* 遞歸調用簡單,當是當節點過多時,其效率就會很差,而且比較耗費空間
* Created by Administrator on 2016/9/5.
*/
/*public class BinaryTree {
public static void fun(TreeNode pHead){
ArrayList<Integer> list = new ArrayList<>();
if(pHead != null){
list.add(pHead.value);
}
if(pHead.left != null)
fun(pHead.left);
if(pHead.right != null)
fun(pHead.right);
}
}*/
/**
* 二叉樹的中序遍歷的遞歸調用 --- 左孩子 -- 根節點--右孩子
*/
/*public class BinaryTree{
public static void fun(TreeNode pHead){
ArrayList<TreeNode> list = new ArrayList<TreeNode>();
while(pHead != null){
if(pHead.left != null)
fun(pHead.left);
list.add(pHead);
if(pHead.right != null)
fun(pHead.right);
}
}
}*/
/**
* 二叉樹的后序遍歷的遞歸調用 --- 左孩子-- 右孩子--根節點
*/
/*public class BinaryTree{
public static void fun(TreeNode pHead) {
public static void fun(TreeNode pHead){
ArrayList<TreeNode> list = new ArrayList<TreeNode>();
while(pHead != null){
if(pHead.left != null)
list.add(pHead.left);
if(pHead.right != null)
list.add(pHead.right);
list.add(pHead);
}
}
}
}*/
/**
* 二叉樹的前序遍歷的非遞歸實現--- 根節點 -- 左孩子--右孩子
*先訪問根節點 再訪問左子樹,最后訪問右子樹。而對於每個子樹來說,又按照同樣的訪問順序進行遍歷。
* Created by Administrator on 2016/9/5.
*/
public class BinaryTree{
public static void fun(TreeNode pHead){
Stack<TreeNode> stack = new Stack<TreeNode>();
Queue<Integer> q = new LinkedList<Integer>();//用來存放遍歷的結果
TreeNode pCur = pHead;
TreeNode node = null;
//當前節點非空或者Stack非空時執行
while(pCur != null || !stack.isEmpty()){
q.add(pCur.value);//簡單的觀察一下程序結構,會發現每次入棧元素都為當前的“根節點”---而入棧的順序是根節點,左子節點,右子節點。
stack.push(pCur);
pCur=pCur.left;
while(pCur == null && !stack.isEmpty()){
pCur = stack.peek();
node = stack.pop();
pCur=pCur.right;
}
}
for(Integer i : q)
System.out.print(i+" ");
}
public static void main(String[] args){
TreeNode t1= new TreeNode(1);
TreeNode t2= new TreeNode(2);
TreeNode t3= new TreeNode(3);
TreeNode t4= new TreeNode(4);
TreeNode t5= new TreeNode(5);
TreeNode t6= new TreeNode(6);
TreeNode t7= new TreeNode(7);
t1.left=t2;
t1.right=t3;
t2.left=t4;
t2.right=t5;
t3.left=t6;
t3.right=t7;
t4.left =null;
t4.right=null;
t6.left=null;
t6.right=null;
t7.left=null;
t7.right=null;
fun(t1);
}
}
/**
* 二叉樹的中序遍歷的非遞歸實現--- 左孩子-- 根節點 --右孩子
*/
/*public class BinaryTree{
public static void fun(TreeNode pHead){
Stack<TreeNode> stack = new Stack<TreeNode>();
Queue<Integer> q = new LinkedList<Integer>();
TreeNode pCur = pHead;
TreeNode node = null;
while(pCur != null || !stack.isEmpty()){
stack.push(pCur);
pCur=pCur.left;
while(pCur == null && !stack.isEmpty()){
pCur = stack.peek();
node = stack.pop();
q.add(node.value);//觀察會發現,先序和中序唯一不同之處就在這條語句的位置。。。。。q中存儲的是出棧元素。
pCur = pCur.right;
}
}
for(Integer i : q)
System.out.print(i+" ");
}
public static void main(String[] args){
TreeNode t1= new TreeNode(1);
TreeNode t2= new TreeNode(2);
TreeNode t3= new TreeNode(3);
TreeNode t4= new TreeNode(4);
TreeNode t5= new TreeNode(5);
TreeNode t6= new TreeNode(6);
TreeNode t7= new TreeNode(7);
t1.left=t2;
t1.right=t3;
t2.left=t4;
t2.right=t5;
t3.left=t6;
t3.right=t7;
t4.left =null;
t4.right=null;
t6.left=null;
t6.right=null;
t7.left=null;
t7.right=null;
fun(t1);
}
}*/