1. 程式人生 > 其它 >JZ8 二叉樹的下一個結點

JZ8 二叉樹的下一個結點

JZ8 二叉樹的下一個結點

描述

給定一個二叉樹其中的一個結點,請找出中序遍歷順序的下一個結點並且返回。注意,樹中的結點不僅包含左右子結點,同時包含指向父結點的next指標。下圖為一棵有9個節點的二叉樹。樹中從父節點指向子節點的指標用實線表示,從子節點指向父節點的用虛線表示

示例:
輸入:{8,6,10,5,7,9,11},8
返回:9
解析:這個組裝傳入的子樹根節點,其實就是整顆樹,中序遍歷{5,6,7,8,9,10,11},根節點8的下一個節點就是9,應該返回{9,10,11},後臺只打印子樹的下一個節點,所以只會列印9,如下圖,其實都有指向左右孩子的指標,還有指向父節點的指標,下圖沒有畫出來

分析

初拿到這道題,很明顯看出是一個二叉樹的中序遍歷就可以解決的問題,但是仔細看了題目之後,發現,題目會給兩個引數,而這兩個引數組裝成的是一個二叉樹節點(可以是其中樹的任意節點),這樣的話,如果使用普通的遍歷方法直接做,就會有問題,需要多一步遍歷這個節點的next找到整棵樹的根節點,之後使用dfs進行中序遍歷得到結果。

程式碼

      /**
     * JZ8 二叉樹的下一個結點
     * @param pNode
     * @return
     */
    public TreeLinkNode GetNext(TreeLinkNode pNode) {
        //提出題目中要求對比的值
        Integer value = pNode.val;
        //通過不斷的尋找next找到整棵樹的根節點
        while (pNode.next != null) {
            pNode = pNode.next;
        }
        //結果佇列
        Queue<TreeLinkNode> queue = new LinkedList<>();
        //dfs遍歷使用的棧,儲存沒有遍歷過的節點用
        Stack<PosNode> treeStack = new Stack<>();
        //根節點
        PosNode rootNode = new PosNode(pNode);
        //根節點加入棧
        treeStack.push(rootNode);
        //如果所有節點都已經遍歷過就跳出迴圈
        while (treeStack.size() > 0) {
            //中序遍歷,先遍歷左子樹
            if (treeStack.peek().node.left != null && treeStack.peek().visitLeft == false) {
                PosNode posNode = new PosNode(treeStack.peek().node.left);
                //證明左子樹訪問過
                treeStack.peek().visitLeft = true;
                treeStack.push(posNode);
            }else {
                //把節點值值儲存在結果佇列中
                queue.offer(treeStack.peek().node);
                //證明左子樹訪問過
                treeStack.peek().visitLeft = true;
                //開始遍歷右子樹
                if (treeStack.peek().node.right != null && treeStack.peek().isVisitRight == false) {
                    PosNode posNode = new PosNode(treeStack.peek().node.right);
                    treeStack.peek().isVisitRight = true;
                    treeStack.push(posNode);
                }else {
                    //如果右子樹也遍歷過或者為空的話
                    treeStack.peek().isVisitRight = true;
                    //通過出棧尋找左右子樹都沒有遍歷過的節點
                    while (treeStack.size() != 0 && treeStack.peek().isVisitRight == true && treeStack.peek().visitLeft == true)
                        treeStack.pop();
                }
            }
        }

        //儲存的中序遍歷結果進行值的比較找出結果
        while (queue.size() != 0) {
            if (queue.peek().val != value) {
                queue.poll();
            }else {
                queue.poll();
                return queue.peek();
            }
        }

        //找不到的話返回空值
        return null;
    }

    /**
     * 儲存節點以及記錄節點的左右子樹是否訪問過的表質量
     */
    class PosNode{
        TreeLinkNode node;
        boolean visitLeft = false;
        boolean isVisitRight = false;

        PosNode(TreeLinkNode node) {
            this.node = node;
        }
    }

總結

需要熟練使用程式碼來遍歷二叉樹,本人的方法使用記憶體佔用較高,後續可以去除結果佇列,直接在遍歷中使用標誌量記錄結果返回。