BinarySearchTree

二叉搜索树的性质:
1、每一个节点都有一个作为搜索依据的关键码(key),所有节点的关键码都不同。
2、左子树上所有关键码(key)都小于根节点的关键码(key)。
3、右 子树上所有关键码(key)都大于根节点的关键码(key)。
4、左右子树都是二叉搜索树。
查找高度次,LogN
构造函数
拷贝构造
赋值运算符重载
析构函数
插入(bool):
树为空,直接插到根节点;
树不为空,定义一个parent记录cur的父亲,cur走到空,parent就走到叶子节点
和根节点比较,大于根节点就插入右子树,小于根节点就插入到左子树
cur指向根,key大于cur->_key,cur就cur->_right向下,直到cur为空
反之,就是左
再或就是相等,输出false。
走到这里树就为空了, cur=new Node(key) ,要考虑插入到parent的左还是右,和parent->_key比较
查找:
定义一个cur存放根节点
如果cur存在(根节点存在),就把cur->_key和key比较,若 cur->_key 大于key,就往左子树走cur=cur->_left,反之就向右子树走,再或者就相等,直接return cur。
出循环,如果cur不存在,直接return NULL
删除(bool):
好删的:叶子好删,非叶子的左或者右为空都很好删,直接让自己的叶子顶替自己成为父亲的孩子即可
难删的:中间节点,左右都不为空,替换法,删掉一个之后,用另一个替换自己,考虑用哪一个替换

定义一个parent置空
定义一个cur存放root
创建循环while(cur)
将cur的key和key作比较,如果cur->_key大于key,那么先把curgei parent记录,然后让cur往他的左子树走;反之,向它的右子树走,反之相等的话,就删除。

删除这里分为3种情况:
1、左为空
2、右为空
3、左右都不为空
当左为空,且cur为parent的右时,就让父亲的右指向cur的右;反之让父亲的左指向cur的右。
当右为空,且cur为parent的左时,就让父亲的左指向cur的左;反之让父亲的右指向cur的左。
当左右都不为空:
定义一个parent初始化为cur
定义一个sub记录cur的右子树sub=cur->_right;
创建while循环,当sub->_left存在,也就是右子树的左子树存在;让parent先存sub,然后sub向它的左子树走;
到了这里说明sub的左不存在了,到了岔路口了,找到右子树的最左节点了,但这个最左节点不一定是叶子节点,也有可能是根,但他的左一定为空。
然后把sub的key给cur的key ,如果sub是parent的左,就让parent的左指向sub的right;反之,如果sub不是parent的左,有可能是parent的右,就让parent的右指向sub的右。

#pragma once
#include <iostream>
using namespace std;

template<class K>
struct BinarySearchTreeNode//二叉搜索树节点
{
BinarySearchTreeNode<K>* _left;//参数左
BinarySearchTreeNode<K>* _right;//参数右
BinarySearchTreeNode<K>* _parent;
K _key;//
BinarySearchTreeNode(const K& key)//初始化各个参数
:_key(key)
, _left(NULL)
, _right(NULL)
{}

};

