C++ 實現二叉搜索樹—BSTree

二叉搜索樹的概念以及特性想必大家都有所瞭解,在這裏主要討論它的實現。
具體算法思路見代碼註釋。

//測試環境爲VS2013

#include <iostream>
#include <stdlib.h>
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){
				//假如已經有了bst1,現在欲將bst2賦值給bst1,
				//即 bst1 = bst2
				//就應該先將原先的bst1釋放了,再將bst2賦給它,否則會造成內存泄漏
				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 != nullptr){
			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 != nullptr){
			if (cur->_data == x)
				//二叉搜索樹裏不能有相同節點,所以就返回錯誤
				return false;
			else if (x > cur->_data){
				parent = cur;
				cur = cur->_right;
			}
			else{
				parent = cur;
				cur = cur->_left;
			}
		}
		//將x的值存入節點中
		//再分析新節點值與parent節點值的大小關係
		//若x大於parent值,就將parent的右指針鏈接cur;反之鏈接左指針
		cur = new Node(x);
		if (x > parent->_data)
			parent->_right = cur;
		else
			parent->_left = cur;
		return true;
	}
	
	//刪除
	bool Erase(const T& x)
	{
		if (_root == nullptr)
			//若爲空樹,則刪除失敗
			return false;
		Node* cur = _root;
		Node* parent = nullptr;
		//要做刪除,先做查找,即先找到要刪除的節點
		while (cur != nullptr){
			if (cur->_data == x)
				break;
			else if (x < cur->_data){
				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;
		}

		//2.孩子節點不完整(有左無右,有右無左)

		//要刪除的節點只有右孩子
		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->_left == cur)
					parent->_left = cur->_left;
				else
					parent->_right = cur->_left;
			}
			else{
				_root = cur->_left;
			}
			delete cur;
			cur = nullptr;
		}

		//若要刪除的節點的左右孩子均完整
		else{
			//在左邊找個最大的(或者在右邊找最小的)
			Node* leftMost = cur->_left;
			parent = cur;
			//找左邊最大的
			//因爲要找左邊最大的,就要往cur的左孩子的right找
			while (leftMost->_right){
				parent = leftMost;
				leftMost = leftMost->_right;
			}
			//找到了
			//置換兩個節點的值,然後將leftMost節點刪除
			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()
	{
		Print_Inorder(_root);
		cout << endl;
	}

	//打印
	void Print_Inorder(Node* root)
	{
		if (root != nullptr){
			Print_Inorder(root->_left);
			cout << root->_data << " ";
			Print_Inorder(root->_right);
		}
	}
private:
	Node* _root;
};

void Test()
{
	BSTree<int> bstree;

	bstree.Insert(0);
	bstree.Insert(1);
	bstree.Insert(2);
	bstree.Insert(3);
	bstree.Insert(4);
	bstree.Insert(5);
	bstree.Insert(6);
	bstree.Insert(7);
	bstree.Insert(8);
	bstree.Insert(9);
	cout << "bstree:";
	bstree.Inorder();

	/*bstree.Inorder();
	bstree.Erase(5);
	bstree.Inorder();
	bstree.Erase(4);
	bstree.Inorder();
	bstree.Erase(8);
	bstree.Erase(9);
	bstree.Inorder();
	bstree.Erase(7);
	bstree.Inorder();
	bstree.Erase(2);
	bstree.Erase(1);
	bstree.Inorder();*/

	BSTree<int> bst;
	bst.Insert(0);
	bst.Insert(1);
	bst.Insert(2);
	bst.Insert(3);
	bst.Insert(4);
	bst.Insert(5);
	cout << "bst:";
	bst.Inorder();
	//BSTree<int> bst (bstree);
	//bst.Inorder();

	bst = bstree;
	cout << "賦值: ";
	bst.Inorder();
}
int main()
{
	Test();
	system("pause");
	return 0;
}

結果:
在這裏插入圖片描述

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