数据结构THU2018 - 树

1. 树的节点定义

在这里插入图片描述
在这里插入图片描述

每个节点都指向一个parent(根节点除外),每个节点可以有一个左孩子,一个右孩子。

struct Node{
    Node* parent = NULL;
    Node* left_child = NULL;
    Node* right_child = NULL;
    int data = -1;
    Node(int e){
        data = e;
    }
    Node* InsertAsLC(int e){ //插入左节点
        Node* lc = new Node(e);
        this->left_child = lc;
        this->left_child->parent = this;
        return lc;
    }
    Node* InsertAsRC(int e){ //插入左节点
        Node* rc = new Node(e);
        this->right_child = rc;
        this->right_child->parent = this;
        return rc;
    }
    int size(){ // 返回树的规模
        if(!this)
            return 0;
        if(!left_child && !right_child)
            return 1;
        return 1+left_child->size()+right_child->size();
    }
};

2. 树的遍历

2.1 先序遍历

先访问根节点,再访问左孩子,最后访问右孩子:
在这里插入图片描述

2.1.1 递归解法
void preorder_traverse(Node* root){ //树的先序遍历
    if(root == NULL)
        return;
    cout<<root->data<<"$";
    preorder_traverse(root->left_child);
    preorder_traverse(root->right_child);
}
2.1.2 迭代解法

先令根节点入栈。在栈空之前,每次取top节点,使右孩子入栈、左孩子入栈。
在这里插入图片描述
在这里插入图片描述

stack<Node*> Stack;
    Stack.push(root);
    while(!Stack.empty()){
        Node* top = Stack.top();
        cout<<top->data<<"&";
        Stack.pop();
        if(top->right_child)
            Stack.push(top->right_child);
        if(top->left_child)
            Stack.push(top->left_child);
2.2 中序遍历

先访问左孩子,然后访问父亲,然后访问右孩子。

2.2.1 递归方法

在这里插入图片描述
在这里插入图片描述

2.2.2 中序遍历下的直接后继

当该节点有右孩子,那么就是右边子树一直向左找到的那个节点:
在这里插入图片描述
如果该节点没有右孩子,那么就是该节点作为右孩子一直向左上找parent,最后一步再向右上走一步:
在这里插入图片描述

Node* succ(){
        if(this->right_child){ //有右孩子
            Node* r = this->right_child;
            while(r->left_child){
                r = r->left_child;
            }
            return r;
        }
        else{ //只有左孩子
            Node* l = this;
            while(l->parent != NULL && l->parent->right_child == l){ //向左上迈一步
                l = l->parent;
            }
            return l->parent;
        }
    }
2.3 后序遍历

在这里插入图片描述
举例:表达式树就是后序遍历
在这里插入图片描述

2.4 层次遍历

在这里插入图片描述

例子:
在这里插入图片描述

void level_traverse(Node* root){ //树的先序遍历
    queue<Node*> Q;
    Q.push(root);
    while(!Q.empty()){
        Node* front = Q.front();
        cout<<front->data<<"*";
        Q.pop();
        if(front->left_child)
            Q.push(front->left_child);
        if(front->right_child)
            Q.push(front->right_child);
    }
}

3. 二叉树重建

3.1 [前序 | 后序] + 中序

在这里插入图片描述
Leetcode: 重建二叉树 https://leetcode-cn.com/problems/zhong-jian-er-cha-shu-lcof/

class Solution {
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        if(preorder.size() == 0) //别忘记递归停止条件
            return NULL;
        if(preorder.size() == 1) {
            TreeNode* root = new TreeNode(preorder[0]);
            return root;
        }
        vector<int> preorder_left; //左子树的先序遍历
        vector<int> preorder_right; //右子树的先序遍历
        vector<int> inorder_left; //左子树的中序遍历
        vector<int> inorder_right; //右子树的中序遍历
        int mid = preorder[0];
        TreeNode* root = new TreeNode(mid);
        int mid_pos; //root在中序遍历的位置
        for(int i = 0;i < inorder.size(); i++){
            if(inorder[i] == mid){
                mid_pos = i;
                break;
            }
        }
        int left_len = mid_pos;
        for(int i=1;i<1+left_len;i++)
            preorder_left.push_back(preorder[i]);
        for(int i = 1+left_len; i<preorder.size();i++)
            preorder_right.push_back(preorder[i]);
        for(int i = 0;i<left_len;i++)
            inorder_left.push_back(inorder[i]);
        for(int i= left_len + 1;i<inorder.size();i++)
            inorder_right.push_back(inorder[i]);

        TreeNode* left_tree = buildTree(preorder_left,inorder_left);
        TreeNode* right_tree = buildTree(preorder_right,inorder_right);
        root->left = left_tree;
        root->right = right_tree;
        return root;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值