補充5:二叉樹的實現

二叉樹結點數據結構

public class TreeNode{
public int key = 0;
public String data = null;
public boolean isVisited = false;
public TreeNode leftChild = null;
public TreeNode rightChild = null;

public TreeNode(int key,String data){
this.key = key;
this.data = data;
this.leftChild = null;
this.rightChild = null;
}
}

初始化根節點

TreeNode root = null;
public javatest(){
root = new TreeNode(1,"root A");
}

創建二叉樹

public void createBinTree(TreeNode root){
TreeNode newNodeB = new TreeNode(2,"B");
TreeNode newNodeC = new TreeNode(3,"C");
TreeNode newNodeD = new TreeNode(4,"D");
TreeNode newNodeE = new TreeNode(5,"E");
TreeNode newNodeF = new TreeNode(6,"F");

root.leftChild = newNodeB;
                root.rightChild = newNodeC;
                root.leftChild.leftChild = newNodeD;
                root.leftChild.rightChild = newNodeE;
                root.rightChild.rightChild = newNodeF;

}

訪問節點

    public void visted(TreeNode subTree) {
        subTree.isVisited = true;
        System.out.println("key:" + subTree.key + "--name:" + subTree.data);
    }

遞歸與非遞歸進行前中後序遍歷

前序遍歷

    // 前序遍歷
    public void preOrder(TreeNode subTree) {
        if (subTree != null) {
            visted(subTree);
            preOrder(subTree.leftChild);
            preOrder(subTree.rightChild);
        }
    }

非遞歸藉助棧來實現

1.定義node來遍歷二叉樹,定義棧來儲存二叉樹結點

2.利用while循環,一開始node指向根節點,訪問node,併入棧,將node更新爲左子樹,繼續循環;當node爲null時循環停止,此時node代表的是最左節點的左節點,爲null時表示最左節點和其左子樹打印完畢。

3.接下來需要打印左節點的右子樹,取出棧頂元素,並將node更新爲棧頂元素的右子樹。

    // 前序遍歷的非遞歸實現
    public void nonRecPreOrder(TreeNode root) {
        Stack<TreeNode> stack = new Stack<TreeNode>();
        TreeNode node = root;
        while (node != null || stack.size() > 0) {
            while (node != null) {
                visted(node);
                stack.push(node);
                node = node.leftChild;
            }
            while (stack.size() > 0) {
                node = stack.pop();
                node = node.rightChild;
            }
        }
    }

中序遍歷

    // 中序遍歷
    public void inOrder(TreeNode subTree) {
        if (subTree != null) {
            inOrder(subTree.leftChild);
            visted(subTree);
            inOrder(subTree.rightChild);
        }
    }

非遞歸過程

1.定義node來遍歷二叉樹,定義棧來儲存二叉樹結點

2.利用while循環,一開始node指向根節點,入棧,然後將node更新爲左子樹,繼續循環;直到node爲null時第二層while循環停止,此時node代表最左節點的左節點。

3.接下來需要打印最左節點的左子樹;因爲左字樹爲空,所以直接打印他的根,取出棧頂元素,這就是最後一顆樹的根,打印,刪除棧頂結點,將node更新爲棧頂元素的右結點;

    // 中序遍歷的非遞歸實現
    public void nonRecInOrder(TreeNode root) {
        Stack<TreeNode> stack = new Stack<javatest.TreeNode>();
        TreeNode node = root;
        while (node != null || stack.size() > 0) {
            // 存在左子樹
            while (node != null) {
                stack.push(node);
                node = node.leftChild;
            }
            // 棧非空
            if (stack.size() > 0) {
                node = stack.pop();
                visted(node);
                node = node.rightChild;
            }
        }
    }

後序遍歷

    // 後續遍歷
    public void postOrder(TreeNode subTree) {
        if (subTree != null) {
            postOrder(subTree.leftChild);
            postOrder(subTree.rightChild);
            visted(subTree);
        }
    }

非遞歸過程

1.循環將左子樹左節點全部入棧

2.入棧結束,當前root爲最左節點的左節點;當前節點無右子樹或右子樹已經輸出,則訪問當前節點後用node記錄剛訪問過的節點,root = stack.pop();更新root爲棧內下一元素。

3.當前root有右子樹時,右子樹入棧,當前節點更新爲節點的右子樹。

    // 後序遍歷的非遞歸實現
    public void noRecPostOrder(TreeNode root) {
        Stack<TreeNode> stack = new Stack<javatest.TreeNode>();
        TreeNode node = root;
        while (root!= null) {
            // 左子樹入棧
            for (; root.leftChild != null; root = root.leftChild) {
                stack.push(root);
            }
            // 當前結點無右子樹或右子樹已經輸出
            while (root != null && (root.rightChild == null || root.rightChild == node)) {
                visted(root);
                // 紀錄上一個已輸出結點
                node = root;
                if (stack.empty())
                    return;
                root = stack.pop();
            }
            // 處理右子樹
            stack.push(root);
            root = root.rightChild;
        }
    }

完整測試

