1. 程式人生 > 其它 >演算法筆記-尋找二叉樹的前後置節點

演算法筆記-尋找二叉樹的前後置節點

  我們前面寫過二叉樹的前序,中序,後續遍歷演算法,今天聊到的前後置節點就是對於中序遍歷來說的順序前後節點,如下圖是按中序遍歷順序1-10的節點:

比如3的前置節點為2,後置節點為4,我們先來看看後置節點的演算法思想:

  我們都知道中序遍歷是按照節點左-父-右順序遍歷的,因此一個節點的後置節點只會有兩種情況:1.在右子節點的所在的樹上,2.當前節點所在位置處於某一父(可能是祖父,曾祖父,這裡統稱父)節點的左子節點的樹上,否則肯定是不存在的,我們在細分析這兩點:

  1:右子節點所在樹上有很多節點,那麼我們如何知道具體是哪個節點呢?其實這個問題我們可以換個角度:我們如何找到右子節點樹上的第一個節點,這個答案就顯而易見了:最左節點

  2:細評第二種情況之前我們可以先思考一個問題,中序遍歷時,如果當前節點已經是某一結點的最右節點,那麼這個節點是否是這個節點下面的遍歷最後的一個節點?答案是肯定的,那麼我們只能繼續往上找父節點,如果這個節點在父節點的右節點上,那說明對於父節點所在的樹上,依舊是最右節點,直到找到這個在父節點的左節點時,說明這個父節點是這整個樹的後置節點,而這個數最後一個節點就是我們選中的節點,那麼不正說明這個節點的後置節點是最後找到的這個父節點嗎。

  理解起來可能有點繁雜,這裡我對中序遍歷也做一個昇華:理解中序遍歷時,不要侷限於某個點,比如對於根節點來說,左子樹相當於左,右子樹相當於右,而左-父-右的順序對於這一整顆樹來說則是左子樹-根節點-右子樹,對於下面的子樹也是一樣的道理,這樣就可以把無數個小的行為概括成一個大的行為,同樣對於每一個子樹也是這樣一個個大的行為。我們在找後置節點時其實就是在考慮兩個問題:1.該節點作為某一顆子樹的根節點,那麼我們就找這一顆子樹的右節點的第一個遍歷的點,2.作為左子樹上的最後一個節點,那麼我們就需要找到這個節點作為找到的父節點左子樹的最後一個節點(也是最右節點),這樣就好理解多了。

說了那麼多,還是用程式碼來看:

public static Node getNextNode(Node node){

        if(node == null){
            return null;
        }

        if(node.right != null){
            return findLeftNode(node.right);
        }else{
            Node parent = node.parent;
            while(parent != null && node != parent.left){
                node 
= parent; parent = parent.parent; } return parent; } }
private static Node findLeftNode(Node right) {
        while(right.left != null) right = right.left;
        return right;
    }

如果可以理解上面的思想,程式碼還是很簡單的。

如果可以理解後置節點,前置節點也是一樣的道理,我們就可以直接看中序遍歷順序:左-父-右,那麼我們也可以分為兩種情況:1.作為父節點,那麼前置節點一定在左子樹上,只需要找到左子樹最後一個點(最右節點) 2.作為右節點,那麼我們只需要找到以該節點為右子樹的最左節點的最大樹父節點(也就是第一個將該節點所在子樹作為右子樹的節點),程式碼如下:

public static Node getPreNode(Node node){
        if(node == null){
            return null;
        }
        if(node.left != null){
            return findRightNode(node.left);
        }else{
            Node parent = node.parent;
            while (parent!= null && node != parent.right){
                node = parent;
                parent = parent.parent;
            }
            return parent;
        }
    }
private static Node findRightNode(Node left) {
        while(left.right != null) left = left.right;
        return left;
    }