一. 二叉树

1.1 从中序和后序遍历序列构造二叉树

二叉树的中序遍历与先序遍历,以及二叉树的中序遍历和后序遍历可以唯一地确定一颗二叉树

以中序遍历和后序遍历构造为例:

在后序遍历序列中,最后一个结点一定是二叉树的根结点;而在中序遍历中,根结点必然将中序序列分割成两个子序列,前一个子序列是根结点的左子树的中序序列,后一个子序列是根结点的右子树的中序序列。根据这两个子序列,在后序序列中找到对应的左子序列和右子序列。在后序序列中,左子序列的最后一个结点是左子树的根结点,右子序列的最后一个结点是右子树的根结点。如此递归下去,便能唯一地确定这棵二叉树。

void Tree::inPostBuild(const std::vector<int> &in_order, const std::vector<int> &post_order){
    this->tree_nodes.emplace_back(nullptr);
    auto inner = [this](const auto &inner, const std::vector<int> &in_order, const std::vector<int> &post_order) -> TreeNode*{
        if(post_order.size() == 0)
            return nullptr;
        int value_root = post_order[post_order.size() - 1];
        alice::TreeNode *node = new alice::TreeNode(value_root);
        this->tree_nodes.emplace_back(node);
        if(post_order.size() == 1)
            return node;
    
        int mid_index = 0;
        for(; mid_index < in_order.size(); ++mid_index){
            if(in_order[mid_index] == value_root)
                break;
        }

        std::vector<int> in_left(in_order.begin(), in_order.begin() + mid_index);
        std::vector<int> in_right(in_order.begin() + mid_index + 1, in_order.end());
        std::vector<int> post_left(post_order.begin(), post_order.begin() + in_left.size());
        std::vector<int> post_right(post_order.begin() + in_left.size(), post_order.end() - 1);

        node->lchild = inner(inner, in_left, post_left);
        node->rchild = inner(inner, in_right, post_right);
        return node;                                                        
    };  
    this->root = inner(inner, in_order, post_order);                        
    return;                                                                 
} 

1.2 二叉排序树

二叉排序树(又称二叉搜索树)或者是一颗空树,或者是具有下列特性地二叉树: 1、若左子树非空,则左子树上所有结点的值均小于根结点的值 2、若右子树非空,则右子树上所有结点的值均大于根结点的值 3、左、右子树也分别是一棵二叉排序树

根据二叉排序树的定义,左子树结点值 < 根结点值 < 右子树结点值,所以对二叉排序树进行中序遍历,可以得到一个递增的有序序列

给定二叉搜索树(BST)的根结点和一个值。 你需要在BST中找到结点值等于给定值的节点。 返回以该结点为根的子树。 如果结点不存在,则返回 nullptr

非递归算法

void show(const alice::TreeNode *root){
    auto inner = [](const auto &inner, const alice::TreeNode *root, int depth) -> void{
        if(! root){
            printf("%s null\n", std::string(depth, '-').c_str());
            return;
        }
        printf("%s %d\n", std::string(depth, '-').c_str(), root->data);
        inner(inner, root->lchild, 1 + depth);
        inner(inner, root->rchild, 1 + depth);
    };
    inner(inner, root, 1);
    return;
}

const alice::TreeNode *searchBST(const alice::TreeNode *root, int target_value){
    if(! root)
        return nullptr;
    const alice::TreeNode *node = root;
    while(node && node->data != target_value){
        if(node->data > target_value)
            node = node->lchild;
        else
            node = node->rchild;
    }
    return node;
}

递归算法

const alice::TreeNode *searchBST(const alice::TreeNode *root, int target_value){
    if(! root)
        return nullptr;
    if(root->data == target_value)
        return root;
    if(root->data > target_value)
        return searchBST(root->lchild, target_value);
    else
        return searchBST(root->rchild, target_value);
}

1.3 判断二叉排序树

递归算法,采用中序遍历

bool isBST(const alice::TreeNode *root){                                                                                                                
    const alice::TreeNode *pre = nullptr;                                                                                                               
    auto inner = [&pre](const auto &inner, const alice::TreeNode *root) -> bool{                                                                        
        if(! root)                                                                                                                                      
            return true;                                                                                                                                
        bool is_left = inner(inner, root->lchild);
        if(pre && pre->data >= root->data)
            return false;
        pre = root;
        bool is_right = inner(inner, root->rchild);
        return is_left && is_right;
    };
    return inner(inner, root);
}

非递归算法,采用中序遍历

bool isBST(const alice::TreeNode *root){                                                                                                                
    if(! root)                                                                                                                                          
        return true;                                                                                                                                    
    std::stack<const alice::TreeNode *> stack;                                                                                                          
    const alice::TreeNode *pre_node = nullptr;                                                                                                          
    const alice::TreeNode *cur_node = root;
    while(cur_node || ! stack.empty()){
        if(cur_node){
            stack.push(cur_node);
            cur_node = cur_node->lchild;
        }
        else{
            cur_node = stack.top();
            stack.pop();
            if(pre_node && pre_node->data >= cur_node->data)
                return false;
            pre_node = cur_node;
            cur_node = cur_node->rchild;
        }
    }
    return true;
}

1.4 二叉树中序序列的最小绝对值差

递归算法,采用中序遍历

int minDifBST(const alice::TreeNode *root){                                                                                                             
    int result = INT_MAX;
    const alice::TreeNode *pre_node;
    auto inner = [&result, &pre_node](const auto &inner, const alice::TreeNode *root) -> void{
        if(! root)
            return;
        inner(inner, root->lchild);
        if(pre_node)
            result = std::min(result, root->data - pre_node->data);
        pre_node = root;
        inner(inner, root->rchild);
    };
    inner(inner, root);
    return result;
}

作业

实现二叉树中序序列的最小绝对值差的非递归算法