template<class K>
class BinarySearchTree//二叉搜索树
{
typedef BinarySearchTreeNode<K> Node;//重命名一下节点
public:
BinarySearchTree()//构造
:_root(NULL)
{}
//BinarySearchTree(const BinarySearchTree& t);//拷贝构造
//BinarySearchTree& operator=(BinarySearchTree t);//赋值运算符重载
//~BinarySearchTree();//析构
bool Insert(const K& key)//插入一个key
{
if (_root == NULL)
{
_root = new Node(key);
return true;
}
Node* parent = NULL;
Node* cur = _root;
while (cur)
{
if (cur->_key > key)
{
parent = cur;
cur = cur->_left;
}
else if (cur->_key < key)
{
parent = cur;
cur = cur->_right;
}
else
{
return false;
}
}
cur = new Node(key);
if (parent->_key > key)
{
parent->_left = cur;
}
else
{
parent->_right = cur;
}
return true;
}
// Node* cur = _root;
// if (cur == NULL)
// {
// cur=new Node(key);//有问题,无法解析的外部命令
//        return true;
// }
// Node* parent = cur->_parent;
// if (cur->_key > key)
// {
// parent = cur;
// cur = cur->_left;
// }
// else if (cur->_key < key)
// {
// parent = cur;
// cur = cur->_right;
// }
// else
// {
// return false;
// }
// cur = new Node(key);
// if (parent->_key > key)
// {
// parent->_left=cur;
// }
// else
// {
// parent->_right=cur;
// }
//}
bool InsertR(const K&key)
{
return _InsertR(_root, key);
}
bool _InsertR(Node*& root,const K key)//递归插入
{
if (root == NULL)
{
root = new Node(key);
return true;
}
if (root->_key > key)
{
return _InsertR(root -> _left, key);
}
else if (root->_key < key)
{
return _InsertR(root->_right, key);
}
else
{
return false;
}
}
bool RemoveR(const K& key)//递归删除
{
return _RemoveR(_root, key);
}
bool _RemoveR(Node*& root, const K& key)
{
if (root == NULL)
{
return false;
}
else if (root->_key > key)
{
return _RemoveR(root->_left, key);
}
else if (root->_key < key)
{
return _RemoveR(root->_right, key);
}
else
{
//删除
Node* del = root;
if (root->_left == NULL)
{
root = root->_right;
}
else if (root->_right == NULL)
{
root = root->_left;
}
else
{
Node* sub = root->_right;
while (sub->_left)
{
sub = sub->_left;
}
root->_key = sub->_key;
return _RemoveR(root->_right, sub->_key);
}
delete del;
return true;
}
}
Node* Find(const K& key)//查找
{
Node* cur = _root;
while (cur)
{
if (cur->_key > key)
{
cur = cur->_left;
}
else if (cur->_key < key)
{
cur = cur->_right;
}
else
{
return cur;
}
}
return NULL;
}
bool Remove(const K& key)//删除
{
Node* parent = NULL;
Node* cur = _root;
while (cur)
{
if (cur->_key > key)
{
parent = cur;
cur = cur->_left;
}
else if (cur->_key < key)
{
parent = cur;
cur = cur->_right;
}
else//删除//1、左为空//2、右为空//3、左右都不为空
{
Node* del = cur;
if (cur->_left == NULL)
{
if (parent == NULL)
{
_root=cur->_right;
}
else
{
if (parent->_right == cur)//若删除过多,父亲为空,进不去了,加上面三行
{
parent->_right = cur->_right;
}
else
{
parent->_left = cur->_right;
}
}
}
else if(cur->_right == NULL)
{
if (parent == NULL)
{
_root=cur->_left;
}
else
{
if (parent->_left == cur)
{
parent->_left = cur->_left;
}
else
{
parent->_right = cur->_left;
}
}
}
else//左右都不为空//替换法删除//先找右树的最左节点或者左树的最右节点
{
Node* parent = cur;//不能为空,如果右子树没有左子树,就进不去while,parent就不能更新,所以parent不能为空
Node* sub = cur->_right;//该句至关重要
while (sub->_left)//sub的左存在,不存在说明就到了去往右树最左节点的//岔路口
{
parent = sub;
sub = sub->_left;//向右树的最左节点走
}//最左节点不一定是叶子节点,但他一定是左为空,例如节点1//最左节点也有可能是根
del = sub;
cur->_key = sub->_key;
if(parent->_left == sub)
{
parent->_left = sub->_right;
}
else
{
parent->_right = sub->_right;
}
}
delete del;
return true;
}
}
return false;
}
void InOrder()
{
_InOrder(_root);
}
void _InOrder(Node* root)
{
if (root == NULL)
{
return;
}
_InOrder(root->_left);
cout << root->_key<<" ";
_InOrder(root->_right);
}
protected:
Node* _root;
};


//void TestBSTree()
//{
// int a[] = { 5, 3, 4, 1, 7, 8, 2, 6, 0, 9 };
// BinarySearchTree<int> t;
// for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); ++i)
// {
// t.Insert(a[i]);
// }
// t.InOrder();
// cout << endl;
//
// //BinarySearchTree t1(t);
//
//
// // 测试情况 
// // 1. 左为空/右为空 
// // 2. 左右都不为空 
// /*t.Remove(8);
// t.Remove(2);
// t.Remove(1);
// t.Remove(5);
// t.InOrder();
//*/
// // 相不到情况 
// t.Remove(0);
// t.Remove(1);
// t.Remove(2);
// t.Remove(3);
// t.Remove(4);
// t.Remove(5);
// t.Remove(6);
// t.Remove(7);
// t.Remove(9);
// t.InOrder();
//
// //t1.InOrder();
//}

void TestBSTreeR()
{
int a[] = { 5, 3, 4, 1, 7, 8, 2, 6, 0, 9 };
BinarySearchTree<int> t;
for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); ++i)
{
t.InsertR(a[i]);
}
t.InOrder();
cout << endl;
//BinarySearchTree<int> t1(t);

// 测试情况 
// 1. 左为空/右为空 
// 2. 左右都不为空 
//t.RemoveR(8);
t.RemoveR(2);
t.RemoveR(1);
t.RemoveR(5);
t.InOrder();
cout << endl;
// 相不到情况 
t.RemoveR(0);
t.RemoveR(1);
t.RemoveR(2);
t.RemoveR(3);
t.RemoveR(4);
t.RemoveR(5);
t.RemoveR(6);
t.RemoveR(7);
t.RemoveR(9);
t.RemoveR(10);
t.InOrder();
cout << endl;

}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值