二叉搜索树的插入和删除

二叉搜索树BST(工程上几乎不用,后续理论学习的基础)(没有平衡因子的约束)

  • 概念
    • 节点中存储的数据,左小右大
    • 按中序遍历就可以得到有序序列
    • 结构(如下):树头 + 具体节点树

在这里插入图片描述

插入操作

static BSNode *createBSNode(Element e){
    BSNode *node = malloc(sizeof(BSNode));
    if(node==NULL){
        return NULL;
    }
    node->data=e;
    node->left=node->right=NULL;
    return node;
}

static BSNode *insertBSNode(BSNode *node,Element e){
    if(!node){
        return createBSNode(e);
    }
    if(e < node->data){
        node->left=insertBSNode(node-left,e);
    }else if(e > node->data){
        node-right=insertBSNode(node-right,e);
    }
    return node;		// 已经有了data值为e的节点不用再进行插入
}

void BSNode *insertBSTree(BSTree *tree,Element e){
    tree->root=insertBSNode(tree->root,e);
}

删除操作

逻辑完备性:再删除完后BST树的性质不能变

  1. 度为0的点:直接删除

  2. 度为1的点:把度为1的子节点进行替换:比如要删除图中的22节点,则只需要把33->left指向8即可。直接进行替换

度为0和度为1的代码可以归纳成一个:即先判断该节点的left是否为空,若为空,则一定为度为0或度为1的节点,直接将该节点替换为该结点指向的right即可(若度为0,则right==NULL,直接替换相当于删除;若度为1,则将right以及后面所带的子串替换上来即可)

  1. 度为2的点:转移矛盾,把度为2的节点转化为中序遍历中该节点的前驱或者后继节点。前驱或后继节点非0即1。
  • 找前驱节点的极右值(比当前度为2的节点小的最大值)

  • 找后继节点的极左值(比当前度为2的节点大的最小值)

  • 当一个度为2的节点:

    • 前驱:左边节点的最大值
    • 后继:右边节点的最小值
// 找前驱节点的极左值
static BSNode *maxValueBSNode(BSNode *node) {
	while (node && node->right) {
		node = node->right;
	}
	return node;
}

static BSNode* deleteBSNode(BSTree* tree, BSNode *node, Element e) {
	if (node == NULL) {
		return NULL;
	}
	if (e < node->data) {
		node->left = deleteBSNode(tree, node->left, e);
	} else if (e > node->data) {
		node->right = deleteBSNode(tree, node->right, e);
	} else {
		BSNode *tmp;
		if (node->left == NULL) {		// 度为1或0
			tmp = node->right;
			free(node);
			tree->count--;
			return tmp;
		}
		if (node->right == NULL) {		// 度为1
			tmp = node->left;
			free(node);
			tree->count--;
			return tmp;
		}
		// 此时说明待删除的节点,度为2,替换当前节点的值(后继或前驱)
		// 找这个节点的左节点的最大值
        // 可以通过左边的最大值/右边的最小值进行删除
        // 左边最大值:替换原来度为2的节点node,并将node->中原来左边最大值的节点删除掉
        // 传入的就已经是前驱节点或者后继节点了
		tmp = maxValueBSNode(node->left);
		node->data = tmp->data;
		node->left = deleteBSNode(tree, node->left, node->data);
	}
	return node;
}
二叉搜索树: 二叉搜索树是一种特殊的二叉树,它的左子树中所有节点的值都小于它的根节点的值,而右子树中所有节点的值都大于它的根节点的值。二叉搜索树支持快速的插入、查找删除操作,时间复杂度为O(logn)。 插入删除: 插入操作是将一个新节点插入二叉搜索树中,找到对应的位置并插入即可。删除操作比插入操作复杂一些,需要考虑到删除节点后二叉搜索树的结构是否仍然满足二叉搜索树的性质。如果需要删除的节点是叶子节点,直接删除即可。如果需要删除的节点只有一个子节点,可以将其子节点上移,删除该节点。如果需要删除的节点有两个子节点,可以找到该节点右子树中最小的节点,将其值复制到需要删除的节点中,然后删除该最小节点。 树遍历: 树的遍历是指按照某种顺序依次访问树中的所有节点。常用的树遍历方式有前序遍历、中序遍历后序遍历。前序遍历是先访问根节点,然后访问左子树右子树;中序遍历是先访问左子树,然后访问根节点右子树;后序遍历是先访问左子树右子树,然后访问根节点。 AVL树: AVL树是一种自平衡二叉搜索树,它保证了树的任意节点的左右子树高度差不超过1。当插入删除节点时,AVL树会通过旋转操作来保持树的平衡。AVL树的查找、插入删除操作的时间复杂度均为O(logn)。 红黑树: 红黑树也是一种自平衡二叉搜索树,它的插入删除操作比AVL树更快,但查找操作稍慢一些。红黑树通过染色旋转操作来保持树的平衡,它要求树中任意一条从根到叶子的路径上,红色节点黑色节点的个数相同。红黑树的时间复杂度也为O(logn)。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值