二叉搜索树

搜索树

链表允许我们添加、删除、搜索元素,种种数据结构会在执行时申请必要的内存空间,便于管理动态集合。但是,在链表中搜索元素的算法复杂度为O(n)。相比之下,使用动态树结构能更加有效地添加、删除和搜索数据。

  • 搜索树是一种可以进行插入、搜索、删除等操作的数据结构,可以用作字典或优先级队列。二叉搜索树属于最基本的搜索树。

二叉搜索树

  • 顾名思义,二叉搜索树首先是二叉树,然后是搜索树。
  • 对于二叉搜索树,一般满足以下性质:

左子结点小于等于父结点,右子结点大于等于父结点。

在这里插入图片描述

  • 对于二叉搜索树来说,最为重要的就是如何插入,搜索和删除元素。

插入

  • 二叉搜索树的插入很简单,先与根结点相比,比根节点小,就放在左子树里面,比根结点大,就放入右子树。在每一个子树中不断执行这一过程,直到需要插入的结点成为叶结点。对于插入来说,设树高为h,则算法复杂度为O(h)。
//使用链表建立二叉搜索树
struct Node {
    int key;
    Node *parent, *left, *right;
};
//声明根和尾,所有空都指向尾
Node *root;

void insert(int k){
    Node *y = NULL;
    Node *x = root;
    Node *z;
	//动态开辟空间并初始化
    z = (Node*)malloc(sizeof(Node));
    z->key = k;
    z->left = NULL;
    z->right = NULL;
	
    while (x != NULL ){
    	//记录x的上一个并将x向下移动到底
        y = x;
        if (z->key < x->key){
            x = x->left;
        }
        else {
            x = x->right;
        }
    }
	//将z和y连接
    z->parent = y;
    if (y == NULL) {
        root = z;
    }
    else {
        if (z->key < y->key){
            y->left = z;
        }
        else {
            y->right = z;
        }
    }
}

搜索

  • 知道了如何插入,如何搜索也就很简单了。
  • 与结点相比,如果要查找的值比它小,则搜索左子树,反之,则搜索右子树,不断重复这个过程直到找出或者搜索到达树底端。
  • 同样,设树高为h,搜索的算法复杂度也为O(h)。
Node * find(Node *p, int x){
    while (u != NULL && u->key != x){
        if (x < u->key) u = u->left;
        else u = u -> right;
    }
    return u;
}

删除

  • 对于二叉搜索树来说,删除反而成了最为复杂的事情。
  • 删除将遵循以下几条规则:

1.需要删除的是叶结点,直接删除。
2.需要删除的结点只有一棵子树,将这颗子树的根结点与删除结点的父结点连接。
3.需要删除的结点有两棵子树,可选择左子树的最大值,也可选择右子树的最小值。

void delNode(Node *u){
	//如果要删除叶结点,直接删除
    if (u->left == NULL && u->right == NULL){
    	if (u->parent->left == u)
    		u->parent->left = NULL;
    	else
    		u->parent->right = NULL;
        free(u);
        return;
    }
    //如果只有一棵子树,连接到这棵子树
    else if (!u->left || !u->right){
        if (u->left){
        	if (u->parent->left == u){
				u->parent->left = u->left;
			}
			else{
				u->parent->right = u->left;
			}
        }
        else{
        	if (u->parent->left == u){
				u->parent->left = u->right;
			}
			else{
				u->parent->right = u->right;
			}
        }
        free(u);
        return;
    }
    //如果两棵子树都存在,则找出右子树的最小值,赋给此结点,然后递归删除最小值结点。
    else{
        Node *tmp = u->right;
        while(tmp->left)
            tmp = tmp->left;
        u->key = tmp->key;
        delNode(tmp);
        free(tmp);
        return;
    }
}

返回目录

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值