二叉搜索树的实现

目录

1、前言

2、二叉搜索树

(1). 二叉搜索树的查找

(2). 二叉搜索树的插入

(3). 二叉搜索树的删除

3、模拟实现

4、结语


1、前言

之前对二叉树进行了实现,这次对二叉搜索树进行实现,可能有的小伙伴会觉得没有必要,但其实,二叉搜索树有很多可以使用的场景,虽然二叉搜索树有缺陷,但是这种数据结构也很值得去玩,从中可以获得很多新的感悟。本篇文章仅仅只是个人看法,如果有错误或者其他问题,可以私信作者,联系我指出,谢谢!

2、二叉搜索树

二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:

        若它的左子树不为空,则左子树上所有节点的值都小于根节点的值

        若它的右子树不为空,则右子树上所有节点的值都大于根节点的值

        它的左右子树也分别为二叉搜索树

        使用中序遍历去遍历整个搜索二叉树的时候,会得到一个有序集合。

(1). 二叉搜索树的查找

        a、从根开始比较,查找,比根大则往右边走查找,比根小则往左边走查找。

        b、最多查找高度次,走到到空,还没找到,这个值不存在。

(2). 二叉搜索树的插入

插入的具体过程如下:

        a. 树为空,则直接新增节点,赋值给root指针

        b. 树不空,按二叉搜索树性质查找插入位置,插入新节点

(3). 二叉搜索树的删除

首先查找元素是否在二叉搜索树中,如果不存在,则返回, 否则要删除的结点可能分下面四种情况:

        a. 要删除的结点无孩子结点

        b. 要删除的结点只有左孩子结点

        c. 要删除的结点只有右孩子结点

        d. 要删除的结点有左、右孩子结点

看起来有待删除节点有4中情况,实际情况a可以与情况b或者c合并起来,因此真正的删除过程如下:

        情况b:删除该结点且使被删除节点的双亲结点指向被删除节点的左孩子结点--直接删除

        情况c:删除该结点且使被删除节点的双亲结点指向被删除结点的右孩子结点--直接删除

        情况d:在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除节点中,再来处理该结点的删除问题--替换法删除

3、模拟实现


#include <iostream>

using namespace std;

template<class K, class V>
struct BSTreeNode {

	BSTreeNode(const K& key = K(), const V& value = V()) 
		:_key(key), _value(value), _left(nullptr),_right(nullptr)
	{}

	K _key;
	V _value;
	BSTreeNode<K,V>* _left;
	BSTreeNode<K, V>* _right;
};

template<class K, class V>
class BSTree
{
	typedef BSTreeNode<K, V> Node;

public:
	~BSTree() {
		destructor(_root);
	}
	void destructor(Node*& root) {
		if (root == nullptr) return;
		if (root->_left == root->_right) {
			delete root;
			root = nullptr;
			return;
		}
		destructor(root->_left);
		destructor(root->_right);
		delete root;
		root = nullptr;
	}
public:
	bool Insert(const K& key, const V& value) {
		Node* node = new Node(key,value);

		if (_root == nullptr) {
			_root = node;
			return true;
		}
		Node* temp = _root;
		while (temp != nullptr) {
			if (node->_key == temp->_key) {
				return false;
			}
			if (node->_key > temp->_key) {
				if (temp->_right == nullptr) {
					temp->_right = node;
					return true;
				}
				temp = temp->_right;
			}
			else {
				if (temp->_left == nullptr) {
					temp->_left = node;
					return true;
				}
				temp = temp->_left;
			}
		}
		
	}
	Node* Find(const K& key) {
		if (_root == nullptr) return nullptr;
		
		Node* temp = _root;
		while (temp != nullptr) {
			if (key == temp->_key) return temp;
			if (key > temp->_key) temp = temp->_right;
			else temp = temp->_left;
		}
		return nullptr;
	}

	Node* MaxNode(Node* root) {
		while (root->_right != nullptr) {
			root = root->_right;
		}
		return root;
	}

	bool _Erase(Node*& root) {
		if (root->_left == nullptr && root->_right == nullptr) {
			delete root;
			root = nullptr;
			return true;
		}
		if (root->_left == nullptr) {
			Node* temp = root->_right;
			delete root;
			root = temp;
			return true;
		}
		if (root->_right == nullptr) {
			Node* temp = root->_left;
			delete root;
			root = temp;
			return true;
		}
		Node* leftMax = MaxNode(root->_left);
		if (leftMax->_left == nullptr){
			swap(leftMax->_key,root->_key);
			swap(leftMax->_value,root->_value);
			delete leftMax;
			leftMax = nullptr;
		}
		else {
			swap(leftMax->_key, root->_key);
			swap(leftMax->_value, root->_value);

			leftMax->_key = leftMax->_left->_key;
			leftMax->_value = leftMax->_left->_value;
			leftMax->_right = leftMax->_left->_right;
			leftMax->_left = leftMax->_left->_left;
		}
	}

	bool Erase(const K& key) {
		if (key == _root->_key) return _Erase(_root);
		Node* temp = _root;
		while (temp != nullptr) {
			if (key < temp->_key) {
				if (temp->_left == nullptr) return false;
				if (key == temp->_left->_key) {
					return _Erase(temp->_left);
				}	
				else {
					temp = temp->_left;
				}
			}
			else {
				if (temp->_right == nullptr) return false;
				if (key == temp->_right->_key) {
					return _Erase(temp->_right);
				}
				else {
					temp = temp->_right;
				}
			}
		}
		return false;
	}
	void _InOrder(Node* root) {
		if (root == nullptr) return;
		if (root->_left == nullptr && root->_right == nullptr) {
			cout << "key:" << root->_key << "    value:" << root->_value << endl;
			return;
		}
		_InOrder(root->_left);
		cout << "key:" << root->_key << "    value:" << root->_value << endl;
		_InOrder(root->_right);
	}
	void InOrder() {
		_InOrder(_root);
	}
private:
	Node* _root = nullptr;
};

4、结语

如有错误和其他问题!欢迎各位朋友私信我!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孟婆的cappucino

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值