二叉搜索树的简单操作与实现

二叉搜索树(BinarySearchTree)性质

  二叉搜索树首先是一棵二叉树,二叉树可能为空,而一颗非空的二叉搜索树要满足以下条件:

  (1)每个元素有一个关键字,所有关键字是唯一的。(关键字不唯一的二叉搜索树叫有重复值的二叉搜索树

  (2)在根节点的左子数的元素都小于根节点的关键字。

  (3)在根节点的右子数的元素都大于根节点的关键字。

  (4)根节点的左右子树也是一棵二叉搜索树

二叉搜索树的结构

c++代码:

template <class K,class V>
struct BSTnode     //二叉搜索树节点结构
{
	BSTnode *leftChild;     //左子树
	BSTnode *rightChild;    //右子树
	K key;
	V value;

	//构造方法
	BSTnode(const K& theKey,const V& theValue)
		:leftChild(NULL),rightChild(NULL),key(theKey),value(theValue)
	{}
};

template <class K,class V>
class MyBSTree
{
private:
	BSTnode<K, V> rootNode;     //根节点
public:
	BSTnode<K, V>* Find(const K& theKey);          //查找
	bool Insert(const K& theKey, const V& theValue);   //插入
	bool Erase(const K& theKey);                 //删除
	void InOrder();                          //中序遍历
};


二叉搜索树的查找

查找的递归实现(c++):

//查找的递归实现
template <class K,class V>
BSTnode<K, V>* MyBSTree<K, V>::Find(BSTnode<K,V>* root,const K& theKey)
{
	if (root == NULL)
	{
		return NULL;
	}
	if (root->key > theKey)
	{
		return Find(root->leftChild, theKey);
	}
	else if (root->key < theKey)
	{
		return Find(root->rightChild, theKey);
	}
	else
	{
		return root;
	}
}

查找的迭代实现(c++):

template <class K,class V>
BSTnode<K, V>* MyBSTree<K, V>::Find(const K& theKey)
{
	BSTnode<K, V>* currentNode = rootNode;
	while (currentNode != NULL)
	{
		if (currentNode->key > theKey)
		{
			currentNode = currentNode->rightChild;
		}
		else if (currentNode->key < theKey)
		{
			currentNode = currentNode->leftChild;
		}
		else
		{
			return currentNode;
		}
	}
	return  NULL;
}
二叉搜索树的插入

二叉搜索树的插入步骤:

首先查找二叉搜索树是否有节点的关键字和要插入的相同,有的话则不插入;

如果没有与要插入的节点的关键字相同的节点,则将该节点作为搜索中断的节点的孩子插入二叉搜索树。

插入的递归实现

template <class K,class V>
bool MyBSTree<K,V>::Insert(BSTnode<K,V>*& root ,const K& theKey, const V& theValue)
{
	if (root == NULL)
	{
		rootNode = new BSTnode(theKey, theValue);
		return true;
	}
	if (root->key >theKey)
	{
		return Insert(root->leftChild,theKey,theValue);
	}
	else if (root->key < theKey)
	{
		return Insert(root->rightChild,theKey,theValue);
	}
	else
	{
		return false;
	}
}

插入的迭代实现

//插入的迭代实现
template <class K, class V>
bool MyBSTree<K, V>::Insert(const K& theKey, const V& theValue)
{
	if (rootNode == NULL)         //插入空树
	{
		rootNode = new BSTnode(theKey, theValue);
		return;
	}
	BSTnode<K, V>* currentNode = rootNode;
	BSTnode<K, V>* parentNode = NULL;
	while (currentNode != NULL)   //寻找插入位置
	{
		if (currentNode->key > theKey)
		{
			parentNode = currentNode;
			currentNode = currentNode->leftChild;
		}
		else if (currentNode->key < theKey)
		{
			parentNode = currentNode;
			currentNode = currentNode->rightChild;
		}
		else
		{
			return false;
		}			
	}
	//找到插入位置后,判断是左节点还是右节点,建立新的节点并与parentNode进行连接
	if (parentNode->key >theKey)
	{
		parentNode->leftChild = new BSTnode(theKey, theValue);
	}
	else if (parentNode->key < theKey)
	{
		parentNode->rightChild = new BSTnode(theKey, theValue);
	}
	return true;
}

二叉搜索树的删除

二叉搜索树删除的步骤:

要考虑三种情况:(1)p是叶子节点(2)p只有只有一棵非空子树(3)p有两棵非空子树

当p为叶子节点,只需要把p的父节点对应子树置为NULL,如果p为根节点,则令根节点为NULL。

当p有一棵非空子树,子树继承p的位置。

当p有两棵非空子树,找到p的最近前驱,来替代p的位置,并将前驱删去,用前驱的子树替代前驱位置。

删除的递归实现:

//删除递归实现
template <class K, class V>
bool MyBSTree<K, V>::Erase(BSTnode<K,V>*& root,const K& theKey)
{
	if (root == NULL)       //空树
	{
		return false;
	}
	if (root->leftChild == NULL&&root->rightChild == NULL)     //只有根节点
	{
		if (root->key == theKey)          //要删除的是根节点
		{
			delete root;
			root = NULL;
			return true;
		}
		else
		{
			return false;
		}
	}
	if (root->key > theKey)
	{
		Erase(root->leftChild, theKey);
	}
	else if (root -> key < theKey)
	{
		Erase(root->rightChild, theKey);
	}
	else      //找到要删除的节点
	{
		BSTnode<K, V>* tempNode = NULL;   //临时节点
		if (root->leftChild == NULL)   //没有左子树
		{
			tempNode = root;
			root = root->rightChild;          //右子树继承自身位置
			delete tempNode;
			return true;
		}
		else if (root ->rightChild == NULL)  //没有右子树
		{
			tempNode = root;
			root = root->leftChild;      //左子树替代自身位置
			delete tempNode;
			return true;
		}
		else   //既有左子树也有右子树
		{
			//找到最近前驱
			BSTnode<K, V>* closestNode = root->leftChild;
			while (closestNode->rightChild)   //根节点左子树的右子树为最近前驱
			{
				tempNode = closestNode;
				closestNode = closestNode->rightChild;
			}
			//前驱替换要删除的节点
			swap(root->key, closestNode->key);
			swap(root->value, closestNode->value);

			Erase(root->leftChild);
		}
	}
}


删除的迭代实现:

//删除迭代实现
template <class K, class V>
bool MyBSTree<K, V>::Erase(const K& theKey)
{
	if (rootNode == NULL) //空树
	{
		return false;
	}
	if (rootNode->leftChild ==NULL&& rootNode->rightChild ==NULL) //只有根节点
	{
		if (rootNode.key == theKey)
		{
			rootNode = NULL;
			delete rootNode;
			return true;
		}
		return false;
	}
	BSTnode<K, V>* parentNode = NULL;
	BSTnode<K, V>* currentNode = rootNode;
	while (currentNode != NULL)
	{   //寻找要删除的节点
		if (currentNode->key>theKey)
		{
			parentNode = currentNode;
			currentNode = currentNode->leftChild;
		}
		else if (currentNode->key<theKey)
		{
			parentNode = currentNode;
			currentNode = currentNode->rightChild;
		}
		else
		{    //找到要删除的节点
			if (currentNode->leftChild == NULL)   //没有左子树
			{
				if (parentNode == NULL)  //要删除的为根节点
				{
					rootNode = currentNode.rightChild;
					delete currentNode;
					currentNode = NULL;
					return true;
				}
				if (parentNode->key>currentNode->key)
				{
					parentNode->leftChild = currentNode->rightChild;
					delete currentNode;
					currentNode = NULL;
					return true;
				}
				else if (parent->key<currentNode->key)
				{
					parentNode->rightChild = currentNode->rightChild;
					delete currentNode;
					currentNode = NULL;
					return true;
				}
			}
			else if (currentNode->rightChild == NULL)  //没有右子树,同没右左子树
			{
				if (parentNode == NULL)  //要删除的为根节点
				{
					rootNode = currentNode.leftChild;
					delete currentNode;
					currentNode = NULL;
					return true;
				}
				if (parentNode->key>currentNode->key)
				{
					parentNode->leftChild = currentNode->leftChild;
					delete currentNode;
					currentNode = NULL;
					return true;
				}
				else if (parent->key<currentNode->key)
				{
					parentNode->rightChild = currentNode->leftChild;
					delete currentNode;
					currentNode = NULL;
					return true;
				}
			}
			else    //既有左子树也有右子树
			{
				BSTnode<K, V>* tempNode = currentNode;
				BSTnode<K, V>* closestNode = currentNode->leftChild;
				while (closestNode->rightChild)
				{
					tempNode = closestNode;
					closestNode = closestNode->rightChild;  //closestNode指向最近前驱节点,tempNode指向其父节点
				}
				currentNode->key = closestNode->key;
				currentNode->value = closestNode->value;
				if (tempNode != currentNode)
					tempNode->rightChild = closestNode->leftChild;
				else
				{
					tempNode->leftChild = closestNode->leftChild;
				}
				delete tempNode;
			}
			return true;
		}
	}
}


二叉搜索树的遍历

根据二叉搜索树的性质,所以二叉树的中序遍历可以得到有序表。

中序遍历的实现(c++)

//中序遍历
template <class K,class V>
void MyBSTree<K, V>::InOrder()
{
	if (rootNode == NULL)
	{
		return;
	}
	InOrder(rootNode->leftChild);
	cout << rootNode->key<<" ";
	InOrder(rootNode->rightChild);
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值