二叉查找树(C++刷题笔记)

二叉查找树(C++刷题笔记)

二叉查找树

  • 若左子树不空,左子树所有节点的值均小于或等于它根节点的值;

  • 若右子树不空,右子树所有节点的值均大于或等于它根节点的值;

  • 左右子树也是二叉查找树

  • 等于的情况只能出现在左子树或右子树中的某一侧

struct TreeNode{
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x):
    val(x),left(NULL),right(NULL){}
};

插入节点

将某个节点a插入以b为根的BST中:

  • a.val<b.val :

    如果b有左子树,则递归的将该节点插入至左子树为根的BST中

    否则,将b.left赋值为该节点地址

  • a.val>=b.val:

    如果b有右子树,递归将该节点插入右子树为根的BST中

    否则,将b.right赋值为该节点地址

void BST_insert(TreeNode *root, TreeNode *node) {
    if (node->val < root->val) {
        if (root->left != NULL) {
            BST_insert(root->left, node);
        } else {
            root->left = node;
        }
    } else {
        if (root->right) {
            BST_insert(root->right, node);
        } else {
            root->right = node;
        }
    }

}

测试

void preorder(TreeNode *node,int layer){
    if(!node){
        return;
    }
    for (int i=0;i<layer;i++){
        cout<<">";
    }
    cout<<node->val;
    preorder(node->left,layer+1);
    cout<<"\n";
    preorder(node->right,layer+1);

}


int main() {
    TreeNode root(8);
    vector<TreeNode *>vec;
    int ls[]={3,1,6,4,7,10,14,13};
    for (int i = 0; i <8 ; ++i) {
        vec.push_back(new TreeNode(ls[i]));
    }
    for (int i = 0; i <vec.size(); ++i) {
        BST_insert(&root,vec[i]);
    }
    preorder(&root,0);

    return 0;

}
8>3>>1   

>>6>>>4  

>>>7     

>10      
>>14>>>13

查找数值

查找数值val是否在二叉树中出现

  • val==当前节点node节点值:返回真

  • val<当前节点node节点值:

    如果node有左子树,继续在左子树中查找该值;否则返回假

  • val>当前节点node节点值:

    如果node有右子树,继续在右子树中查找该值;否则返回假

bool BST_search(TreeNode *node, int val) {
    if (node->val == val) {
        return true;
    }
    if (val < node->val) {
        if (node->left) {
            return BST_search(node->left, val);
        } else {
            return false;
        }
    } else {
        if (node->right) {
            return BST_search(node->right, val);
        } else {
            return false;
        }
    }
}

449. 序列化和反序列化二叉搜索树

力扣

编码:

  • 将二叉树先序遍历,遍历将整型数据转为字符串并拼接,链接时使用符号分割

解码:

  • 将字符串按照编码时的分隔符,将各个数字拆分出来,将第一个数字变成构建二叉树的根节点,后面数字根据解析顺序插入根节点中去,返回根节点
void int2str(int val,string &str){
    string tmp;
    while (val){
        tmp+=val%10+'0';
        val=val/10;
    }
    for (int i = tmp.length()-1; i >=0 ; --i) {
        str+=tmp[i];
        str+='#';
    }
}

void BST_preorder(TreeNode *node,string &data){
    if(!node){
        return;
    }
    string str;
    int2str(node->val,str);
    data+=str;
    BST_preorder(node->left,data);
    BST_preorder(node->right,data);

}

题目代码

class Codec {

public:
    void int2str(int val, string &str) {
        string tmp;
        while (val) {
            tmp += val % 10 + '0';
            val = val / 10;
        }
        for (int i = tmp.length() - 1; i >= 0; --i) {
            str += tmp[i];

        }
        str += '#';

    }

    void BST_insert(TreeNode *root, TreeNode *node) {
        if (node->val < root->val) {
            if (root->left != NULL) {
                BST_insert(root->left, node);
            } else {
                root->left = node;
            }
        } else {
            if (root->right) {
                BST_insert(root->right, node);
            } else {
                root->right = node;
            }
        }

    }

    // Encodes a tree to a single string.
    string serialize(TreeNode *root) {
        string data;
        BST_preorder(root, data);
        return data;


    }

    // Decodes your encoded data to tree.
    TreeNode *deserialize(string data) {
        if (data.length() == 0) {
            return NULL;
        }
        vector<TreeNode *> vec;
        int val = 0;
        for (int i = 0; i < data.length(); ++i) {
            if (data[i] == '#') {
                vec.push_back(new TreeNode(val));
                val = 0;
            } else {
                val = val * 10 + data[i] - '0';
            }
        }
        for (int i = 1; i < vec.size(); ++i) {
            BST_insert(vec[0], vec[i]);
        }
        return vec[0];

    }

    void BST_preorder(TreeNode *node, string &data) {
        if (!node) {
            return;
        }
        string str;
        int2str(node->val, str);
        data += str;
        BST_preorder(node->left, data);
        BST_preorder(node->right, data);

    }
};

315. 计算右侧小于当前元素的个数

力扣

记录左子树数量的二叉树

struct node{
    int val;
    int cnt;
    node *left;
    node *right;
    node(int x):val(x),left(NULL),right(NULL),cnt(0){}
};
  • 按照数组逆置后的顺序插入二叉查找树, 插入时,计算已有多少个元素比当前插入元素小

  • 设置lower=0,记录插入过程中,有多少个元素比插入节点值小

  • 若待插入节点值小于等于当前node值,node.cnt++,递归将该节点插入到当前节点左子树;

  • 若待插入节点大于当前node值,lower+=node.cnt++,递归将该节点插入右子树

void insert(node *nd, node *insert_nd, int &lower) {
    if (insert_nd->val <= nd->val) {
        nd->cnt++;
        if (nd->left) {
            insert(nd->left, insert_nd, lower);
        } else {
            nd->left = insert_nd;
        }
    } else {
        lower += nd->cnt + 1;
        if (nd->right) {
            insert(nd->right, insert_nd, lower);
        } else {
            nd->right = insert_nd;
        }

    }


}

题目代码

class Solution {

public:
    struct node {
        int val;
        int cnt;
        node *left;
        node *right;

        node(int x) : val(x), left(NULL), right(NULL), cnt(0) {}
    };

    void insert(node *nd, node *insert_nd, int &lower) {
        if (insert_nd->val <= nd->val) {
            nd->cnt++;
            if (nd->left) {
                insert(nd->left, insert_nd, lower);
            } else {
                nd->left = insert_nd;
            }
        } else {
            lower += nd->cnt + 1;
            if (nd->right) {
                insert(nd->right, insert_nd, lower);
            } else {
                nd->right = insert_nd;
            }

        }


    }

    vector<int> countSmaller(vector<int> &nums) {
        vector<int> res;//结果数组
        vector<node *> vec;//存储二叉树节点
        vector<int> cnt;//从后先前插入,比当前节点值小的
        for (int i = nums.size() - 1; i >= 0; --i) {
            vec.push_back(new node(nums[i]));//从后先前插入节点
        }
        cnt.push_back(0);//第一节点比它小的为0
        for (int i = 1; i < vec.size(); ++i) {
            int lower = 0;
            insert(vec[0], vec[i], lower);
            cnt.push_back(lower);//把比它小的个数插入进去
        }
        for (int i = vec.size() - 1; i >= 0; --i) {
            res.push_back(cnt[i]);
        }
        return res;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值