包含,插入,單旋轉,雙旋轉,以及每次都要想好久的,除了結點裏指針的其餘的指針都想不清楚......又想了一遍......
//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);
}
};