數據結構--二叉樹

二叉樹的實現、廣度優先遍歷和遞歸、非遞歸的深度優先遍歷,思路在註釋中:

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();
    }
}

對於廣度優先遍歷,藉助隊列來實現,從根開始,將根入隊列,然後如果左孩子不爲空,左孩子入隊列,右孩子不爲空,右孩子入隊列。然後出對列,繼續訪問,直到隊列空。

對於遞歸實現的深度優先遍歷,每當要訪問一個結點,便對這個結點的左孩子右孩子進行遞歸深度優先遍歷,先序、中序、後序只不過是對該節點訪問、對左孩子遞歸、對右孩子遞歸的順序問題而已。

對於非遞歸的先序遍歷,藉助棧來實現。從根開始,訪問根結點,將其右子樹入棧,然後左子樹入棧。彈棧重複上述步驟,直到棧空。

對於非遞歸的中序遍歷,藉助棧來實現。對於訪問一個結點,將其所有左節點入棧。然後彈棧,訪問當前節點,轉向棧內結點的右子樹,如果這些右子樹有左子樹,繼續入棧這些左結點。重複以上,直到棧空並且當前訪問結點爲空。

對於非遞歸的後序遍歷,藉助棧來實現。將所有有左子樹的結點壓入棧中,當前結點爲最後一個沒有左子樹的結點,如果當前結點沒有右子樹或者右子樹被訪問過,則訪問當前結點,將當前結點置爲上一次訪問的結點,否則當前結點入棧,轉向右子樹。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章