包含,插入,单旋转,双旋转,以及每次都要想好久的,除了结点里指针的其余的指针都想不清楚......又想了一遍......
//AVL,二叉平衡树,任何一个结点,左右子树的高度差都不大于1的二叉搜索树
template <typename Comparable>
struct AvlNode
{
Comparable element;
AvlNode *left;
AvlNode *right;
int height;
AvlNode(const Comparable & theElement, AvlNode *lt, AvlNode *rt, int h = 0) :element(theElement), left(lt), right(rt), height(h)
int height(AvlNode *t) const
{
return t == NULL ? -1 : t->height; //AVL中,NULL高度设为1,这样叶子结点就是0了,然后上面的高度就都可以算了
}
void insert(const Comparable & x, AvlNode * & t) //把x插入到以t为根结点的树上
{
if (t == NULL)
t = new AvlNode(x, NULL.NULL);
else if (x < t->element)
{
insert(x, t->left); //插入
if (height(t->left) - height(t->right) == 2) //调整
{
if (x < t->left->element)
rotateWithLeftChild(t); //值小于t->left的,单旋转
else
DoubleWithLeftChild(t); //值介于t和t->left之间,双旋转
}
}
else if (x > t->element)
{
insert(x, t->right); //插入
if (height(t->right) - height(t->left) == 2) //调整
{
if (x > t->right->element)
rotateWithRightChild(t); //值小于t->left的,单旋转
else
DoubleWithRightChild(t); //值介于t和t->left之间,双旋转
}
}
else; //什么都不干
t->height = max(height(t->left), height(t->right)) + 1; //计算树的新高度
}
//一共四种旋转,原理上只有两类(LL,RR;LR,RL),但是代码是4类,这里实现两类(LL,LR),左右是对称的。(LL和RR,用单旋转,LR和RL,用双旋转,不过用单旋转还是双旋转,就按照代码里写的判定吧)
//这个单旋转的逻辑,参见《数据结构与算法分析C++描述第三版》,双旋转感觉它说的不好,但是看它给的代码实现加上嵌在代码实现里的例子,就很明白了
void rotateWithLeftChild(AvlNode * & k2) //还是那个*和Node的问题,k2就理解成拎着结点的小棍棍,第一行是再弄一个小棍棍拎着k2->left这个小棍棍拎着的结点,叫做k1;然后最后的一行,意思是让k2不要拎着现在的结点了,让它拎着新的根结点
{
AvlNode *k1 = k2->left;
k2->left = k1->right;
k1->right = k2;
k2->height = max(height(k2->left), height(k2->right)) + 1;
k1->height = max(height(k1->left), k2->height) + 1;
k2 = k1;
}
void DoubleWithLeftChild(AvlNode * & k3)
{
rotateWithRightChild(k3->left);
rotateWithLeftChild(k3);
}
};