#include "iostream"
#include "cmath"
using namespace std;
//首先分析了这几种旋转,发现都和平衡因子有关系,当一个结点平衡因子为2的时候,就该旋转了。
/*左旋之后,K1子节点的右枝上如果有结点给予K2,左枝上的结点保持不变;
右旋之后,K1子节点的左枝上如果有结点给予K2,右枝上的结点保持不变。*/
template<class T>
class avlTree
{
public:
avlTree();
avlTree(const avlTree &rhs);
~avlTree();
const avlTree<T> &operator=(const avlTree &rhs);
//int Balance(avlNode *t); //隐含了一个类嵌套的问题,就是私有类的位置问题。BAB OR ABA
void insert(const T &x);
void remove(const T &x);
void inOrderPrint();
private:
struct avlNode
{
T element;
avlNode *left;
avlNode *right;
int height;
avlNode(const T &theElement, avlNode *lt, avlNode *rt, int h = 0)
:element(theElement), left(lt), right(rt), height(h){}
};
avlNode *root;
void RR(avlNode *k2);
void LL(avlNode *k2);
void LR(avlNode *k2);
void RL(avlNode *k2);
void insert(const T &x, avlNode * &root); //结点比较的插入
void remove(const T &x, avlNode * &root);
void inOrderPrint(avlNode * root);
public:
int height(avlNode *t);
};
template<class T>
avlTree<T>::avlTree()
{
root = NULL;
}
template<class T>
avlTree<T>::~avlTree()
{
}
template<class T>
avlTree<T>::avlTree(const avlTree &rhs)
{
root = rhs;
}
template<class T>
const avlTree<T> &avlTree<T>::operator=(const avlTree &rhs)
{
if(this = &rhs)
return *this;
delete root;
root = new avlNode;
root = rhs.root;
return *this;
}
/*if the tree is unbalance ,adjust the smallest unbalance tree to get the balance tree */
/* the smallest unbalance root node is the nearest to the branches nodes*/
template<class T>
int avlTree<T>::height(avlNode *t)
{
return root == NULL ? -1 : root->height;
}
/* case one RR //定义右旋,右旋时K2的左孩子一定不为空。 //外侧插入
* 80 ← k2 60
* /\ /\
* k1→ 60 90 → 20 80
* / \ / /\
* 20 75 ? 75 90
* /
* ?
*/
template<class T>
void avlTree<T>::RR(avlNode *k2) //the t node is unbalance node
{
avlNode *k1 = k2->left;
k2->left = k1->right;
k1->right = k2;
k2->height = max(height(k2->right), height(k2->left)) + 1;
k1->height = max(height(k1->left), k2->height) + 1;
k2 = k1;
}
/* case two LL //定义左旋,左旋时,k2的右孩子一定不为空 //外侧插入
* k2→ 100 120
* /\ /\
* 85 120 ←k1 → 100 130
* / \ / \ \
* 110 130 85 110 ?
* \
* ?
*/
template<class T>
void avlTree<T>::LL(avlNode *k2)
{
avlNode *k1; //enter the tree
k1 = k2->right;
k2->right = k1->left;
k1->left = k2;
k2->height = max(height(k2->right), height(k2->left)) + 1;
k1->height = max(height(k2->right), k2->height) + 1;
k2 = k1;
}
/* case three RL //内测插入 //r有个孩子不为空
* the detal can contain two cases
* first
*
* LL RR
* 100 → p → 100 → 90
* /\ /\ /\
* p → 80 120 l → 90 120 80 100
* /\ / /\ \
* 60 90 ← r 80 60 85 120
* / /\ /
* 85 60 85 ?
* / /
* ? ?
*/
template<class T>
void avlTree<T>::RL(avlNode *k2)
{
LL(k2->left);
RR(k2);
}
/* case four LR //内测插入 //r有个孩子不为空
* the detal can contain two cases
* 右旋 左旋
* 80 → 80 ← p → 85
* /\ /\ /\
* 60 100 ← p 60 85 ← r 80 100
* /\ \ / /\
* l →85 120 100 60 90 120
* \ /\ /
* 90 90 120 ?
* / /
* ? ?
*/
template<class T>
void avlTree<T>::LR(avlNode *k2)
{
RR(k2->right);
LL(k2);
}
//插入策略,插完调整
/* 在特殊情况时 //特殊情况先左旋为正常情况在进行右旋。
* 39 <-k2 LL 39 <-k2 RR 30 <-r
* / / /\
* k1-> 20 ---> r-> 30 ---> k1-> 20 39 <-k2
* \ /
* r-> 30 k1-> 20
*/
template<class T>
void avlTree<T>::insert(const T &x)
{
insert(x, root);
}
template<class T>
void avlTree<T>::insert(const T &x, avlNode * &root)
{
if(root == NULL) //如果根树为block,and then insert at there
root = new avlNode(x, NULL, NULL);
else if(x < root->element) //左子树上插入
{
insert(x, root->left);
if(height(root->left) - height(root->right) == 2)
if(x < root->left->element)
RR(root);
else //上述特殊情况下的插入
LR(root);
}
else if(x > root->element)
{
insert(x, root->right);
if((height(root->right) - height(root->left)) == 2)
if(x > root->right->element)
LL(root);
else
RL(root);
}
else
;
root->height = max(height(root->left), height(root->right)) + 1; //旋转之后,现在找到左孩子和右孩子的高度,然后定义自己的高度
}
//删除策略,将要删的右子结点的最小节点值给了删的那个root->element
/* 在特殊情况时
* 39 <-root 30
* / \ / \
* 20 49 ---> 20 49
* /
* 30 delete:30
*/
template<class T>
void avlTree<T>::remove(const T &data) //删除结点
{
remove(data, root);
}
template<class T>
void avlTree<T>::remove(const T &data, avlNode * &root)
{
if(root == NULL) //此节点不存在,
return;
if(data < root->element) //左子树上进行删除
{
remove(data, root->left); //循环找到那个结点
if(height(root->right) - height(root->left) == 2)
{
if(root->right->left != NULL && (height(root->right->left) > height(root->right->right)))
RL(root);
else
RR(root);
}
}
else if(data > root->element) //右子树上进行删除
{
remove(data, root->right);
if(height(root->left) - height(root->right) == 2)
{
if((root->left->right) != NULL && (height(root->left->right) > height(root->left->left)))
LR(root);
else
LL(root);
}
}
else if(data == root->element) //这个结点上的删除
{
if(root->right != NULL && root->left != NULL) //两个子节点都存在
{
avlNode *temp = root->right;
while(temp != NULL) temp = temp->left; //将右子结点的最小值替换root
root->element = temp->element;
remove(root->element, root->right); //再将那个最小的值清除
if(height(root->left) - height(root->right) == 2)
{
if(root->left->right != NULL && height(root->left->right) > height(root->left->left))
RL(root);
else
LL(root);
}
}
else //只存在一个子节点或不存在子节点
{
avlNode *temp = root;
if(root->left == NULL) //只有右结点,将其作为根结点
root = root->right;
else if(root->right == NULL)
root = root->left;
delete temp;
temp = NULL;
}
}
if(root == NULL) return;
root->height = max(height(root->left), height(root->right)) + 1; //重设高度
return;
}
template<class T>
void avlTree<T>::inOrderPrint() //中序遍历输出
{
inOrderPrint(root);
}
template<class T>
void avlTree<T>::inOrderPrint(avlNode * root)
{
if(root == NULL)
return;
if(root->left)
inOrderPrint(root->left);
cout << root->element << " ";
if(root->right)
inOrderPrint(root->right);
return;
}
int main()
{
avlTree<int> tree;
tree.insert(20);
tree.insert(30);
tree.insert(25);
tree.remove(25);
tree.inOrderPrint();
return 0;
}
(四)数据结构-平衡二叉树
最新推荐文章于 2024-09-10 21:01:04 发布