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;
    }
};

 

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