数据结构:二叉搜索树(Binary Search Tree)

本文深入探讨了二叉搜索树(BST)的实现与操作,包括查找、插入、删除等核心算法,并提供了详细的代码示例。同时,文章还介绍了树的遍历方式,如中序、前序和后序遍历。

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

Binary Search Tree(BST)

创作人:ZJUT_YC
测试代码还没有加上,后续补齐。

代码实现

#pragma once
#include <iostream>
using namespace std;

template<class T>
class BST
{
private:
	class Node {
		T m_data;
		Node* m_left;
		Node* m_right;
	};
	Node* m_root;
public:
	bool isEmpty()const;
	bool searchRecursive(const T& item);// 查找某个元素是否在树中(递归版本)
	bool searchNonRecursive(const T& item); // 查找某个元素是否在树中(非递归版本)
	void insert(const T& item);// 将元素插入到二叉树中
	void remove(const T& item);// 将元素从二叉树中删除
	void inOrder(ostream& os);//遍历树的方式:中序遍历
	void leftOrder(ostream& os);//遍历树的方式:前序遍历
	void rightOrder(ostream& os);//遍历树的方式:后续遍历
private:
	bool searchAux(BST<T>::Node* subRoot,const T& item)const; // 查找辅助函数 
	void inOrderAux(ostream& os, BST<T>::Node* subRoot)const; // 中序遍历Aux
	void leftOrderAux(ostream& os, BST<T>::Node* subRoot)const;// 前序遍历Aux
	void rightOrderAux(ostream& os, BST<T>::Node* subRoot)const;// 后序遍历Aux
};

template<class T>
inline bool BST<T>::isEmpty() const
{
	return m_root==nullptr;
}

template<class T>
inline bool BST<T>::searchRecursive(const T& item)
{
	return searchAux(m_root,item);
}

template<class T>
inline bool BST<T>::searchNonRecursive(const T& item)
{
	BST<T>::Node* localptr = m_root;
	while (nullptr != localptr) {
		if (item < localptr->m_data) {
			localptr = localptr->m_left;
		}
		else if (item > localptr->m_data) {
			localptr = localptr->m_right;
		}
		else {
			return true;
		}
	}
	return false;
}

// 二叉树的插入
template<class T>
inline void BST<T>::insert(const T& item)
{
	BST<T>::Node* ptr = m_root;
	BST<T>::Node* parent=nullptr;
	bool found = false;
	while (!found && ptr!=nullptr) {
		parent = ptr;
		if (item < ptr->m_data)
			ptr = ptr->left;
		else if(item > ptr->right)
			ptr = ptr->right;
		else
			found = true;
	}//1. 先判断元素item在不在二叉树中

	// 2. 元素在树中与否执行相应的操作
	if (found)// 2.1 元素在树中
		std::cout << "item" << item << " has already exist!\n";
	else {
		// 2.2 元素不在二叉树中,则插入元素
		// 插入时区分是否为空树
		BST<T>::Node* newNode = new BST<T>::Node(item);
		if (parent == nullptr) //一颗空的树
			m_root = newNode;
		if (item<parent->m_data)
		{
			parent->left = item;
		} 
		else
		{
			parent->right = item;
		}
	}
}

