#pragma once
#include
using namespace std;
#define NEG -1
#define ZERO 0
#define POS 1
template
struct AVLTreeNode//樹的節(jié)點(diǎn)
{
K _key;
V _value;
AVLTreeNode* _left;
AVLTreeNode* _right;
AVLTreeNode* _parent;
int _bf;
AVLTreeNode(const K& key,const V& value)
:_key(key)
, _value(value)
, _left(NULL)
, _right(NULL)
, _parent(NULL)
, _bf(0)//平衡因子 取值 -1 0 1 (左高1 相等 右高1)
{}
};
template
class AVLTree
{
typedef AVLTreeNode Node;
public:
AVLTree()
:_root(NULL)
{}
~AVLTree(){}
bool Insert(const K& key,const V& value)//插入
{
if (_root == NULL)
{
_root = new Node(key,value);//空樹 直接插入
return true;
}
Node* cur = _root, *prev = NULL;//當(dāng)前 與 之前 節(jié)點(diǎn)指針
while (cur){
if (cur->_key < key)//插入key 比當(dāng)前節(jié)點(diǎn) key大 跳到右
{
if (cur->_right){//右不為空繼續(xù)
prev = cur;
cur = cur->_right;
if (cur->_bf == ZERO)//如果節(jié)點(diǎn)的bf為0,說明插入(如果成功),會改變prev->bf的值
prev->_bf++;
}
else
{//如果右為空 到達(dá)插入節(jié)點(diǎn)位置,插入cur->bf ++
cur->_right = new Node(key,value);
cur->_right->_parent = cur;
cur->_bf++;
break;
}
}
else if (cur->_key>key)//同理 向左 插入
{
if (cur->_left){
prev = cur;
cur = cur->_left;
if (cur->_bf == ZERO)
prev->_bf--;
}
else
{
cur->_left = new Node(key, value);
cur->_left->_parent = cur;
cur->_bf--;
break;
}
}
else//key相等,插入失敗,依次將改變的平衡因子 改回來
{
while (prev&&cur->_bf == ZERO)
{
if (prev->_left == cur)
prev->_bf++;
else
prev->_bf--;
cur = prev;
prev = prev->_parent;
}
return false;
}
}
//插入結(jié)束 對整棵樹進(jìn)行調(diào)節(jié) 使其繼續(xù)平衡
//高度不變
if (cur->_bf == ZERO)
return true;
else//高度改變
{
//找高度變?yōu)?2 或 2的節(jié)點(diǎn)旋轉(zhuǎn)
while (prev)
{
if (prev->_bf < -1)//左高2
{
if (cur->_bf <= -1)//右旋
{
_RotateR(prev);
cout << "右旋"<_bf > 1)//右高2
{
if (cur->_bf >= 1)//左旋
{
_RotateL(prev);
cout << "左旋" << endl;
break;
}
else//右左旋
{
_RotateR(cur);
_RotateL(prev);
cout << "右左旋" << endl;
break;
}
}
cur = prev;
prev = prev->_parent;
}
}
return true;
}
bool IsBalance()
{
if (_root == NULL)
return true;
return _Isbalance(_root);
}
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)
{
if (_root == NULL)
{
return false;//空樹刪除失敗
}
Node* cur = _root, *prev = NULL;
while (cur){
if (cur->_key < key)//刪除位置在cur 右
{
if (cur->_right){//右非空,繼續(xù)找
prev = cur;
cur = cur->_right;
}
else//右空,未找到刪除節(jié)點(diǎn) 返回
return false;
}
else if (cur->_key>key)//刪除位置在左
{
if (cur->_left){
prev = cur;
cur = cur->_left;
}
else
return false;
}
else
{
Node* parent = cur->_parent;//記錄刪除節(jié)點(diǎn)的 父
if (cur->_left == NULL)//刪除節(jié)點(diǎn) 左空,直接使其右與prev相連
{
if (prev == NULL){//prev為空,刪除根節(jié)點(diǎn),根節(jié)點(diǎn)改變
_root = cur->_right;
delete cur;
return true;
}
if (prev->_right == cur){//prev右為cur,cur的右連到prev右
prev->_bf--;//平衡因子 減少
prev->_right = cur->_right;
if (cur->_right)
cur->_right->_parent = prev;
}
if (prev->_left == cur){//prev左為 cur
prev->_left = cur->_right;
prev->_bf++;
if (cur->_right)
cur->_right->_parent = prev;
}
delete cur;//釋放節(jié)點(diǎn)
cur = prev;//將cur prev指向有效節(jié)點(diǎn)
prev = cur->_parent;
}
else if (cur->_right == NULL)//同上 cur右為空
{
if (prev == NULL){
_root = cur->_left;
delete cur;
return true;
}
if (prev->_right == cur){
prev->_bf--;
prev->_right = cur->_left;
if (cur->_left)
cur->_left->_parent = prev;
}
if (prev->_left == cur){
prev->_left = cur->_left;
prev->_bf++;
if (cur->_left)
cur->_left->_parent = prev;
}
delete cur;
cur = prev;
prev = cur->_parent;
}
else
{//cur左右都非空,為了避免換當(dāng)前root的復(fù)雜操作,替換為刪除cur左孩子 最右 節(jié)點(diǎn) ,或者cur右孩子的 最左 節(jié)點(diǎn),將其內(nèi)容拷貝給cur
Node* tmp = cur;
prev = cur;
cur = cur->_right;
while (cur->_left)//找右樹最左
{
prev = cur;
cur = cur->_left;
}
tmp->_key = cur->_key;
tmp->_value = cur->_value;//拷貝值
if (cur == prev->_left)//調(diào)節(jié)prev bf并將 cur右樹連接到prev
prev->_bf++;
prev->_left = cur->_right;
}
if (cur == prev->_right)//同上
{
prev->_bf--;
prev->_right = cur->_right;
}
tmp = cur;//記錄刪除位置
cur = prev;
parent = cur;//cur prev 指向有效節(jié)點(diǎn)
prev = cur->_parent;
delete tmp;//刪除tmp
}
while (prev &&cur->_bf == ZERO)//刪除節(jié)點(diǎn) 父樹高度可能改變,依次確認(rèn)并修改 bf (cur bf為0 說明是 -1 或 1 變來 高度發(fā)生改變 需修改父節(jié)點(diǎn) bf)
{
if (cur == prev->_left){
prev->_bf++;
}
if (cur == prev->_right)
{
prev->_bf--;
}
cur = prev;
prev = prev->_parent;
}
prev = parent;//prev指向 實(shí)際刪除節(jié)點(diǎn)的父節(jié)點(diǎn)
if (prev->_bf < ZERO)
cur = prev->_left;
if (prev->_bf > ZERO)
cur = prev->_right;
if (prev->_bf == ZERO){
cur = prev;
prev = prev->_parent;
}
break;
}
}
//找高度變?yōu)?2 或 2的節(jié)點(diǎn)旋轉(zhuǎn)
while (prev)
{
if (prev->_bf < -1)//左高2
{
cur = prev->_left;//因?yàn)閯h除一側(cè)節(jié)點(diǎn)可能需要另一側(cè)旋轉(zhuǎn),因此需要對 cur重新賦值
if (cur && (cur->_bf <= -1 || cur->_bf == ZERO))//右旋
{
_RotateR(prev);
if (prev->_left&&prev->_right == NULL)//判斷旋轉(zhuǎn)后 prev的bf
prev->_bf--;
cout << "右旋" << endl;
}
else//左右旋
{
_RotateL(cur);
_RotateR(prev);
cout << "左右旋" << endl;
}
cur = prev->_parent;
prev = cur->_parent;
while (prev&&cur->_bf == ZERO)//依次修改旋轉(zhuǎn)完畢的prev的bf
{
if (cur == prev->_left)
prev->_bf++;
else
prev->_bf--;
cur = prev;
prev = prev->_parent;
}
}
else if (prev->_bf > 1)//右高2
{
cur = prev->_right;
if (cur && (cur->_bf >= 1 || cur->_bf == ZERO))//左旋
{
_RotateL(prev);
cout << "左旋" << endl;
if (prev->_right&&prev->_left == NULL)
prev->_bf++;
}
else//右左旋
{
_RotateR(cur);
_RotateL(prev);
cout << "右左旋" << endl;
}
cur = prev->_parent;
prev = cur->_parent;
while (prev&&cur->_bf == ZERO)
{
if (cur == prev->_left)
prev->_bf++;
else
prev->_bf--;
cur = prev;
prev = prev->_parent;
}
}
cur = prev;
if (prev)
prev = prev->_parent;
}
return true;
}
private:
Node* _root;
int _height(Node* root)
{
if (root == NULL)
return 0;
int left = 1, right =1;
left += _height(root->_left);
right += _height(root->_right);
return left > right ? left : right;
}
bool _Isbalance(Node* root)//判斷 數(shù)是否平衡 bf是否匹配
{
if (root == NULL)
return true;
/*if (root ->_left==NULL&&root->_right==NULL)
return true;*/
bool left = _Isbalance(root->_left);
bool right = _Isbalance(root->_right);
int num1 = 1;
num1+=_height(root->_left);
int num2 = 1;
num2+=_height(root->_right);
if (left == false || right == false)
{
cout << "not balace!" << " key: " << root->_key << "bf: " << root->_bf << endl;
return false;
}
if (num2-num1!=root->_bf)
{
cout << "bf error!" << "key:" << root->_key << "bf: " << root->_bf << "a-b:" << num1-num2 << endl;
return false;
}
if (abs(num1-num2) <= 1)
return true;
return false;
}
//旋轉(zhuǎn)后 bf 調(diào)節(jié)總結(jié):左旋 bf 減小 右旋 bf 增加;sub=2 ,parent變化 3,sub變化 2;sub=1,parent 變化2,sub變化 1;
void _RotateR(Node* parent)//右旋
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
Node* ppNode=parent->_parent;
subL->_right = parent;
parent->_parent = subL;
parent->_left = subLR;
if (subLR)
subLR->_parent = parent;
if (ppNode)
{
if (ppNode->_left == parent)
ppNode->_left = subL;
else
ppNode->_right = subL;
}
else
_root = subL;
subL->_parent = ppNode;//旋轉(zhuǎn)
//修改 bf
if (subL->_bf == -2){
parent->_bf = 1;
subL->_bf=0;
}
else
{
subL->_bf++;
parent->_bf = 0;
}
}
void _RotateL(Node* parent)//左旋
{
Node* subR= parent->_right;
Node* subRL = subR->_left;
Node* ppNode = parent->_parent;
subR->_left = parent;
parent->_parent = subR;
parent->_right = subRL;
if (subRL)
subRL->_parent = parent;
if (ppNode)
{
if (ppNode->_left == parent)
ppNode->_left = subR;
else
ppNode->_right = subR;
}
else
_root = subR;
subR->_parent = ppNode;//以上為左旋轉(zhuǎn)
//以下下修改 bf 值
if (subR->_bf == 2)//右孩子的高度為2 說明旋轉(zhuǎn)前 高度差在右孩子的下方,旋轉(zhuǎn)后parent 右支 沒有可以連接的,高度會降3 從2變?yōu)?1
{
parent->_bf = -1;
subR->_bf = 0;
}
else{ //右孩子高度為1,旋轉(zhuǎn)后高度將2 buf為 0,而右孩子 高度將1;
parent->_bf = 0;
subR->_bf--;
}
}
};
文章標(biāo)題:c++AVLTree(高度平衡的搜索二叉樹)
分享URL:
http://weahome.cn/article/jjcejh.html