1. 程式人生 > >Java實現簡單二叉樹遍歷

Java實現簡單二叉樹遍歷

楔子

最近聽了個詞叫紅黑樹,看了下,發現真難。突然覺得自己好失敗。難的不會,寫個簡單的吧。就隨手寫了個二叉樹實現了下遍歷功能,好像比以前只會複製貼上的自己強了點,安慰下自己。

實現樹

二叉樹的組成部分就是節點和關聯關係。Java裡一個節點就是一個類,關聯關係直接設計成屬性,結果樹和節點就成了一個類了。

public class StreeNode {
    private String name;
    private Integer value;

    // 父節點
    private StreeNode parentNode;

    // 左孩子節點
    private
StreeNode leftNode; // 右孩子節點 private StreeNode rightNode; public StreeNode(String name, Integer value) { super(); this.name = name; this.value = value; } ··· }

為了方便構造二叉樹,增加一個簡單的增加節點的方法,同時實現成有序的

    /**
     * 增加一個節點並排序
     * 
     * @param node
     */
    public
void appendChildNode(StreeNode node) { if (node.value > this.value) { setRightNode(node); return; } setLeftNode(node); } private void setLeftNode(StreeNode leftNode) { if (this.leftNode == null) { leftNode.setParentNode(this
); this.leftNode = leftNode; } else { this.leftNode.appendChildNode(leftNode); } } private void setRightNode(StreeNode rightNode) { if (this.rightNode == null) { rightNode.setParentNode(this); this.rightNode = rightNode; } else { this.rightNode.appendChildNode(rightNode); } }

因為有parentNode屬性,簡單實現了通過樹關係中任意節點獲得root節點的方法。

    public StreeNode getRootNode() {
        if (parentNode != null) {
            return parentNode.getRootNode();
        }
        return this;
    }

實現樹遍歷

概念就不贅述了


    /**
     * 中序遍歷
     */
    public void middleForEach() {
        if (getLeftNode() != null) {
            getLeftNode().middleForEach();
        }
        System.out.println(this);
        if (getRightNode() != null) {
            getRightNode().middleForEach();
        }
    }

    /**
     * 後序遍歷
     */
    public void lastForEach() {
        if (getLeftNode() != null) {
            getLeftNode().lastForEach();
        }
        if (getRightNode() != null) {
            getRightNode().lastForEach();
        }
        System.out.println(this);
    }

    /**
     * 先序遍歷
     */
    public void fristForEach() {
        System.out.println(this);
        if (getLeftNode() != null) {
            getLeftNode().fristForEach();
        }
        if (getRightNode() != null) {
            getRightNode().fristForEach();
        }
    }

總結:

由於二叉樹結構設計時是自身包含同類型的物件實現關係,所以幾個方法都是回撥方法,類內實現。
三種遍歷方法,在概念的理解上的差異在程式實現中卻很小,程式碼差異很小。

附完整程式碼

public class StreeNode {
    private String name;
    private Integer value;

    // 父節點
    private StreeNode parentNode;

    // 左孩子節點
    private StreeNode leftNode;
    // 右孩子節點
    private StreeNode rightNode;

    public StreeNode(String name, Integer value) {
        super();
        this.name = name;
        this.value = value;
    }

    public StreeNode getParentNode() {
        return parentNode;
    }

    public void setParentNode(StreeNode parentNode) {
        this.parentNode = parentNode;
    }

    public StreeNode getLeftNode() {
        return leftNode;
    }

    /**
     * 增加一個節點並排序
     * 
     * @param node
     */
    public void appendChildNode(StreeNode node) {
        if (node.value > this.value) {
            setRightNode(node);
            return;
        }
        setLeftNode(node);
    }

    private void setLeftNode(StreeNode leftNode) {
        if (this.leftNode == null) {
            leftNode.setParentNode(this);
            this.leftNode = leftNode;
        } else {
            this.leftNode.appendChildNode(leftNode);
        }
    }

    private void setRightNode(StreeNode rightNode) {
        if (this.rightNode == null) {
            rightNode.setParentNode(this);
            this.rightNode = rightNode;
        } else {
            this.rightNode.appendChildNode(rightNode);
        }
    }

    public StreeNode getRightNode() {
        return rightNode;
    }

    public StreeNode getRootNode() {
        if (parentNode != null) {
            return parentNode.getRootNode();
        }
        return this;
    }

    /**
     * 中序遍歷
     */
    public void middleForEach() {
        if (getLeftNode() != null) {
            getLeftNode().middleForEach();
        }
        System.out.println(this);
        if (getRightNode() != null) {
            getRightNode().middleForEach();
        }
    }

