二分搜索树的寻找、插入与删除

二分搜索树的寻找、插入与删除

节点定义

struct TNode { /* 树结点定义 */
	ElementType Data; /* 结点数据 */
	TNode*  Left;     /* 指向左子树 */
	TNode*  Right;    /* 指向右子树 */
};

寻找

  1. 将key值与当前节点比较,若key较小则前往左子树寻找;否则前往右子树寻找(重复此步骤)
  2. 当key值与当前节点相等时,返回当前节点地址

find

// 返回目标节点地址,实际上传入的也是一个节点的地址
TNode* find(ElementType key, TNode* root) {
	if (!root)
		return NULL;

	while (root) {
		if (key == root->Data)
			return root;
		else if (key < root->Data)
			root = root->Left;
		else
			root = root->Right;
	}
	return NULL;
}

findMax

TNode*  findMax(TNode*  root) {
	if (!root)
		return NULL;

	while (root){
		root = root->Right;
	}
	return root;
}

findMin

TNode*  findMin(TNode*  root) {
	if (!root)
		return NULL;

	while (root) {
		root = root->Left;
	}
	return root;
}

插入

  1. 将key值与当前节点比较,若key较小则前往左子树寻找插入位置;否则前往右子树寻找插入位置(重复此步骤)
  2. 直到当前节点为空,插入即可

应当注意的是,这里如果采用递归实现插入函数,我们最好将函数的宏观语义定义为对以root为根的树插入新节点,并返回root的地址

// 递归形式
// 返回新的根节点地址(递归形式的插入需要这样处理)
TNode*  insert(ElementType key, TNode*  root) {
	if (!root) {
		root = (TNode*)malloc(sizeof(struct TNode));
		root->Data = key;
		root->Left = NULL;
		root->Right = NULL;
		return root;
	}

	if (key > root->Data)
		root->Right =  insert(key, root->Right);
	else if (key < root->Data)
		root->Left =  insert(key, root->Left);

	return root;
}

删除

对于删除,本文对待删除节点的情况作出如下讨论:

  1. 待删除节点不存在
  2. 待删除节点是叶子节点
  3. 待删除节点有一个子节点
  4. 待删除节点有左右子树

当待删除节点是叶子节点时,应当将其父亲节点指向其的指针改为NULL;当待删除节点只有一个子节点时,应当将其父亲节点指向其的指针改为其子节点;

此外,当出现待删除节点有左右子树,应当进行如下操作:

  1. 寻找待删除节点右子树的最小节点min
  2. 将待删除节点更新为min
  3. 删除右子树中的最小节点min即可

应当注意的是,这里如果采用递归实现删除函数,我们最好将函数的宏观语义定义为对以root为根的树删除节点,并返回root的地址。

// 递归形式
// 返回新的根节点地址
TNode* Delete(ElementType key, TNode* root) {
	if (!root)
		return NULL;

	if (key > root->Data) {
		root->Right = Delete(key, root->Right);
		return root;
	}
	else if (key < root->Data) {
		root->Left = Delete(key, root->Left);
		return root;
	}else{
		// 待删除节点只有一个非空子节点或无子节点时
		if (root->Left == NULL)
			return root->Right;

		if (root->Right == NULL)
			return root->Left;
		// 待删除节点有两个非空子节点时
		root->Data = findMin(root->Right)->Data;
		root->Right = Delete(root->Data, root->Right);
		return root;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值