二叉搜索树的概念以及特性想必大家都有所了解,在这里主要讨论它的实现。
具体算法思路见代码注释。
//测试环境为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;
}
结果: