LeetCode算法练习——树(一)

树的定义,想必大家都不陌生,在树正式进入前,我们需要回顾一下二叉树的几种遍历方法,尤其很多题目都是围绕树的递归遍历进行考察。

树的递归遍历

#include <iostream>
#include <vector>
using namespace std;

struct Node{
    int val;
    Node * left;
    Node * right;
    Node(int x) :val(x), left(nullptr), right(nullptr){};
};

Node* createTree(vector<int> tree, int start){
    if (tree[start] == -1) {
        return NULL;
    }
    Node* root = new Node(tree[start]);
    int lnode = 2*start + 1;
    int rnode = 2*start + 2;
    if ( lnode > tree.size() - 1) {
        root -> left = NULL;
    }
    else{
        root -> left = createTree(tree, lnode);
    }
    if (rnode > tree.size() - 1) {
        root -> right =NULL;
    }
    else{
        root -> right = createTree(tree, rnode);
    }
    return root;
}
/*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);
    }
}

int main(){
    vector<int> tree = {10, 5, 15, -1, -1, 6, 20};
    Node* root = createTree(tree, 0);
    preOrder(root);
    cout << endl;
    inOrder(root);
    cout << endl;
    postOrder(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;
    }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值