《数据结构》学习笔记 16

本文详细介绍了二叉搜索树的基本概念、插入与删除操作的实现细节,并探讨了优化思路,旨在帮助读者掌握二叉搜索树的核心知识。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

穿线二叉树直接忽略了。这几天看了些GMA那些大公司的面试题目,丢,什么都不会。。那些人确实有实力,任重道远啊。


1 二叉搜索树BST


上传一图,方便了解。


插入操作

template<class T>
void BinarySearchTree<T>::InsertNode(
	     BinaryTreeNode<T>* root ,
	     BinaryTreeNode<T>* newpointer)
{//向二叉搜索树插入新结点
	BinaryTreeNode<T>* pointer=NULL;
	if(root==NULL){
	//用指针newpointer初始化二叉搜索树树根,赋值实现
		Initialize(newpointer);
 		return;
	}
	else pointer=root;
while(1){
		if(newpointer->value()==pointer->value())
			return ;					
		//相等则不用插入
		else if(newpointer->value()<pointer->value())	{
		    if(pointer->leftchild()==NULL){
			pointer->left=newpointer;//作为左子树     只要弄清楚这里即可,由于new的关键码值小于pointer,就要进入左子树,所以判断左子树是否为空
			return;
		    }
		   else	pointer=pointer->leftchild();
	      }
else{
		//作为右子树
		if(pointer->rightchild()==NULL) {
			pointer->right=newpointer;
			return;
		}
		else	pointer=pointer->rightchild();
		}//end else
	}//end while
}

删除操作较复杂些,从二叉搜索树里删除一个结点时,不能把以这个结点为根的子树都删除掉,只能删除掉这一个结点,并且还要保持二叉搜索树原来的性质。这就意味着要进行完整的“脱链”和“挂钩”操作。

普通想法

设p,p1,r是指针变量,p↑表示s要删除的结点,p1↑表示p↑的父母结点,则删除可以按如下规定进行:
若结点p↑没有左子树,则用右子树的根代替被删除的结点p↑
若结点p↑有左子树,则在左子树里找按中序周游的最后一个结点r↑,将r↑的右指针置成指向p↑的右子树的根,然后用结点p↑的左子树的根去代替被删除的结点p↑

这样树的高度可能会增加许多,比如图中zom可能有很高的子树。

template<class T>
void BinarySearchTree<T>::DeleteNode(BinaryTreeNode<T>* pointer){		//二叉搜索树的删除
	BinaryTreeNode<T>* temppointer=NULL;	
	BinaryTreeNode<T>*parent=GetParent(root,pointer);
	//被删结点无左子树吗?
	if(pointer->leftchild() == NULL)
	{//被删除结点是根结点吗?
		if(parent == NULL)                                          //下面可以简化,temppointer=pointer->rightchild();
			root=pointer->rightchild();
		else if(parent->leftchild()==pointer)
	   		parent->left=pointer->rightchild();
		else
 		      	parent->right=pointer->rightchild();
                delete pointer;
		pointer=NULL;
		return;
	}

	else temppointer=pointer->leftchild();
	//在左子树中找对称序的最后一个结点
	while(temppointer->rightchild()!=NULL)
	temppointer=temppointer->rightchild();
	//被删除结点的右子树作为temppointer的右子树
	temppointer->right=pointer->rightchild();
	//被删除结点的左子树根代替被删除结点
		if(parent==NULL)
			root=pointer->leftchild();
		else if(parent->leftchild()==pointer)
			parent->left=pointer->leftchild();
		else 
			parent->right=pointer->leftchild();
		delete pointer;
		pointer=NULL;
		return;
}


改进想法:

若结点p↑没有左子树,则用右子树的根代替被删除的结点p↑(相同)
若结点p↑有左子树,则在左子树里找按中序周游的最后一个结点r↑,将r↑的右指针置成指向p↑的右子树的根,然后用结点r↑去代替被删除的结点p↑

这样树的高度可能维持不变或者减少。即保持性质之后要考虑性能。

template <class T>	void BinarySearchTree<T>::DeleteNodeEx
  (BinaryTreeNode<T>* pointer)
{//若待删除结点不存在,返回
	if( pointer == NULL )
		return;
	//保存替换结点
	BinaryTreeNode<T> * temppointer;
	//保存替换结点的父结点        该用的时候还是用上啊
	BinaryTreeNode<T> * tempparent = NULL;
	
//保存删除结点的父结点
	BinaryTreeNode<T> * parent = GetParent(root ,pointer );
//如果待删除结点的左子树为空,就将它的右子树代替它
	if( pointer->leftchild() == NULL )
	temppointer=pointer->rightchild();
else{
	//当待删除结点左子树不为空,就在左子树中寻找最大结点替换待删除结点
	temppointer = pointer->leftchild();
	while(temppointer->rightchild() != NULL )	
{
		tempparent = temppointer;
		temppointer = temppointer->rightchild();   //精妙啊
	}
	//删除替换结点
	if(tempparent==NULL)                                  //做边界检查
		pointer->left=temppointer->leftchild();       //就是删除结点的左孩子结点,这样连接就跳过一个temppointer结点     
	else    tempparent->right=temppointer->leftchild();
	temppointer->left=pointer->leftchild();                    //要挂好钩
	temppointer->right=pointer->rightchild();
}
//用替换结点去替代真正的删除结点
if(parent==NULL)
	root=temppointer;
	else if( parent->leftchild() == pointer )
	parent->left=temppointer;
	else parent->right=temppointer;

	delete pointer;
	pointer=NULL;
	return;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值