    /**
     * 後序遍歷
     */
    public void lastForEach() {
        if (getLeftNode() != null) {
            getLeftNode().lastForEach();
        }
        if (getRightNode() != null) {
            getRightNode().lastForEach();
        }
        System.out.println(this);
    }

    /**
     * 先序遍歷
     */
    public void fristForEach() {
        System.out.println(this);
        if (getLeftNode() != null) {
            getLeftNode().fristForEach();
        }
        if (getRightNode() != null) {
            getRightNode().fristForEach();
        }
    }

    @Override
    public String toString() {
        return "StreeNode [name=" + name + ", value=" + value + ", parentNode=" + checkNullName(parentNode)
                + ", leftNode=" + checkNullName(leftNode) + ", rightNode=" + checkNullName(rightNode) + "]";
    }

    private String checkNullName(StreeNode node) {
        return node == null ? "null" : node.name;
    }
}

測試用例

    @Test
    public void test() throws InterruptedException {
        StreeNode node = new StreeNode("A", 50);

        List<String> names = Arrays.asList("B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L");
        List<Integer> valuses = Arrays.asList(85, 14, 63, 27, 37, 29, 71, 22, 4, 75, 76);

        for (int i = 0; i < valuses.size(); i++) {
            node.appendChildNode(new StreeNode(names.get(i), valuses.get(i)));
        }

        System.out.println("先");
        node.fristForEach();

        System.out.println("中");
        node.middleForEach();

        System.out.println("後");
        node.lastForEach();

    }

測試結果

先
StreeNode [name=A, value=50, parentNode=null, leftNode=C, rightNode=B]
StreeNode [name=C, value=14, parentNode=A, leftNode=J, rightNode=E]
StreeNode [name=J, value=4, parentNode=C, leftNode=null, rightNode=null]
StreeNode [name=E, value=27, parentNode=C, leftNode=I, rightNode=F]
StreeNode [name=I, value=22, parentNode=E, leftNode=null, rightNode=null]
StreeNode [name=F, value=37, parentNode=E, leftNode=G, rightNode=null]
StreeNode [name=G, value=29, parentNode=F, leftNode=null, rightNode=null]
StreeNode [name=B, value=85, parentNode=A, leftNode=D, rightNode=null]
StreeNode [name=D, value=63, parentNode=B, leftNode=null, rightNode=H]
StreeNode [name=H, value=71, parentNode=D, leftNode=null, rightNode=K]
StreeNode [name=K, value=75, parentNode=H, leftNode=null, rightNode=L]
StreeNode [name=L, value=76, parentNode=K, leftNode=null, rightNode=null]
中
StreeNode [name=J, value=4, parentNode=C, leftNode=null, rightNode=null]
StreeNode [name=C, value=14, parentNode=A, leftNode=J, rightNode=E]
StreeNode [name=I, value=22, parentNode=E, leftNode=null, rightNode=null]
StreeNode [name=E, value=27, parentNode=C, leftNode=I, rightNode=F]
StreeNode [name=G, value=29, parentNode=F, leftNode=null, rightNode=null]
StreeNode [name=F, value=37, parentNode=E, leftNode=G, rightNode=null]
StreeNode [name=A, value=50, parentNode=null, leftNode=C, rightNode=B]
StreeNode [name=D, value=63, parentNode=B, leftNode=null, rightNode=H]
StreeNode [name=H, value=71, parentNode=D, leftNode=null, rightNode=K]
StreeNode [name=K, value=75, parentNode=H, leftNode=null, rightNode=L]
StreeNode [name=L, value=76, parentNode=K, leftNode=null, rightNode=null]
StreeNode [name=B, value=85, parentNode=A, leftNode=D, rightNode=null]
後
StreeNode [name=J, value=4, parentNode=C, leftNode=null, rightNode=null]
StreeNode [name=I, value=22, parentNode=E, leftNode=null, rightNode=null]
StreeNode [name=G, value=29, parentNode=F, leftNode=null, rightNode=null]
StreeNode [name=F, value=37, parentNode=E, leftNode=G, rightNode=null]
StreeNode [name=E, value=27, parentNode=C, leftNode=I, rightNode=F]
StreeNode [name=C, value=14, parentNode=A, leftNode=J, rightNode=E]
StreeNode [name=L, value=76, parentNode=K, leftNode=null, rightNode=null]
StreeNode [name=K, value=75, parentNode=H, leftNode=null, rightNode=L]
StreeNode [name=H, value=71, parentNode=D, leftNode=null, rightNode=K]
StreeNode [name=D, value=63, parentNode=B, leftNode=null, rightNode=H]
StreeNode [name=B, value=85, parentNode=A, leftNode=D, rightNode=null]
StreeNode [name=A, value=50, parentNode=null, leftNode=C, rightNode=B]

最後,中序遍歷的輸出結果是有序的。