C++(map/multimap/set/multiset)底層實現---二叉搜索樹

二叉搜索樹的概念

二叉搜索樹又稱二叉排序樹,它或者是一棵空樹或者是具有以下性質的二叉樹:

若它的左子樹不爲空,則左子樹上所有節點的值都小於根節點的值

若它的右子樹不爲空,則右子樹上所有節點的值都大於根節點的值

它的左右子樹也分別爲二叉搜索樹

 

                                   

二叉搜索樹的插入

插入的具體過程如下:

a. 樹爲空,則直接插入

b. 樹不空,按二叉搜索樹性質查找插入位置,插入新節點

                            

     bool Insert(const T& x)
	{
        //樹爲空直接插入
		if (_root == nullptr)
		{
			_root = new Node(x);
			return true;
		}

		Node* cur = _root;
		Node* parent = nullptr;
        //尋找插入位置
		while (cur)
		{
			if (cur->_data == x)
				return false;
			else if (x > cur->_data)
			{
				parent = cur;
				cur = cur->_right;
			}
			else
			{
				parent = cur;
				cur = cur->_left;
			}
		}
		cur = new Node(x);
		if (parent->_data > x)
			parent->_left = cur;
		else
			parent->_right = cur;
		return true;
	}

3. 二叉搜索樹的刪除

首先查找元素是否在二叉搜索樹中,如果不存在,則返回, 否則要刪除的結點可能分下面四種情況:

a. 要刪除的結點無孩子結點(葉子節點)

if (cur->_left == nullptr && cur->_right == nullptr)
		{
			if (cur != _root)
			{
				if (parent->_left == cur)
					parent->_left = nullptr;
				else
					parent->_right = nullptr;
			}
			else
				_root = nullptr;

			delete cur;
			cur = nullptr;
		}

b. 要刪除的結點只有左孩子結點

else if (cur->_right == nullptr)
		{
			if (cur != _root)
			{
				if (parent->_right == cur)
					parent->_right = cur->_left;
				else
					parent->_left = cur->_left;
			}
			else
			{
				_root = cur->_left;
			}
			delete cur;
			cur = nullptr;
		}

c. 要刪除的結點只有右孩子結點

else if (cur->_left == nullptr)
		{
			if (cur != _root)
			{
				if (parent->_left == cur)
					parent->_left = cur->_right;
				else
					parent->_right = cur->_right;
			}
			else
			{
				_root = cur->_right;
			}
			delete cur;
			cur = nullptr;
		}

d. 要刪除的結點有左、右孩子結點

看起來有待刪除節點有4中情況,實際情況a可以與情況b或者c合併起來,因此真正的刪除過程如下:

情況b:刪除該結點且使被刪除節點的雙親結點指向被刪除節點的左孩子結點

情況c:刪除該結點且使被刪除節點的雙親結點指向被刪除結點的右孩子結點

情況d:在它的右子樹中尋找中序下的第一個結點(關鍵碼最小),用它的值填補到被刪除節點中,再來處理該結點的刪除問題

                Node* leftMost = cur->_left;
			parent = cur;
			//找到左邊最大
			while (leftMost->_right)
			{
				parent = leftMost;
				leftMost = leftMost->_right;
			}
			//置換
			cur->_data = leftMost->_data;
			if (parent->_right == leftMost)
				parent->_right = leftMost->_left;
			else
				parent->_left = leftMost->_left;
			//刪除節點
			delete leftMost;
			leftMost = nullptr;

代碼整合

#include <iostream>
using namespace std;

template <class T>
struct BSTNode
{
	BSTNode(const T& val = T())
	:_left(nullptr)
	, _right(nullptr)
	, _data(val)
	{}
	BSTNode<T>* _left;
	BSTNode<T>* _right;
	T _data;
};

template <class T>
class BSTree
{
public:
	typedef BSTNode<T> Node;
	BSTree(Node* root = nullptr)
		:_root(root)
	{}

	Node* Copy(Node* root)
	{
		if (root)
		{
			Node* newNode = new Node(root->_data);
			newNode->_left = Copy(root->_left);
			newNode->_right = Copy(root->_right);
			return newNode;
		}
		else
			return nullptr;

	}

