二叉搜索树的特点:
1. 每个节点都有一个作为搜索依据的关键码(key),所有节点的关键码互不相同。
2. 左子树上所有节点的关键码(key)都小于根节点的关键码(key)。
3. 右子树上所有节点的关键码(key)都大于根节点的关键码(key)。
4. 左右子树都是二叉搜索树。
一棵二叉搜索树如下图:
平衡二叉树的特点:
左右子树的高度差<=1
无法达到绝对平衡是因为:如果一棵二叉树只有两个节点,则高度差永远差1。
#pragma once
#include<iostream>
#include<stack>
using namespace std;
template <class K, class V>
struct BinarySearchTreeNode
{
K _key;
V _value;
BinarySearchTreeNode<K, V>* _left;
BinarySearchTreeNode<K, V>* _right;
BinarySearchTreeNode(K& k, V& v)
:_key(k)
, _value(v)
, _left(NULL)
, _right(NULL)
{}
};
template <class K, class V>
class BinarySearchTree
{
typedef BinarySearchTreeNode<K, V> Node;
public:
BinarySearchTree()
: _root(NULL)
{}
bool Insert(K key, V val)
{
if (_root == NULL)
{
_root = new Node(key, val);
return true;
}
Node *cur = _root;
Node *prev = NULL; //保存cur的前一个节点
while (cur)
{
if (key < cur->_key)
{
prev = cur;
cur = cur->_left;
}
else if (key > cur->_key)
{
prev = cur;
cur = cur->_right;
}
else //已经存在
return false;
}
Node *node = new Node(key, val);
if (key < prev->_key)
prev->_left = node;
else
prev->_right = node;
return true;
}
Node *Find(const K& key)
{
Node *cur = _root;
while (cur)
{
if (key < cur->_key)
cur = cur->_left;
else if (key > cur->_key)
cur = cur->_right;
else //找到
return cur;
}
return NULL;
}
bool Remove(const K& key)
{
if (_root == NULL)
return false;
if (_root->_left == NULL && _root->_right == NULL)
{
delete _root;
_root = NULL;
return true;
}
Node *cur = _root;
Node *parent = NULL;
while (cur)
{
if (key < cur->_key)
{
parent = cur;
cur = cur->_left;
}
else if (key > cur->_key)
{
parent = cur;
cur = cur->_right;
}
else //找到要删除的key
{
//1、cur的左孩子为空
if (cur->_left == NULL)
{
if (cur != _root)
{
if (parent->_left == cur) //判断cur在parent的左边还是右边
parent->_left = cur->_right;
else
parent->_right = cur->_right;
}
else //删除节点为跟节点并且左子树为空
_root = cur->_right;
}
//2、cur的右孩子为空或左右都为空
else if (cur->_right == NULL)
{
if (cur != _root)
{
if (parent->_left == cur) //判断cur在parent的左边还是右边
parent->_left = cur->_left;
else
parent->_right = cur->_left;
}
else
_root = cur->_left;
}
//2、cur的左右都不为空
if (cur->_left != NULL && cur->_right != NULL)
{
Node *del = cur; //保存要删除的节点
parent = cur;
cur = cur->_right;
while (cur->_left) //找右子树的最左节点
{
parent = cur;
cur = cur->_left;
}
// 将最左节点的值赋给要删除的节点
del->_key = cur->_key;
del->_value = cur->_value;
if (cur == parent->_left)
parent->_left = cur->_right;
else
parent->_right = cur->_right;
}
delete cur;
cur = NULL;
return true;
}
}
return false;
}
bool Insert_R(K& key, V& val)
{
return _Insert_R(_root, key, val);
}
bool Find_R(const K& key)
{
return _Find_R(_root, key);
}
bool Remove_R(const K& key)
{
return _Remove_R(_root, key);
}
void Inorder()
{
_Inorder(_root);
}
bool Isbalance()
{
int depth = 0;
return _Isbalance(_root,depth);
}
int Heigh()
{
return _Height(_root);
}
protected:
//用后序遍历的方式遍历整课二叉树,在遍历到某一节点之后根据它左右节点的深度
//判断当前节点是否平衡,再计算当前节点的深度。知道遍历到根节点
bool _Isbalance(Node*& root, int& depth)
{
if (root == NULL)
{
depth = 0;
return true;
}
int left = 0;
int right = 0;
if (_Isbalance(root->_left, left) && _Isbalance(root->_right, right))
{
if (abs(left - right) <= 1)
{
depth = (left > right ? left + 1 : right + 1);
return true;
}
}
return false;
}
bool _Insert_R(Node *&root, K& key, V& val)
{
if (root == NULL)
{
root = new Node(key, val);
return true;
}
if (key < root->_key)
return _Insert_R(root->_left, key, val);
else if (key > root->_key)
return _Insert_R(root->_right, key, val);
else
return false;
}
bool _Find_R(Node *&root, const K& key)
{
if (root == NULL)
return false;
if (key < root->_key)
return _Find_R(root->_left, key);
else if (key > root->_key)
return _Find_R(root->_right, key);
else
return true;
}
bool _Remove_R(Node *&root, const K& key)
{
if (root == NULL)
return false;
if (key < root->_key)
return _Remove_R(root->_left, key);
else if (key > root->_key)
return _Remove_R(root->_right, key);
else
{
Node *del = root;
if (root->_left == NULL)
root = root->_right;//利用递归的特点
else if (root->_right == NULL)
root = root->_left;
else
{
Node *parent = root;
Node *cur = root;
cur = cur->_right;
while (cur->_left)
{
parent = cur;
cur = cur->_left;
}
root->_key = cur->_key;
root->_value = cur->_value;
del = cur;
if (parent->_left == cur)
parent->_left = cur->_right;
else
parent->_right = cur->_right;
}
delete del;
del = NULL;
return true;
}
}
int _Height(Node *&root)
{
if (root == NULL)
return 0;
int left = _Height(root->_left);
int right = _Height(root->_right);
return (left > right) ? left + 1 : right + 1;
}
//重复遍历,低效
bool _Isbalance(Node*& root)
{
if (root == NULL)
return true;
int left = _Height(root->_left);
int right = _Height(root->_right);
if (abs(left - right) > 1)
return false;
return _Isbalance(root->_left) && _Isbalance(root->_right);
}
void _Inorder(Node* root)
{
//stack<Node*> s;
//Node *cur = root;
//while (cur || !s.empty())
//{
// while (cur)
// {
// s.push(cur);
// cur = cur->_left;
// }
// if (!s.empty())
// {
// Node* top = s.top();
// cout << top->_key << " ";
// s.pop();
// cur = top->_right;
// }
//}
//cout << endl;
if (root == NULL)
return;
if (root)
{
_Inorder(root->_left);
cout << root->_key << " ";
_Inorder(root->_right);
}
}
private:
Node *_root;
};
void Test1()
{
int a[] = { 4, 5, 6, 2, 1, 3 }; BinarySearchTree<int, int> bst; for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++) { bst.Insert_R(a[i], i); } bst.Inorder(); bst.Find_R(9); bst.Find_R(10); /*bst.Remove_R(1); bst.Inorder(); bst.Remove_R(7); bst.Inorder();*/ cout << "Isbalabce ? :" << bst.Isbalance() << endl; }