C++前序中序後序非遞歸遍歷

前序遍歷-根左右:

循環到左子樹空,else轉右子樹,當一個結點已經訪問右子樹時,該結點出棧

#include<iostream>
#include<string>
#include<stack>
#include<sstream>
#include<vector>
using namespace std;

struct TreeNode {
    int val;
    TreeNode *left;
	TreeNode *right;
	TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> ans;
        stack<TreeNode*> treestack;
        TreeNode* tem = root;
        while(!treestack.empty()||tem){//棧空防止指針指空 
			if(tem){
				ans.push_back(tem->val);//前序在這裏進行內容的讀取 
				treestack.push(tem);//在這裏入棧,減少判斷次數 
        		tem = tem->left;
			}//左子樹到底了
			else{
				tem = treestack.top();
				treestack.pop();//左空就算結束,要彈出 
				tem = tem->right;
			}
		}
        return ans;
    }
};

int main(){
	
	TreeNode* root = new TreeNode(6);
	root->left = new TreeNode(2);
	root->left->left = new TreeNode(1);
	
	root->left->right = new TreeNode(4);
	root->left->right->left = new TreeNode(3);
	root->left->right->right = new TreeNode(5);
	
	
	root->right = new TreeNode(7);
	root->right->right = new TreeNode(8);
	root->right->right->left = new TreeNode(9);
	
	
	Solution s;
	vector<int> v = s.preorderTraversal(root);
	for(int i=0;i<v.size();i++){
		cout<<v[i]<<endl;
	}
	return 0;
} 

中序遍歷-左根右:

原理同前序,因爲總是訪問右子樹時出棧,意味着出棧結點左子樹空,即我們要訪問的結點

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> ans;
        stack<TreeNode*> treestack;
        TreeNode* tem = root;
        while(!treestack.empty()||tem){//棧空防止指針指空 
			if(tem){
				
				treestack.push(tem);//在這裏入棧,減少判斷次數 
        		tem = tem->left;
			}//左子樹到底了
			else{
				tem = treestack.top();
				treestack.pop();//左空就算結束,要彈出 
                ans.push_back(tem->val);//中序在這裏進行內容的讀取 
				tem = tem->right;
			}
		}
        return ans;
    }
};

後序遍歷-左右根:

後序非遞歸遍歷一般有兩種思路

①變左右根爲根右左再取反

即先類似前序遍歷得到根右左的結果,然後再對結果取反,思路是簡單可行的,但是不方便對樹進行其他操作,只能看遍歷結果

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> ans,fin;
        stack<TreeNode*> treestack;
        TreeNode* tem = root;
        while(!treestack.empty()||tem){//棧空防止指針指空 
			if(tem){
				ans.push_back(tem->val);
				treestack.push(tem);//在這裏入棧,減少判斷次數 
        		tem = tem->right;
			}//左子樹到底了
			else{
				tem = treestack.top();
				treestack.pop();//左空就算結束,要彈出 
				tem = tem->left;
			}
		}
		for(int i=ans.size()-1;i>=0;i--){
			fin.push_back(ans[i]);
		}
        return fin;
    }
};

②當前結點沒有孩子或孩子都被訪問時訪問此結點

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
    	TreeNode* tem;//注意這裏不需要初始化
    	stack<TreeNode*> treestack;
    	treestack.push(root);//根要先入棧,這一點與前面不同
    	vector<int> ans;
    	TreeNode* pre = NULL;
    	while(!treestack.empty()){//判斷條件只需要棧不空
    		tem = treestack.top();
    		if((tem->left==NULL&&tem->right==NULL)||(pre!=NULL&&(pre==tem->left||pre==tem->right))){
    			//子樹空或子樹都已經被訪問過 
    			ans.push_back(tem->val);
    			treestack.pop();
    			pre = tem;
			}
			else{
				if(tem->right!=NULL)treestack.push(tem->right);//先右子樹入棧
				if(tem->left!=NULL)treestack.push(tem->left);//再左子樹入棧,實際上也是根右左,只不過棧是後進先出
			}
		}
		return ans;
    }
};

 

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