数据结构:二叉搜索树

bst

二叉搜索树(Binary Search Tree)可以用来解决数据的查找问题.

链表,队列等线性数据结构可以存储数据 但在数据的查找,排序方面效率不高
二叉搜索树则兼具了数据的存储和查找,能用来解决涉及数据查找的问题

二叉树的原理和实现:
http://blog.csdn.net/qq_21358401/article/details/79329523

二叉搜索树

和之前描述过的二叉树一样:二叉搜索树的左节点的键值小于根节点的键值 
                               右节点的键值大于根节点的键值

二叉搜索树应该具有这几个特性: 1. 插入节点
                         2. 搜索/删除节点
上一文中描述的二叉树原型已经比较接近二叉搜索树 仅缺少搜索/删除节点的能力.

二叉搜索树的节点:
增加parent节点指向节点的根节点 这是为了删除节点时更改节点的连接关系准备的.
struct tree {
    struct tree *parent;
    struct tree *left;
    struct tree *right;
    int index;
};

插入节点:
和普通二叉树类似 大于根节点键值则向右插入 小于根节点键值则向左插入
static inline void sort_tree_insert(struct tree **node, 
                                    struct tree *parent, int val) {
    if (!(*node)) {
        *node = malloc(sizeof(struct tree));
        assert((*node) != NULL);

        (*node)->parent = parent; // 根节点和子节点建立连接
        (*node)->left = NULL;
        (*node)->right = NULL;
        (*node)->index = val;

        return;
    }

    if (val < (*node)->index) {
        sort_tree_insert(&((*node)->left), (*node), val); // 向左插入
    } else {
        sort_tree_insert(&((*node)->right), (*node), val); // 向右插入
    }

    return;
}

搜索节点:
返回节点的指针
static inline struct tree* sort_tree_search(struct tree *root, int val) {
    if (!root) {
        return NULL;
    }

    if (root->index == val) {
        return root;
    }

    if (val < root->index) {
        return sort_tree_search(root->left, val);
    } else if (val >= root->index){
        return sort_tree_search(root->right, val);
    }
}

删除节点

删除节点要考虑多种情况 所以比较复杂 单独列举出来
有这么几种情况:
1. 删除根节点
2. 删除普通节点

删除根节点其实和删除普通节点要考虑的情况一样 
但因为删除根节点需要替换根节点 而不是简单的更改连接关系 所以要区别开来处理
删除根节点
1. 根节点没有左右节点
   直接返回根节点 

2. 根节点只存在左节点
   让左节点成为根节点 返回原先的根节点

3. 根节点只存在右节点
   让右节点成为根节点 返回原先的根节点

4. 根节点存在左右节点
   bst的特性是左节点键值 < 根节点 < 有节点
   如果要删除根节点 就要从剩下的节点中选出一个 调整到根节点的位置上来
   可以明确的是:一定从左边的节点(包含可能存在的子节点)选取这个调整节点
   因为只有这样 才能保持bst的特性

   所以左边的节点中的键值最大的节点是寻找的目标
   1. 左节点没有右节点
       2        像这样 2是根节点 1就是左节点 因为1没有右节点 所以1是左边的节点中最大的
      /  \      将2删除 1翻转到2的位置就形成了新的二叉树
     1    4              1
    /                   / \
   0                   0   4
   2. 左节点存在有节点
        3     3是根节点 1就是左节点 1存在右节点 左边节点中最大的明显是2节点      
      /  \    将3删除 2翻转到3的位置 
     1    4        2
    / \           / \
   0   2         1   4
                / 
               0 
可以看出 这样操作删除后 bst的特性没有被破坏

关于寻找左边子树的最大键值
1.  如果左节点没有右子节点 直接返回左节点
2. 左节点存在右子节点 则递归向右寻找 知道找到叶子节点(根据bst的特性 一定是最大值)
static inline struct tree* sort_tree_find_max_right(struct tree *node) {
    if (!node->right)
        return node;

    sort_tree_find_max_right(node->right);
}
删除普通节点
删除普通节点也要考虑四种情况:
1. 节点没有左右子节点
   直接返回这个节点

2. 节点有左节点
   把左节点连接到要删除节点的父节点上替代自己的位置

3. 节点有右节点
   把右节点连接到要删除节点的父节点上替代自己的位置

4. 节点有左右子节点
   和删除根节点时考虑的情况一样 寻找左边方向的最大键值调整替换要删除的节点

参考blog

http://blog.csdn.net/feixiaoxing/article/details/6867460

示例代码

git repo:
https://github.com/sliver-chen/codingutil/tree/master/data_struct/bst
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值