【leetcode】---二叉樹前、中、後序遍歷

【leetcode】二叉樹前、中、後序遍歷

前序遍歷

遞歸版本1
此解法比較簡單,先訪問 root 結點,然後用同樣的方法遞歸去訪問 root 結點的 left 結點然後是 root 結點的 right 結點,將他們放入容器vector中。注意這裏使用了遞歸的方法,遞歸越深,內存開銷越大

class Solution {
public:
	vector<int> ret;
	vector<int> preorderTraversal(TreeNode* root) {
		_prerder(root);
		return ret;
	}

	void _prerder(TreeNode* root)
	{
		if (root)
		{
			ret.push_back(root->val);//訪問其根節點
			_prerder(root->left);//遞歸左子樹
			_prerder(root->right);//遞歸右子樹
		}
	}
};

在這裏插入圖片描述
遞歸優化版本
同樣也是先訪問 root 結點,然後用同樣的方法去訪問 root 結點的 left 結點
然後是 root 結點的 right 結點,將他們放入容器vector中。在這裏我使用了一個輔助函數 PushNode(), 該方法略微優化了一些,減少程序使用的內存

class Solution {
public:
	vector<int> preorderTraversal(TreeNode* root) {
		vector<int> result;

		if (root) {
			PushNode(root, result);
		}

		return result;
	}

private:
	void PushNode(TreeNode* root, vector<int> & v) {
		if (root) {
			v.push_back(root->val);
			PushNode(root->left, v);
			PushNode(root->right, v);
		}
	}
};

在這裏插入圖片描述
非遞歸實現
此種方法需要使用一個 stack 進行輔助,首先將 root 結點 push 到 棧中,然後就在一個 while 循環裏去取棧的頂部,並將其保存。然後壓棧 root 的right 結點,然後壓棧 root 的 left 結點。注意:這裏是前序遍歷,所以先壓棧 right 結點,是因爲棧 LIFO(後進先出)的特點。直至 取完棧爲空,可以清晰看出,內存消耗少了0.4MB。

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> v;
        if(root==NULL)
        {
            return v;
        }

        stack<TreeNode*> st;
        TreeNode* tmp;

        st.push(root);

        while(!st.empty())
        {
            tmp=st.top();
            v.push_back(tmp->val);
            st.pop();

            if(tmp->right!=NULL)
            {
                st.push(tmp->right);
            }
            if(tmp->left!=NULL)
            {
                st.push(tmp->left);
            }
        }
        return v;
    }
};

在這裏插入圖片描述

中序遍歷

遞歸版本
此解法跟前序遍歷一樣,先遞歸訪問 root 結點的left節點,然後去訪問 root 結點,最後是 遞歸root 結點的 right 結點,將他們放入容器vector中。注意這裏使用了遞歸的方法,遞歸越深,內存開銷越大

class Solution {
public:
     vector<int> v;
    vector<int> inorderTraversal(TreeNode* root) {
        _inorderTraversal(root);
        return v;
    }

    void _inorderTraversal(TreeNode* root)
    {
        if(root)
        {
            _inorderTraversal(root->left);
            v.push_back(root->val);
            _inorderTraversal(root->right);
        }
    }
};

在這裏插入圖片描述
非遞歸版本
思路:用while循環找最左路節點,並將沿路的節點push_back到棧中,然後將指針tmp指向的最左路節點放入容器vector中,然後pop掉,就退回到了自身指向的val上,放入容器vector中,然後再指向其右路節點,直到棧中爲空結束。

class Solution {
public:
	vector<int> inorderTraversal(TreeNode* root) {
		vector<int> v;
		if (root == NULL)
		{
			return v;
		}
		stack<TreeNode*> st;
		TreeNode* tmp = root;

		while (tmp || st.size())
		{
			while (tmp)//一直找到最左邊的節點,將所有左路節點,全部放入棧中
			{
				st.push(tmp);
				tmp = tmp->left;
			}
			tmp = st.top();
			st.pop();
			v.push_back(tmp->val);
			tmp = tmp->right;
		}
		return v;
	}
};

在這裏插入圖片描述

後序遍歷

遞歸版本
此解法和前序遍歷一樣,用同樣的遞歸方法先去訪問 root 結點的 left 結點,然後是 root 結點的 right 結點,最後訪問 root 根結點,將他們放入容器vector中。注意這裏使用了遞歸的方法, 遞歸越深,內存開銷越大

class Solution {
public:vector<int> v;
	   vector<int> postorderTraversal(TreeNode* root) {
		   _postorderTraversal(root);
		   return v;
	   }	   
	   void _postorderTraversal(TreeNode* root)
	   {
		   if (root)
		   {
			   _postorderTraversal(root->left);
			   _postorderTraversal(root->right);
			   v.push_back(root->val);
		   }
	   }
};

在這裏插入圖片描述
非遞歸版本
大致思路和前序遍歷一樣,就是最後把前序遍歷倒過來輸出就好了。

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> v,res;
        if(root==NULL)
        {
            return v;
        }

        stack<TreeNode*> st;
        TreeNode* tmp;

        st.push(root);

        while(!st.empty())
        {
            tmp=st.top();             
            v.push_back(tmp->val);
             st.pop();            
            if(tmp->left!=NULL)
            {
                st.push(tmp->left);
            }    
            if(tmp->right!=NULL)
            {
                st.push(tmp->right);
            }          
        }
        for(int i=v.size()-1;i>=0;--i)
        {
            res.push_back(v[i]);
        }
        return res;
    }
};

在這裏插入圖片描述

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