二叉樹的實現、廣度優先遍歷和遞歸、非遞歸的深度優先遍歷,思路在註釋中:
package 二叉樹;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Queue;
public class BinaryTree<E> {
public static class TreeNode<E>{
TreeNode<E> leftChild;
TreeNode<E> rightChild;
E value;
public TreeNode(E value, TreeNode<E> leftChild, TreeNode<E> rightChild){
this.value = value;
this.leftChild = leftChild;
this.rightChild = rightChild;
}
}
TreeNode<E> root;
public BinaryTree(TreeNode<E> root){
this.root = root;
}
public void breadFirstTravel(){
Queue<TreeNode<E>> queue = new LinkedList<TreeNode<E>>();
queue.offer(root);
while(!queue.isEmpty()){
TreeNode<E> currentNode = queue.poll();
System.out.print(currentNode.value+" ");
if(currentNode.leftChild!=null)
queue.add(currentNode.leftChild);
if(currentNode.rightChild!=null)
queue.add(currentNode.rightChild);
}
System.out.println();
}
public void preRootTravalWithRecursion(){
preRootTravalWithRecursion(root);
System.out.println();
}
private void preRootTravalWithRecursion(TreeNode<E> node){
if(node!=null){
System.out.print(node.value+" ");
preRootTravalWithRecursion(node.leftChild);
preRootTravalWithRecursion(node.rightChild);
}
}
public void inRootTravalWithRecursion(){
inRootTravalWithRecursion(root);
System.out.println();
}
private void inRootTravalWithRecursion(TreeNode<E> node){
if(node!=null){
inRootTravalWithRecursion(node.leftChild);
System.out.print(node.value+" ");
inRootTravalWithRecursion(node.rightChild);
}
}
public void postRootTravalWithRecursion(){
postRootTravalWithRecursion(root);
System.out.println();
}
private void postRootTravalWithRecursion(TreeNode<E> node){
if(node!=null){
postRootTravalWithRecursion(node.leftChild);
postRootTravalWithRecursion(node.rightChild);
System.out.print(node.value+" ");
}
}
//單棧實現非遞歸先序遍歷 訪問節點 右子樹入棧 左子樹入棧
public void preRootTravelWithoutRecursion(){
Deque<TreeNode<E>> deque = new LinkedList<TreeNode<E>>();
TreeNode<E> temp ;
if(root!=null){
deque.addLast(root);
while(!deque.isEmpty()){
//訪問節點
temp = deque.removeLast();
System.out.print(temp.value+" ");
//右子樹入棧
if(temp.rightChild!=null)
deque.addLast(temp.rightChild);
//左子樹入棧
if(temp.leftChild!=null)
deque.addLast(temp.leftChild);
}
System.out.println();
}
}
//單棧非遞歸實現二叉樹的中序遍歷
public void inRootTravelWithoutRecursion(){
Deque<TreeNode<E>> deque = new LinkedList<TreeNode<E>>();
TreeNode<E> temp = root;
while(temp!=null||!deque.isEmpty()){
//當前節點所有左側子節點壓入棧
while(temp!=null){
deque.addLast(temp);
temp = temp.leftChild;
}
//訪問當前結點 轉向右子樹
if(!deque.isEmpty()){
temp = deque.removeLast();
System.out.print(temp.value+" ");
//轉向右子樹
temp = temp.rightChild;
}
}
System.out.println();
}
//非遞歸單棧後序遍歷
public void postRootTravelWithoutRecursion(){
Deque<TreeNode<E>> deque = new LinkedList<TreeNode<E>>();
TreeNode<E> pointer = root;
TreeNode<E> preNode = null;//存放上一個被訪問過的元素
while(pointer!=null){
for(;pointer.leftChild!=null;pointer = pointer.leftChild){//將所有有左子樹的結點壓入棧中
deque.addLast(pointer);
}
while(pointer!=null && (pointer.rightChild==null||preNode==pointer.rightChild)){//右子樹被訪問過了或者右子樹爲空
System.out.print(pointer.value+" ");
preNode = pointer;//把pointer置爲上一個訪問節點
if(deque.isEmpty())
{
return;
}
pointer = deque.removeLast();
}
deque.addLast(pointer);
pointer = pointer.rightChild;
}
System.out.println();
}
}
對於廣度優先遍歷,藉助隊列來實現,從根開始,將根入隊列,然後如果左孩子不爲空,左孩子入隊列,右孩子不爲空,右孩子入隊列。然後出對列,繼續訪問,直到隊列空。
對於遞歸實現的深度優先遍歷,每當要訪問一個結點,便對這個結點的左孩子右孩子進行遞歸深度優先遍歷,先序、中序、後序只不過是對該節點訪問、對左孩子遞歸、對右孩子遞歸的順序問題而已。
對於非遞歸的先序遍歷,藉助棧來實現。從根開始,訪問根結點,將其右子樹入棧,然後左子樹入棧。彈棧重複上述步驟,直到棧空。
對於非遞歸的中序遍歷,藉助棧來實現。對於訪問一個結點,將其所有左節點入棧。然後彈棧,訪問當前節點,轉向棧內結點的右子樹,如果這些右子樹有左子樹,繼續入棧這些左結點。重複以上,直到棧空並且當前訪問結點爲空。
對於非遞歸的後序遍歷,藉助棧來實現。將所有有左子樹的結點壓入棧中,當前結點爲最後一個沒有左子樹的結點,如果當前結點沒有右子樹或者右子樹被訪問過,則訪問當前結點,將當前結點置爲上一次訪問的結點,否則當前結點入棧,轉向右子樹。