import java.util.Stack;
public class javatest {

TreeNode root = null;

public class TreeNode{
public int key = 0;
public String data = null;
public boolean isVisited = false;
public TreeNode leftChild = null;
public TreeNode rightChild = null;

public TreeNode(int key,String data){
this.key = key;
this.data = data;
this.leftChild = null;
this.rightChild = null;
}
}

public javatest(){
root = new TreeNode(1,"root A");
}

public void createBinTree(TreeNode root){
TreeNode newNodeB = new TreeNode(2,"B");
TreeNode newNodeC = new TreeNode(3,"C");
TreeNode newNodeD = new TreeNode(4,"D");
TreeNode newNodeE = new TreeNode(5,"E");
TreeNode newNodeF = new TreeNode(6,"F");

root.leftChild = newNodeB;
                root.rightChild = newNodeC;
                root.leftChild.leftChild = newNodeD;
                root.leftChild.rightChild = newNodeE;
                root.rightChild.rightChild = newNodeF;

}




    // 前序遍歷
    public void preOrder(TreeNode subTree) {
        if (subTree != null) {
            visted(subTree);
            preOrder(subTree.leftChild);
            preOrder(subTree.rightChild);
        }
    }


    // 中序遍歷
    public void inOrder(TreeNode subTree) {
        if (subTree != null) {
            inOrder(subTree.leftChild);
            visted(subTree);
            inOrder(subTree.rightChild);
        }
    }


    // 後續遍歷
    public void postOrder(TreeNode subTree) {
        if (subTree != null) {
            postOrder(subTree.leftChild);
            postOrder(subTree.rightChild);
            visted(subTree);
        }
    }
    // 前序遍歷的非遞歸實現
    public void nonRecPreOrder(TreeNode p) {
        Stack<TreeNode> stack = new Stack<TreeNode>();
        TreeNode node = p;
        while (node != null || stack.size() > 0) {
            while (node != null) {
                visted(node);
                stack.push(node);
                node = node.leftChild;
            }
            while (stack.size() > 0) {
                node = stack.pop();
                node = node.rightChild;
            }
        }
    }


    // 中序遍歷的非遞歸實現
    public void nonRecInOrder(TreeNode p) {
        Stack<TreeNode> stack = new Stack<javatest.TreeNode>();
        TreeNode node = p;
        while (node != null || stack.size() > 0) {
            // 存在左子樹
            while (node != null) {
                stack.push(node);
                node = node.leftChild;
            }
            // 棧非空
            if (stack.size() > 0) {
                node = stack.pop();
                visted(node);
                node = node.rightChild;
            }
        }
    }


    // 後序遍歷的非遞歸實現
    public void noRecPostOrder(TreeNode root) {
        Stack<TreeNode> stack = new Stack<javatest.TreeNode>();
        TreeNode node = root;
        while (root!= null) {
            // 左子樹入棧
            for (; root.leftChild != null; root = root.leftChild) {
                stack.push(root);
            }
            // 當前結點無右子樹或右子樹已經輸出
            while (root != null && (root.rightChild == null || root.rightChild == node)) {
                visted(root);
                // 紀錄上一個已輸出結點
                node = root;
                if (stack.empty())
                    return;
                root = stack.pop();
            }
            // 處理右子樹
            stack.push(root);
            root = root.rightChild;
        }
    }


    public void visted(TreeNode subTree) {
        subTree.isVisited = true;
        System.out.println("key:" + subTree.key + "--name:" + subTree.data);
    }


    // 測試
    public static void main(String[] args) {
        javatest bt = new javatest();
        bt.createBinTree(bt.root);


        System.out.println("*******(前序遍歷)[ABDECF]遍歷*****************");
        bt.preOrder(bt.root);


        System.out.println("*******(中序遍歷)[DBEACF]遍歷*****************");
        bt.inOrder(bt.root);


        System.out.println("*******(後序遍歷)[DEBFCA]遍歷*****************");
        bt.postOrder(bt.root);


        System.out.println("***非遞歸實現****(前序遍歷)[ABDECF]遍歷*****************");
        bt.nonRecPreOrder(bt.root);


        System.out.println("***非遞歸實現****(中序遍歷)[DBEACF]遍歷*****************");
        bt.nonRecInOrder(bt.root);


        System.out.println("***非遞歸實現****(後序遍歷)[DEBFCA]遍歷*****************");
        bt.noRecPostOrder(bt.root);


    }

}


結果:

*******(前序遍歷)[ABDECF]遍歷*****************
key:1--name:root A
key:2--name:B
key:4--name:D
key:5--name:E
key:3--name:C
key:6--name:F
*******(中序遍歷)[DBEACF]遍歷*****************
key:4--name:D
key:2--name:B
key:5--name:E
key:1--name:root A
key:3--name:C
key:6--name:F
*******(後序遍歷)[DEBFCA]遍歷*****************
key:4--name:D
key:5--name:E
key:2--name:B
key:6--name:F
key:3--name:C
key:1--name:root A
***非遞歸實現****(前序遍歷)[ABDECF]遍歷*****************
key:1--name:root A
key:2--name:B
key:4--name:D
key:3--name:C
key:6--name:F
***非遞歸實現****(中序遍歷)[DBEACF]遍歷*****************
key:4--name:D
key:2--name:B
key:5--name:E
key:1--name:root A
key:3--name:C
key:6--name:F
***非遞歸實現****(後序遍歷)[DEBFCA]遍歷*****************
key:4--name:D
key:5--name:E
key:2--name:B
key:6--name:F
key:3--name:C
key:1--name:root A




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