二叉查找树的 c++实现

基本概念

  1. BST

    二叉查找树又称二叉搜索树或者二叉排序树;它可以是一个空树或者是一个二叉树,既有链表的快速插入与删除的特点,又有数组快速查找的优势。

  2. 基本性质

    二叉查找树非空时,具有以下性质:

    ①.若左子树非空,则左子树所有节点均小于根节点的值

    ②.若右子树非空,则右子树所有节点均大于跟节点的值

    ③.左右子树也是二叉查找树

    ④.没有键值相等的节点

  3. 基本操作

    ①.插入:插入一个新值

    ②.查找:根据键值查找节点

    ③.删除:根据键值删除节点

  4. 其他

    ①.前驱节点:所有节点从小到大到大排列后的小于本节点键值的前一个节点

    ②.后继节点:所有节点从小到大到大排列后的大于本节点键值的后一个节点

    ③.中序遍历:按照“左节点”、“本节点”、“右节点”的顺序遍历树;中序遍历的结果就是元素值从小到大的排列

    ④.前序遍历:按照“本节点”、“左节点”、“右节点”的顺序遍历树

    ⑤.后序遍历:按照“左节点”、“右节点”、“中节点”的顺序遍历树

实现方法

// BST节点类
class TBSTNode
{
private:
	TBSTNode * leftChild;//左子树
	TBSTNode * rightChild;//右子树
	int val; //节点值
	TBSTNode * parentNode;//父节点
public:
	//构造函数
	TBSTNode(int key) :leftChild(nullptr), rightChild(nullptr), val(key),parentNode(nullptr) {};
	TBSTNode(int key, TBSTNode * node) :leftChild(nullptr), rightChild(nullptr), val(key), parentNode(node) {};
	//析构函数,释放子节点
	~TBSTNode()
	{
		if( leftChild )
		{
			delete leftChild;
			leftChild = nullptr;
		}
		if( rightChild )
		{
			delete rightChild;
			rightChild = nullptr;
		}	
	};
	// 公开接口
	int getKey()//访问节点值
	{
		return val;
	};
	void setKey(int key)//重置节点值
	{
		val = key;
	};
	TBSTNode * getLeft()//访问左子树
	{
		return leftChild;
	};
	void setLeft(TBSTNode * node)//重置左子树
	{
		leftChild = node;
	};
	TBSTNode * getRight()//访问右子树
	{
		return rightChild;
	};
	void setRight(TBSTNode * node)//重置右子树
	{
		rightChild = node;

	};
	TBSTNode * getParent()//访问父节点
	{
		return parentNode;
	};
	void setParent(TBSTNode * node)//重置父节点
	{
		parentNode = node;
	};
};
// BST 树类
class TBSTree
{
public:
	TBSTree() :root(nullptr) {};
	~TBSTree()
	{
		if (root)
		{
			delete root;
			root = nullptr;
		}
	};
	//对外接口
	void insertKey(int key)//插入一个值
	{
		if (!root)
		{
			root = new TBSTNode(key);
		}
		else
		{
			insertKey(root, key);
		}
	}
	TBSTNode * searchKey(int key)// 根据值查询节点
	{
		TBSTNode * temp = root;//遍历树
		while (temp)
		{
			if (key > temp->getKey())// 比本节点大,继续比较右节点
			{
				temp = temp->getRight();
			}
			else if (key < temp->getKey()) // 比本节点大,继续比较左节点
			{
				temp = temp->getLeft();
			}
			else
				return temp;
		}
		return nullptr;
	};
	TBSTNode * getNext(TBSTNode * node)//查询一个节点的后继节点
	{
		if (node)
		{
			vector<TBSTNode *> tempvector;
			toVectorByMidorder(node->getRight(), tempvector);
			if (tempvector.size() > 0)
			{
				TBSTNode * nextNode = tempvector[0];//后继节点
				return nextNode;
			}
		}
		return nullptr;
	};
	TBSTNode * getPre(TBSTNode * node)//查询一个节点的前驱节点
	{
		if (node)
		{
			vector<TBSTNode *> tempvector;
			toVectorByMidorder(node->getLeft(), tempvector);
			if (tempvector.size() > 0)
			{
				TBSTNode * preNode = tempvector[tempvector.size()-1];//前驱节点
				return preNode;
			}
		}
		return nullptr;
	}
	void deleteKey(int key)//按值删除节点
	{
		TBSTNode * temp = searchKey(key);
		if (temp)
		{
			deleteKey(temp);
		}
	}
	void printByMid()//中序打印数
	{
		printByMid(root);
	};
	
private:
	TBSTNode * root;
	void insertKey(TBSTNode * root, int key)// 在某子树插入新值
	{
		TBSTNode * parent = nullptr;//定位插入点
		TBSTNode * temp = root;//用于遍历树
		while (temp)
		{
			parent = temp;
			if (key > temp->getKey())// 比本节点大,继续比较右节点
			{
				temp = temp->getRight();
			}
			else if (key < temp->getKey()) // 比本节点大,继续比较左节点
			{
				temp = temp->getLeft();
			}
			else
				return;
		}
		if ( key > parent->getKey())
		{
			parent->setRight(new TBSTNode(key,parent));//做为右子节点
		}
		else if (key < parent->getKey())
		{
			parent->setLeft(new TBSTNode(key,parent));//做为左子节点
		}
	}
	void printByMid(TBSTNode * root )
	{
		if (root)
		{
			printByMid(root->getLeft());
			cout << root->getKey() << " ";
			printByMid(root->getRight());
		};
	};
	void toVectorByMidorder(TBSTNode * root,vector<TBSTNode * > &temp_vector)
	{
		if (root)
		{
			toVectorByMidorder(root->getLeft(), temp_vector);
			temp_vector.push_back(root);
			toVectorByMidorder(root->getRight(), temp_vector);
		}
	}
	void deleteKey(TBSTNode * node)
	{
		TBSTNode * temp = node;
		if (temp)
		{
			TBSTNode * tempParent = temp->getParent();//目标父节点
			TBSTNode * left = temp->getLeft();//目标左子树
			TBSTNode * right = temp->getRight();//目标右子树

			if (left == nullptr)
			{
				if (right == nullptr)//没有左右子节点,直接删除
				{
					if (tempParent == nullptr){}//父节点为空
					else
					{
						//断开和父节点的关联
						if (tempParent->getLeft() == temp)
						{
							tempParent->setLeft(nullptr);
						}
						else
						{
							tempParent->setRight(nullptr);
						}
					}
					delete temp;//释放本节点内存
					temp = nullptr;
				}
				else //只有右节点,右子树继承父节点
				{
					//右节点关联到父节点,取代本节点位置
					right->setParent(tempParent);
					if ( tempParent )
					{
						if (tempParent->getLeft() == temp)
						{
							tempParent->setLeft(right);
						}
						else
						{
							tempParent->setRight(right);
						}
					}
					temp->setRight(nullptr);//本节点和其子节点断开
					delete temp;
					temp = nullptr;
				}
			}
			else
			{
				if (right == nullptr)//只有左节点,左子树继承父节点
				{
					//右节点关联到父节点,取代本节点位置
					left->setParent(tempParent);
					if (tempParent)
					{
						if (tempParent->getLeft() == temp)
						{
							tempParent->setLeft(left);
						}
						else
						{
							tempParent->setRight(left);
						}
					}
					temp->setLeft(nullptr);
					delete temp;
					temp = left;
				}
				else//用后继节点取代本节点
				{
					TBSTNode * nextNode = getNext(temp);
					temp->setKey(nextNode->getKey());//更新为后继节点的值
					deleteKey(nextNode);// 删除后继节点
				}
			}
		}
	}
};

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值