JZ8 二叉樹的下一個結點
阿新 • • 發佈:2021-10-21
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; } }
總結
需要熟練使用程式碼來遍歷二叉樹,本人的方法使用記憶體佔用較高,後續可以去除結果佇列,直接在遍歷中使用標誌量記錄結果返回。