	BSTree(const BSTree<T>& bst)
	{
		_root = Copy(bst._root);
	}

	BSTree<T>& operator=(const BSTree<T>& bst)
	{
		if (this != &bst)
		{
			if (_root)
			{
				Destory(_root);
			}
			_root = Copy(bst._root);
		}
		return *this;
	}
	//銷燬
	void Destory(Node* root)
	{
		if (root)
		{
			Destory(root->_left);
			Destory(root->_right);
			delete root;
			root = nullptr;
		}
	}

	~BSTree()
	{
		if (_root)
			Destory(_root);
	}
	//查找
	Node* find(const T& x)
	{
		if (_root == nullptr)
			return nullptr;
		Node* cur = _root;
		while (cur)
		{
			if (cur->_data == x)
				return cur;
			else if (x > cur->_data)
				cur = cur->_right;
			else
				cur = cur->_left;
		}
		return nullptr;
	}

	bool Insert(const T& x)
	{
		if (_root == nullptr)
		{
			_root = new Node(x);
			return true;
		}

		Node* cur = _root;
		Node* parent = nullptr;
		while (cur)
		{
			if (cur->_data == x)
				return false;
			else if (x > cur->_data)
			{
				parent = cur;
				cur = cur->_right;
			}
			else
			{
				parent = cur;
				cur = cur->_left;
			}
		}
		cur = new Node(x);
		if (parent->_data > x)
			parent->_left = cur;
		else
			parent->_right = cur;
		return true;
	}

	bool Erase(const T& x)
	{
		if (_root == nullptr)
			return false;
		Node* cur = _root;
		Node* parent = nullptr;
		while (cur)
		{
			if (cur->_data == x)
				break;
			else if (cur->_data > x)
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				parent = cur;
				cur = cur->_right;
			}
		}

		if (cur == nullptr)
			return false;
		//1. 葉子節點
		if (cur->_left == nullptr && cur->_right == nullptr)
		{
			if (cur != _root)
			{
				if (parent->_left == cur)
					parent->_left = nullptr;
				else
					parent->_right = nullptr;
			}
			else
				_root = nullptr;

			delete cur;
			cur = nullptr;
		}
		//孩子節點不完整
		else if (cur->_left == nullptr)
		{
			if (cur != _root)
			{
				if (parent->_left == cur)
					parent->_left = cur->_right;
				else
					parent->_right = cur->_right;
			}
			else
			{
				_root = cur->_right;
			}
			delete cur;
			cur = nullptr;
		}
		else if (cur->_right == nullptr)
		{
			if (cur != _root)
			{
				if (parent->_right == cur)
					parent->_right = cur->_left;
				else
					parent->_left = cur->_left;
			}
			else
			{
				_root = cur->_left;
			}
			delete cur;
			cur = nullptr;
		}
		else
		{
			Node* leftMost = cur->_left;
			parent = cur;
			//找到左邊最大
			while (leftMost->_right)
			{
				parent = leftMost;
				leftMost = leftMost->_right;
			}
			//置換
			cur->_data = leftMost->_data;
			if (parent->_right == leftMost)
				parent->_right = leftMost->_left;
			else
				parent->_left = leftMost->_left;
			//刪除節點
			delete leftMost;
			leftMost = nullptr;
		}

		return true;
	}

	void Inorder()
	{
		_Inorder(_root);
		cout << endl;
	}

	void _Inorder(Node* root)
	{
		if (root)
		{
			_Inorder(root->_left);
			cout << root->_data << " ";
			_Inorder(root->_right);
		}
	}
private:
	Node* _root;
};

int main()
{
	BSTree<int> bstree;
	bstree.Insert(10);
	bstree.Insert(9);
	bstree.Insert(4);
	bstree.Insert(8);
	bstree.Insert(2);
	bstree.Insert(19);
	bstree.Insert(31);

	bstree.Inorder();

	BSTree<int> copy(bstree);
	copy.Inorder();
	copy.Erase(10);
	copy.Inorder();
	copy = bstree;
	copy.Inorder();

	system("pause");
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章