template<class T>
inline void BST<T>::remove(const T& item)
{
	BST<T>::Node* localptr = m_root;
	BST<T>::Node* parent_of_localptr = nullptr;
	bool leftNode = true;
	while (nullptr != localptr) {
		parent_of_localptr = localptr; // localptr的父节点
		if (item < localptr->m_data) {
			localptr = localptr->m_left;
			leftNode = true;
		}
		else if(item>localptr->m_data){
			localptr = localptr->m_right;
			leftNode = false;
		}
		else {
			break; // 此时localptr保存的是item所在元素的值
		}
	}

	if (nullptr == localptr) {
		return; // 表示没有这个元素
	}
	else { // 在BST中找到元素item
		// 分情况讨论
		// 1.localptr指向的节点是叶子节点
		if (localptr->m_left == nullptr && localptr->m_right == nullptr) {
			if (leftNode) {
				parent_of_localptr->m_left = nullptr;
				delete localptr;  // 将空间释放,当然也可以将参数放在函数的参数列表中,由外层进行释放
			}
			else {
				parent_of_localptr->m_right = nullptr;
				delete localptr;
			}
		}
		// 2.1 localptr指向的节点只有一个子节点,且为右子节点
		if (localptr->m_left == nullptr && localptr->m_right != nullptr) {
			if (leftNode) { // localptr是parent的左子节点
				parent_of_localptr->m_left = localptr->m_right;
			}
			else
			{
				parent_of_localptr->m_right = localptr->m_right;
			}
			// 将待删除节点和其子节点解绑,回收内存
			localptr->m_right = nullptr;
			delete localptr; //想象一下删除的过程
		}
		// 2.2 localptr指向的节点只有一个子节点,且为左子节点
		if (localptr->m_left != nullptr && localptr->m_right == nullptr) {
			if (leftNode)
				parent_of_localptr->m_left = localptr->m_left;
			else
				parent_of_localptr->m_right = localptr->m_left;

			localptr->m_left = nullptr;
			delete localptr;
		}
		// 3.localptr指向的节点有两个子节点
		if (localptr->m_left!=nullptr && localptr->m_right!=nullptr) {
			BST<T>::Node* ptr = localptr->m_right;
			BST<T>::Node* ptr_parent = localptr;
			bool noLeftNodeOfLocalptrRight = true;
			while (nullptr != ptr->m_left) {
				noLeftNodeOfLocalptrRight = false;
				ptr_parent = ptr;
				ptr = ptr->m_left;
			}

			// 待删除节点的右子节点没有左子节点,即localptr->m_right->left=nullptr
			if (noLeftNodeOfLocalptrRight) { // localptr->m_right没有左子树
				localptr->m_right->left = localptr->m_left;
				localptr->m_leftptr=localptr->m_right = nullptr;
				delete localptr;
			}
			else { // localptr->m_right有左子节点,成功到达其左子树,ptr表示后驱节点,parent是ptr的父节点
				localptr->m_data = ptr->m_data; // 待删除节点不需要删除,只要将其值改为其后驱节点的值即可
				// ptr存在右子节点
				if (ptr->m_right != nullptr) { // 后驱节点没有左子节点:由它的定义决定的
					ptr_parent->m_left = ptr->m_right;
					ptr->m_right = nullptr; //将后驱节点和它的右子节点解绑
					delete ptr;
				}
				else {//ptr不存在右子节点
					ptr_parent->m_left = nullptr;
					delete ptr;
				}
			}
		}
	}
}

template<class T>
inline void BST<T>::inOrder(ostream& os)
{
	inOrderAux(os, m_root);
}

template<class T>
inline void BST<T>::leftOrder(ostream& os)
{
	leftOrderAux(os, m_root);
}

template<class T>
inline void BST<T>::rightOrder(ostream& os)
{
	rightOrderAux(os, m_root);
}


template<class T>
inline bool BST<T>::searchAux(BST<T>::Node* subRoot, const T& item) const
{
	if (subRoot == nullptr) return false;
	if (subRoot != nullptr) {
		if (item > subRoot->m_data) {
			searchAux(subRoot->m_right, item);
		}
		else if (item < subRoot->m_data) {
			searchAux(subRoot->m_left, item);
		}
		else {
			return true;
		}
	}
}

// 中序遍历Aux
template<class T>
inline void BST<T>::inOrderAux(ostream& os, BST<T>::Node* subRoot) const
{
	if (subRoot != nullptr) {
		inOrderAux(os, subRoot->left);
		os << subRoot->m_data << "  ";
		inOrderAux(os, subRoot->right);
	}
	
}

//前序遍历Aux
template<class T>
inline void BST<T>::leftOrderAux(ostream& os, BST<T>::Node* subRoot) const
{
	if (subRoot != nullptr) {
		std::cout << subRoot->data;
		leftOrderAux(os, subRoot->left);
		leftOrderAux(os, subRoot->right);
	}
}

//后序遍历Aux
template<class T>
inline void BST<T>::rightOrderAux(ostream& os, BST<T>::Node* subRoot) const
{
	if (subRoot != nullptr) {
		rightOrderAux(os, subRoot->left);
		rightOrderAux(os, subRoot->right);
		std::cout << subRoot->m_data << "  ";
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值