1. 程式人生 > >leetcode | 二叉樹的前序遍歷、中序遍歷、後續遍歷的非遞迴實現

leetcode | 二叉樹的前序遍歷、中序遍歷、後續遍歷的非遞迴實現

  • 前序遍歷:先訪問該節點,然後訪問該節點的左子樹和右子樹;
  • 中序遍歷:先訪問該節點的左子樹,然後訪問該節點,再訪問該節點的右子樹;
  • 後序遍歷:想訪問該節點的左子樹和右子樹,然後訪問該節點。

遞迴遍歷

對於遞迴遍歷比較簡單:

void preorder(TreeNode* root) {
    if (root == NULL)
        return;
    visit(root);
    preorder(root->left);
    preorder(root->right);
}

void inorder(TreeNode* root) {
    if
(root == NULL) return; inorder(root->left); visit(root); inorder(root-<right); } void postorder(TreeNode* root) { if (root == NULL) return; postorder(root->left); postorder(root->right); visit(root); }

非遞迴(迭代)遍歷

非遞迴實現在遍歷根節點後還要回來,因此要基於棧(先進後出)來儲存節點。

二叉樹遍歷的非遞迴實現文章裡有不同的實現方式,更易於理解記憶。

前序遍歷

壓入順序:右子樹->左子樹->根節點
使得訪問的時候的順序成為:根->左子樹->右子樹

    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> s;
        if (root == NULL)
            return result;
        s.push(root);
        while
(!s.empty()) { TreeNode* p = s.top(); s.pop(); result.push_back(p->val); if (p->right) s.push(p->right); if (p->left) s.push(p->left); } return result; }

中序遍歷

壓入順序:右子樹->根->左子樹
只有當左子樹已經訪問完後,才能訪問根節點

對於任一結點P,
1)若其左孩子不為空,則將P入棧並將P的左孩子置為當前的P,然後對當前結點P再進行相同的處理;
2)若其左孩子為空,則取棧頂元素並進行出棧操作,訪問該棧頂結點,然後將當前的P置為棧頂結點的右孩子;
3)直到P為NULL並且棧為空則遍歷結束

vector<int> inorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> s;
        if (root == NULL)
            return result;
        TreeNode* p = root;
        while (!s.empty() || p != NULL) {
            if (p != NULL) {
                // push 左子樹入棧
                s.push(p);
                p = p->left;
            } else {
                // 左子樹為空時,訪問該節點,然後訪問右子樹
                p = s.top();
                result.push_back(p->val);
                s.pop();
                p = p->right;
            }
        }
        return result;  
    }

後序遍歷

先壓入根,然後是右子樹,最後左子樹
要求最後訪問根節點,即訪問該根節點時必須訪問完左子樹和右子樹,我們只需要保證訪問某一節點時,該節點的右子樹已經被訪問,否則需要將該節點重新壓入棧。

對於任一結點P,將其入棧,然後沿其左子樹一直往下搜尋,直到搜尋到沒有左孩子的結點,此時該結點出現在棧頂,但是此時不能將其出棧並訪問,因此其右孩子還為被訪問。所以接下來按照相同的規則對其右子樹進行相同的處理,當訪問完其右孩子時,該結點又出現在棧頂,此時可以將其出棧並訪問。這樣就保證了正確的訪問順序。可以看出,在這個過程中,每個結點都兩次出現在棧頂,只有在第二次出現在棧頂時,才能訪問它。

  vector<int> postorderTraversal(TreeNode* root) {
        vector<int> result;
        if (root == NULL)
            return result;
        stack<TreeNode*> s;
        TreeNode* p = root;  //當前正訪問的節點
        TreeNode* q;  //記錄剛剛訪問過的節點
        do{
            while (p != NULL) {
                s.push(p);
                p = p->left;
            }
            q = NULL;
            while (!s.empty()) {
                p = s.top();
                s.pop();
                if (p->right == q) {  //當右子樹已經訪問過了,才可以訪問根
                    result.push_back(p->val);
                    q = p;  //記錄剛剛訪問過的節點
                } else {
                    s.push(p); //第一次訪問到該節點,需要將它重新入棧
                    p = p->right;
                    break;
                }

            }
        } while (!s.empty());
        return result;
    }

相關推薦

給定一個節點,求下一個節點

題目描述 給定一個二叉樹和其中的一個結點,請找出中序遍歷順序的下一個結點並且返回。注意,樹中的結點不僅包含左右子結點,同時包含指向父結點的指標。 using namespace std; /

PTA 5-11 玩轉 (25分)【已知

5-11 玩轉二叉樹   (25分) 給定一棵二叉樹的中序遍歷和前序遍歷,請你先將樹做個鏡面反轉,再輸出反轉後的層序遍歷的序列。所謂鏡面反轉,是指將所有非葉結點的左右孩子對換。這裡假設鍵值都是互

