二叉搜索书是一个有排序的树,特点就在于将二叉搜索书按照中序进行遍历的时候的得到的是一个有小到大的有序数列
在创建二叉搜索树的时候,当数据大于当前节点的数据值时就向右子树中插入,当小于当前结点的数据值时,就向左子树插入.
如上图将其按照中序遍历的结果刚好为: 0,1,2,3,4,5,6,7,8,9
注意:二叉搜索树中没有相同的值
二叉搜索树的定义以及节点定义
template<class T>
struct BSTNode{
BSTNode(const T& x=T())
;_left(nullotr)
,right(nullptr)
,data(x)
{}
BSTNode<T>* _left;
BSTNode<T>* _right;
T _data;
};
template<class T>
class BSTree{
typedef BSTNode<T> Node;
typedef BSTNode<T>* pNode;
punlic:
private:
pNode _root;
}
二叉搜索树的插入
1.如果树为空,直接插入
2.通过对当前节点的比较找到值得插入位置插入
bool Insert(const T& x){
if (_root == nullptr){
_root = new Node(x);
return true;
}
pNode cur = _root;
pNode parent = nullptr;
while (cur != nullptr){
if (cur->_data > x){
parent = cur;
cur = cur->_left;
}
else if (cur->_data < x){
parent = cur;
cur = cur->_right;
}
else
return false;
}
cur = new Node(x);
if (parent->_data>x)
parent->_left = cur;
if (parent->_data < x)
parent->_right = cur;
return true;
}
二叉搜索树的删除
1.如果树为空,直接返回
2.先对树进行遍历寻找要删除的结点,如果没有找到,则删除失败
3.对寻找的的结点的位置进行分析
- 1.删除的结点为叶子结点
直接进行删除 - 2.删除的结点只有一个孩子
将该节点的孩子与他的父亲结点相连 - 3.删除的结点有两个孩子
这里有两个处理方法, 一是寻找左子树中最大的结点与该节点进行交换, 二是寻找右子树中最小的结点与该节点进行交换
bool Esare(const T& x){
//判断树是否为空
if (_root == nullptr)
return false;
//寻找结点在树中的位置
pNode parent = nullptr;
pNode cur = _root;
while (cur){
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;
}
//3.孩子节点完整的
//寻找左子树中最大的节点或者右子树中最小的结点
else {
pNode 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;
}
拷贝构造
拷贝构造使需要对copy函数进行封装,因为我们要拷贝的是一整个树,而不是一个节点因此要利用递归的思想对整个树进行拷贝
pNode Copy(pNode root){
//递归结束的条件
if(root){
//拷贝当前的结点
pNode newNode =new Node(root->_data);
//在递归拷贝左右子树
newNode->_left=Copy(root->_left);
newNode->_right=Copy(root->_right);
}
return newNode;
}
BSTree(BSTree<T>& bst){
_root=Copy(bst._root);
}
赋值运算符拆重载
赋值运算时候需要先对树进行清空, 然后在将源数据拷贝过去
BSTree<T>& operator=(BSTree<>T& bst){
if(this!=bst){
if(_root)
_Delete(_root);
_root=Copy(bst._root);
}
return *this;
}
void _Delete(pNode root){
if(root){
_Delete(root->_left);
_Delete(root->_right;
delete root;
root=nullptr;
}
}
全部的源代码与测试数据如下
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;
typedef Node* pNode;
BSTree(const pNode root = nullptr)
:_root(root)
{}
//插入新节点
bool Insert(const T& x){
if (_root == nullptr){
_root = new Node(x);
return true;
}
pNode cur = _root;
pNode parent = nullptr;
while (cur != nullptr){
if (cur->_data > x){
parent = cur;
cur = cur->_left;
}
else if (cur->_data < x){
parent = cur;
cur = cur->_right;
}
else
return false;
}
cur = new Node(x);
if (parent->_data>x)
parent->_left = cur;
if (parent->_data < x)
parent->_right = cur;
return true;
}
void Print(){
if (_root == nullptr)
return;
_Print(_root);
cout << endl;
}
void _Print(const pNode root){
if (root == nullptr)
return;
_Print(root->_left);
cout << root->_data << " ";
_Print(root->_right);
}
//删除节点
bool Esare(const T& x){
//判断树是否为空
if (_root == nullptr)
return false;
//寻找结点在树中的位置
pNode parent = nullptr;
pNode cur = _root;
while (cur){
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;
}
//3.孩子节点完整的
//寻找左子树中最大的节点或者右子树中最小的结点
else {
pNode 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;
}
//结点的查找
pNode Find(const T& x){
if (_root==nullptr)
return nullptr;
pNode cur = _root;
while (cur){
if (cur->_data == x)
break;
else if (x < cur->_data)
cur = cur->_left;
else
cur = cur->_right;
}
return cur;
}
pNode Copy(pNode root){
if (root){
pNode newNode = new Node(root->_data);
newNode->_left = Copy(root->_left);
newNode->_right = Copy(root->_right);
return newNode;
}
else
return nullptr;
}
BSTree(BSTree<T>& bst){
_root = Copy(bst._root);
}
BSTNode<T>& operator=(const BSTree<T>& bst){
if (this != &bst){
//先对树进行清空
if (_root){
_Delete(_root);
}
//再将要拷贝的树拷贝过来
_root = Copy(bst._root)
}
return *this;
}
~BSTree(){
_Delete(_root);
}
private:
pNode _root;
void _Delete(pNode root){
if (root){
_Delete(root->_left);
_Delete(root->_right);
delete root;
root = nullptr;
}
}
};
void Test(){
BSTree<int> bt;
bt.Insert(5);
bt.Insert(3);
bt.Insert(7);
bt.Insert(1);
bt.Insert(4);
bt.Insert(6);
bt.Insert(8);
bt.Insert(0);
bt.Insert(2);
bt.Insert(9);
bt.Insert(10);
bt.Print();
BSTree<int> bt1 = bt;
bt1.Print();
}
int main(){
Test();
system("pause");
return 0;
}