二叉搜索树(CPP实现简单易懂)

二叉搜索树

 

目录

一、插入

二、查询

三、删除

 

一、插入

思路

其实就是查找的过程,一直找到空指针,就把空指针赋值为要插入的数据并返回true,如果查到了相等的元素,就返回false

 

代码实现

#include <iostream>
using namespace std;
template <class K, class V>
struct BSTreeNode
{
	BSTreeNode(const K& k, const V& v) : lchild(NULL), rchild(NULL), key(k), value(v) {}
	BSTreeNode* lchild;
	BSTreeNode* rchild;
	K key;
	V value;
}; 

template <class K, class V>
class BST
{
	typedef BSTreeNode<K, V> Node;
public:
	BST() :m_Root(NULL) {}

	bool Insert(const K& k, const V& v)
	{
		return Insert_(this->m_Root, k, v);
	}

	bool Insert_(Node*& root, const K& k, const V& v)
	{
		if (!root)
		{
			root = new Node(k, v);
			return true;
		}

		else
		{
			if (root->key > k)
			{
				return Insert_(root->lchild, k, v);
			}

			else if (root->key < k)
			{
				return Insert_(root->rchild, k, v);
			}

			else
			{
				return false;
			}
		}
	}

	//释放在堆区开辟的内存空间
	void clear()
	{
		clear_(this->m_Root);
	}

	void clear_(Node* root)
	{
		//基线条件,当根结点为空使说明当前结点清除完毕,返回
		if (!root)
		{
			return;
		}
		else
		{
			//先清除左子树
			clear_(root->lchild);
			//再清除右子树
			clear_(root->rchild);
			//最后清除根结点
			delete root;
		}
			
	}
private:
	Node* m_Root;
};

int main()
{
	BST<int,int> BSTree;
	if (BSTree.Insert(5, 1))
	{
		cout << "插入成功" << endl;
	}
	else
	{
		cout << "插入失败" << endl;
	}

	if (BSTree.Insert(5, 2))
	{
		cout << "插入成功" << endl;
	}
	else
	{
		cout << "插入失败" << endl;
	}
	
	BSTree.clear();//释放在堆区开辟的内存空间
	system("pause");
	return 0;
}

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ztw1OcbX-1666424817318)(C:\Users\Zhang\AppData\Roaming\Typora\typora-user-images\image-20221022100926353.png)]

返回目录

 

二、查询

思路

先判断根结点是否为空,如果为空就返回NULL,如果根结点大于目标结点,递归调用根结点的左子树为根结点;如果根结点小于目标结点, 递归调用根结点的右子树为根结点;如果根结点等于目标结点,返回该结点

 

代码实现

#include <iostream>
using namespace std;
template <class K, class V>
struct BSTreeNode
{
	BSTreeNode(const K& k, const V& v) : lchild(NULL), rchild(NULL), key(k), value(v) {}
	BSTreeNode* lchild;
	BSTreeNode* rchild;
	K key;
	V value;
};

template <class K, class V>
class BST
{
	typedef BSTreeNode<K, V> Node;
public:
	BST() :m_Root(NULL) {}

	bool Insert(const K& k, const V& v)
	{
		return Insert_(this->m_Root, k, v);
	}

	bool Insert_(Node*& root, const K& k, const V& v)
	{
		if (!root)
		{
			root = new Node(k, v);
			return true;
		}

		else
		{
			if (root->key > k)
			{
				return Insert_(root->lchild, k, v);
			}

			else if (root->key < k)
			{
				return Insert_(root->rchild, k, v);
			}

			else
			{
				return false;
			}
		}
	}

	Node* Find(const K& k)
	{
		return Find_(this->m_Root, k);
	}

	Node* Find_(Node* root, const K& k)
	{
		if (!root)
		{
			return NULL;
		}
		else
		{
			if (root->key > k)
			{
				return Find_(root->lchild, k);
			}
			else if (root->key < k)
			{
				return Find_(root->rchild, k);
			}
			else
			{
				return root;
			}
		}
	}

	//释放在堆区开辟的内存空间
	void clear()
	{
		clear_(this->m_Root);
	}

	void clear_(Node* root)
	{
		//基线条件,当根结点为空使说明当前结点清除完毕,返回
		if (!root)
		{
			return;
		}
		else
		{
			//先清除左子树
			clear_(root->lchild);
			//再清除右子树
			clear_(root->rchild);
			//最后清除根结点
			delete root;
		}

	}
private:
	Node* m_Root;
};

int main()
{
	BST<int, int> BSTree;
	BSTree.Insert(5, 1);
	BSTree.Insert(6, 2);
	BSTreeNode<int, int>* ret = BSTree.Find(6);
	if (!ret)
	{
		cout << "未查到" << endl;
	}
	else
	{
		cout << "查找到的元素value:" << ret->value << endl;
	}
    BSTree.clear();
	system("pause");
	return 0;
}

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zv6MYpUQ-1666424817319)(C:\Users\Zhang\AppData\Roaming\Typora\typora-user-images\image-20221022104009071.png)]

返回目录

 

三、删除

思路

情况一:

当要删除的结点的左右结点至少有一个为空的情况,就将当前结点的指针改为左右结点中的一个并将自身开辟的空间的空间释放

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rA2O1UJX-1666424817320)(C:\Users\Zhang\AppData\Roaming\Typora\typora-user-images\image-20221022121419015.png)]

情况二:

当要删除的结点左右结点都不为空时,首先将该结点的数据和它中序遍历右边的第一个结点互换数据,然后必定会转换为第一种情况,它的右边第一个结点的左节点必定为空

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dcUvK1Je-1666424817321)(C:\Users\Zhang\AppData\Roaming\Typora\typora-user-images\image-20221022123458111.png)]

 

代码实现

#include <iostream>
using namespace std;
template <class K, class V>
struct BSTreeNode
{
	BSTreeNode(const K& k, const V& v) : lchild(NULL), rchild(NULL), key(k), value(v) {}
	BSTreeNode* lchild;
	BSTreeNode* rchild;
	K key;
	V value;
};

template <class K, class V>
class BST
{
	typedef BSTreeNode<K, V> Node;
public:
	BST() :m_Root(NULL) {}

	bool Insert(const K& k, const V& v)
	{
		return Insert_(this->m_Root, k, v);
	}

	bool Insert_(Node*& root, const K& k, const V& v)
	{
		if (!root)
		{
			root = new Node(k, v);
			return true;
		}

		else
		{
			if (root->key > k)
			{
				return Insert_(root->lchild, k, v);
			}

			else if (root->key < k)
			{
				return Insert_(root->rchild, k, v);
			}

			else
			{
				return false;
			}
		}
	}

	Node* Find(const K& k)
	{
		return Find_(this->m_Root, k);
	}

	Node* Find_(Node* root, const K& k)
	{
		if (!root)
		{
			return NULL;
		}
		else
		{
			if (root->key > k)
			{
				return Find_(root->lchild, k);
			}
			else if (root->key < k)
			{
				return Find_(root->rchild, k);
			}
			else
			{
				return root;
			}
		}
	}

	bool remove(const K& k)
	{
		return remove_(this->m_Root, k);
	}

	bool remove_(Node*& root, const K& k)
	{
		if (!root)
		{
			return false;
		}

		else
		{
			if (root->key > k)
			{
				return remove_(root->lchild, k);
			}

			else if (root->key < k)
			{
				return remove_(root->rchild, k);
			}
				
			else
			{
				Node* del;
				if (!root->lchild)
				{
					del = root;
					root = root->rchild;
					delete del;
					del = NULL;
					return true;
				}

				else if (!root->rchild)
				{
					del = root;
					root = root->lchild;
					delete del;
					del = NULL;
					return true;
				}

				else
				{
					Node* rightfirst = root->rchild;
					while (rightfirst->lchild)
					{
						rightfirst = rightfirst->lchild;
					}
					swap(rightfirst->key, root->key);
					swap(rightfirst->value, root->value);
					remove_(root->rchild, k);
				}
			}
		}
	}

	//二叉搜索树的中序遍历
	void inorderBST()
	{
		inorderBST_(this->m_Root);
		cout << endl;
	}

	void inorderBST_(Node* root)
	{
		if (!root)
		{
			return;
		}
		inorderBST_(root->lchild);
		cout << root->key << " ";
		inorderBST_(root->rchild);
	}

	//释放在堆区开辟的内存空间
	void clear()
	{
		clear_(this->m_Root);
	}

	void clear_(Node* root)
	{
		//基线条件,当根结点为空使说明当前结点清除完毕,返回
		if (!root)
		{
			return;
		}
		else
		{
			//先清除左子树
			clear_(root->lchild);
			//再清除右子树
			clear_(root->rchild);
			//最后清除根结点
			delete root;
		}
	}
private:
	Node* m_Root;
};

int main()
{
	BST<int, int> BSTree;
	BSTree.Insert(6, 2);
	BSTree.Insert(8, 2);
	BSTree.Insert(7, 2);
	BSTree.Insert(4, 2);
	BSTree.Insert(5, 2);
	BSTree.Insert(9, 2);
	BSTree.inorderBST();
	BSTree.remove(6);
	BSTree.inorderBST();
    BSTree.clear();
	system("pause");
	return 0;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t3mygGor-1666424817322)(C:\Users\Zhang\AppData\Roaming\Typora\typora-user-images\image-20221022153238309.png)]

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eF1LCtMK-1666424817322)(C:\Users\Zhang\AppData\Roaming\Typora\typora-user-images\image-20221022153523212.png)]

返回目录

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值