[Leetcode 144]Binary Tree Preorder Traversal

public list left 前序 output nod roo strong while 【題目】 Given a binary tree, return the preordertraversal of its nodes‘ values. Example: Inp

Leetcode:

Leetcode: 二叉樹的前序遍歷 最近在複習資料結構, 感覺很多東西都忘得的差不多了,哪怕是看完書再看視訊,還是容易忘,所以乾脆想著配合leetcode來刷吧,Python實現起來很簡單,但是C語言也不能丟,所以C語言和Python一起吧。 題目: 給定一個二叉樹,返回它的前序遍歷。 輸入: [

[每日leetcode]

二叉樹的前序遍歷 給定一個二叉樹,返回它的 前序 遍歷。 示例: 輸入: [1,null,2,3] 1 \ 2 / 3 輸出: [1,2,3] 進階: 遞迴演算法很

LeetCode】Binary Tree Preorder Traversal 以及演算法

  Total Accepted: 17403 Total Submissions: 50093 My Submissions Given a binary tree, return the preorder traversal of its nodes' values.

leetcode | 後續實現

前序遍歷:先訪問該節點,然後訪問該節點的左子樹和右子樹; 中序遍歷:先訪問該節點的左子樹,然後訪問該節點,再訪問該節點的右子樹; 後序遍歷:想訪問該節點的左子樹和右子樹,然後訪問該節點。 遞迴遍歷 對於遞迴遍歷比較簡單: void preo

LeetCode java

給定一個二叉樹,返回它的 前序 遍歷。 示例:輸入: [1,null,2,3] 1 \ 2 / 3 輸出: [1,2,3]/** * Definition for a binary tree node. * public cl

Leetcode:的層

102. 二叉樹的層次遍歷 給定一個二叉樹,返回其按層次遍歷的節點值。 (即逐層地,從左到右訪問所有節點)。 例如: 給定二叉樹: [3,9,20,null,null,15,7], 3 / \ 9 20 / \ 15 7 返回

LeetCode 144 Binary Tree Preorder Traversal(

Given a binary tree, return thepreordertraversal of its nodes' values. For example: Given binary tr

leetcode

給定一個二叉樹 示例:輸入: [1,null,2,3] 1 \ 2 / 3 輸出: [1,2,3] 前序遍歷#include <stdio.h>

得到後

() level struct OS spa str sel src [] 二叉樹的前序遍歷為:{1,2,4,7,3,5,6,8},中序遍歷為:{4,7,2,1,5,3,8,6},求後序遍歷   # -*- coding:utf-8 -*- class Nod

數據結構35:和後

tdi 代碼 nod 完成 循環 同時 reat pan 設置 遞歸算法底層的實現使用的是棧存儲結構,所以可以直接使用棧寫出相應的非遞歸算法。 先序遍歷的非遞歸算法 從樹的根結點出發,遍歷左孩子的同時,先將每個結點的右孩子壓棧。當遇到結點沒有左孩子的時候,取棧頂的右

golang,後算法

rec == int post order nta rev UC right package main import ( "container/list" "fmt" ) // Binary Tree type Bin

/

前語  二叉樹的遍歷是指按一定次序訪問二叉樹中的每一個結點,且每個節點僅被訪問一次。 前序遍歷  若二叉樹非空,則進行以下次序的遍歷:   根節點—>根節點的左子樹—>根節點的右子樹   若要遍歷左子樹和右子樹,仍然需要按照以上次序進行,所以前序遍歷也是一個遞

【演算法】相互求法(轉)

二叉樹前序、中序、後序遍歷相互求法 原文地址      今天來總結下二叉樹前序、中序、後序遍歷相互求法,即如果知道兩個的遍歷,如何求第三種遍歷方法,比較笨的方法是畫出來二叉樹,然後根據各種遍歷不同的特性來求,也可以程式設計求出,下面我們分別說明。  

pat 甲級 1099(+層

題目連結:https://pintia.cn/problem-sets/994805342720868352/problems/994805367987355648 思路: (1)建立二叉樹 (2)將b陣列排序得到二叉樹的前序遍歷 (3)層序遍歷二叉樹 注意:二叉樹前序遍歷是先判

leetcode144 的不同

二叉樹中序遍歷 class Solution { public: vector<int> inorderTraversal(TreeNode* root) { TreeNode* cur=root; vector<int>

,後。用實現

#include<iostream> #include<stack> using namespace std; #define MAX 100 typedef struct Tree{ int data; Tree*lchild; Tree*rchild; }

已知構造(關鍵詞://先//後/先根/根/後根//搜尋/查詢)

已知中序、後序構造二叉樹 遞迴演算法 def buildTree(inorder, postorder): if inorder and postorder: postRootVal = postorder