二叉搜索樹的概念以及特性想必大家都有所瞭解,在這裏主要討論它的實現。
具體算法思路見代碼註釋。
//測試環境爲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;
}
結果: