LeetCode 94. Binary Tree Inorder Traversal(二叉樹的中序遍歷,C++,Python,遞歸+非遞歸)

Given a binary tree, return the inorder traversal of its nodes’ values.

Example:

Input: [1,null,2,3]

   1
    \
     2
    /
   3

Output: [1,3,2]
Follow up: Recursive solution is trivial, could you do it iteratively?

思路:中序遍歷二叉樹,遞歸版本非常簡單。非遞歸需要使用棧來完成。具體思路參考這篇博客,其主要思想是:經過分析,中序遍歷第一個遍歷的元素一定位於二叉樹的最左下角,所以先通過循環找到這個元素,因爲後期遍歷根節點和右子樹需要使用路徑上的元素,所以在查找左下角元素的同時用棧記錄路上的節點
這部分代碼:

while (p)
{
	s.push(p);
	p = p->lchild;
}

到達左下這個元素,只有一下兩種情況,這時只要取出棧頂元素然後訪問根節點,再訪問右子樹即可,右子樹的訪問方式繼續重複左子樹,根節點,右子樹,所以只需要把上面的步驟重複執行即可。

p = s.top();
s.pop();
cout << p->data;

在這裏插入圖片描述
上面的說明遍歷了根節點位於最左下的3個節點構成的子樹,循環重複上面的過程就可以完成對整棵樹的遍歷。

while(!stk.empty()|| p){//棧不空說明還有元素沒有被訪問,開始時棧雖然爲空但p不爲空,最後p指向最右下根節點的右孩子爲null
    if(p){//找左子樹,
        stk.push(p);//記錄路徑上的節點
        p = p->left;
    }
    else{//p == NULL,到達了葉節點,或者左孩子爲空(總之這時棧頂元素的左邊肯定被訪問過)
        p = stk.top();//取出棧頂元素
        stk.pop();//訪問棧頂元素(根節點)
        ans.push_back(p->val);
        p = p->right;//訪問棧頂元素的右子樹
    }
}

C++遞歸

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        inorderTraversal2(root);
        return ans;
    }
    void inorderTraversal2(TreeNode* root) {
        if (root == NULL)
            return;
        inorderTraversal2(root->left);//左子樹
        ans.push_back(root->val);//根節點
        inorderTraversal2(root->right);//右節點
    }
    
    vector<int> ans;
};

結果:
在這裏插入圖片描述

C++非遞歸
原理可以看這篇博客,非常詳細

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        stack<TreeNode*> stk;
        TreeNode * p = root;
        while(!stk.empty()|| p){
            if(p){//找左子樹,
                stk.push(p);//記錄路徑上的節點
                p = p->left;
            }
            else{//p == NULL,到達了葉節點,或者左孩子爲空(總之這時棧頂元素的左邊肯定被訪問過)
                p = stk.top();//取出棧頂元素
                stk.pop();//訪問棧頂元素(根節點)
                ans.push_back(p->val);
                p = p->right;//訪問棧頂元素的右子樹
            }
        }
        return ans;
    }

    vector<int> ans;
};

結果:
在這裏插入圖片描述

python遞歸

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    
    def inorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        ans = []
        self.traversal(root, ans)
        return ans
        
    def traversal(self, root, ans):
        if root == None:
            return
        self.traversal(root.left, ans)
        ans.append(root.val)
        self.traversal(root.right, ans)

結果
在這裏插入圖片描述
python非遞歸

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    
    def inorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        ans = []
        stack = []
        while len(stack) or root:
            if root:
                stack.append(root)
                root = root.left
            else:
                print(len(stack))
                root = stack[-1]
                stack.pop()
                ans.append(root.val)
                root = root.right
        
        return ans

結果
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章