LeetCode算法練習——樹(一)

樹的定義,想必大家都不陌生,在樹正式進入前,我們需要回顧一下二叉樹的幾種遍歷方法,尤其很多題目都是圍繞樹的遞歸遍歷進行考察。

樹的遞歸遍歷

struct Node{
	int val;
	Node * left;
	Node * right;
	Node(int x) :val(x), left(nullptr), right(nullptr){};
};
 
void creatBinaryTree(Node * &root){        //樹的創建
	int x;
	cin >> x;
	if (x == -1){
		root = nullptr;
		return;
	}
	root = new Node(x);
	creatBinaryTree(root->left);
	creatBinaryTree(root->right);
}
void visit(Node *T){                        //樹的訪問
	if (T->val != -1)
		cout << T->val << " ";
}
/**遞歸方式遍歷**/
//先序遞歸遍歷
void preOrder(Node * root){
	if (root != nullptr){
		visit(root);
		preOrder(root->left);
		preOrder(root->right);
	}
}
//中序遞歸遍歷
void inOrder(Node * root){
	if (root != nullptr){
		inOrder(root->left);
		visit(root);
		inOrder(root->right);
	}
}
//後序遞歸遍歷
void postOrder(Node * root){
	if (root != nullptr){
		postOrder(root->left);
		postOrder(root->right);
		visit(root);
	}
}

樹的非遞歸遍歷

LeetCode144. 二叉樹的前序遍歷

思路:棧壓入根節點,進行判空循環,設置一個指針p,其元素爲棧頂元素,出棧之後,將指針p所指的元素壓入容器res中;如果p節點有右孩子,則將右孩子入棧,之後再看p節點是否有左孩子,再將其左孩子入棧,先右後左的順序是因爲棧後進先出的規則;直到棧爲空,結束循環。

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

LeetCode94. 二叉樹的中序遍歷

思路:初始化p指針爲根節點,設置循環條件爲p指針不爲空或棧s不爲空;如果p指針不爲空,則將p節點入棧,p指針變爲其左孩子;若p指針爲空,則另p指針爲棧頂節點並出棧,將p指針所對應的元素壓入容器中,p指針變爲其右孩子。

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        stack<TreeNode*> s;
        vector<int> res;
        if(root == NULL)    return res;
        TreeNode* p = root;
        while(p || !s.empty()){
            if(p){
                s.push(p);
                p = p->left;
            }
            else{
                p = s.top();
                s.pop();
                res.push_back(p->val);
                p = p->right;
            }
        }
        return res;
    }
};

LeetCode145. 二叉樹的後序遍歷

思路:棧壓入根節點,進行判空循環,設置一個指針p,其元素爲棧頂元素,出棧之後,將指針p所指的元素壓入容器res的開頭,這樣依次插入的元素在容器中是逆序的;如果p節點有左孩子,則將左孩子入棧,之後再看p節點是否有右孩子,再將其右孩子入棧;直到棧爲空,結束循環。

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        stack<TreeNode*> s;
        vector<int> res;
        if(root == NULL)    return res;
        TreeNode* p = NULL;
        s.push(root);
        while(!s.empty()){
            p = s.top();
            s.pop();
            res.insert(res.begin(), p->val);
            if(p->left) s.push(p->left);
            if(p->right)    s.push(p->right);
        }
        return res;
    }
};

LeetCode102. 二叉樹的層序遍歷 && 劍指 Offer 32 - II. 從上到下打印二叉樹 II

思路:根節點入隊,進行判空循環;隊頭元素出隊,依次判斷隊頭元素左右孩子是否存在,存在則依次入隊,我們會設置一個end來標記一層的最後一個節點,作爲一層遍歷的結束標誌,結束後,會將一層的信息壓入res容器中並清空臨時存放容器。

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> res;
        vector<int> tmp;
        queue<TreeNode*> q;
        TreeNode* end = root;           //標記一層的最後一個節點
        if (root == NULL) return res;
        q.push(root);
        while(!q.empty()){
            tmp.push_back(q.front()->val);
            if(q.front()->left != NULL) q.push(q.front()->left);
            if(q.front()->right != NULL)    q.push(q.front()->right);
            if(q.front() == end){       //一層遍歷結束
                end = q.back();
                res.push_back(tmp);
                tmp.clear();
            }
            q.pop();
        }
        return res;
    }
};

 

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