首先感谢两位博主的引导:
http://www.cppblog.com/cxiaojia/archive/2012/08/20/187776.html
http://blog.chinaunix.net/uid-24948645-id-3913917.html
以下内容很多是来自上两篇博客的内容,外加自己的实现测试。
AVL树的历史或简介我就不具体描述了,主要讲述以下其实现的原理和测试的结果。
首先要知道的是AVL树对每一个节点都维护着一个平衡因子,要求每个节点的平衡因子为0、-1或1,这样才表示该节点满足平衡。(平衡因子=左子树的高度 - 右子树的高度)
AVL树的节点的每一次插入后,都需要判断该树是否平衡,若不满足,则需要调整。
该测试中树节点的定义结构如下:
struct BSTNode
{
int data;
int height;
BSTNode *lchild;
BSTNode *rchild;
};
对AVL树的调整主要分为以下四种方式(注:调整前后,树的中序遍历结果不变):
1、在K2节点的左孩子(K1)的左子树插入。K1<C<K2
左左调整:
void modifiedLL(BSTNode *&A)
{
BSTNode *B;
B = A->lchild;
A->lchild = B->rchild;
B->rchild = A;
A->height = Max(Height(A->lchild),Height(A->rchild))+1;
B->height = Max(Height(B->lchild),Height(B->rchild))+1;
A = B;
}
2 、在 K2 节点的右孩子( K1 )的右子树插入。 K1<C<K2
右右调整:
void modifiedRR(BSTNode *&A)
{
BSTNode *B;
B = A->rchild;
A->rchild = B->lchild;
B->lchild = A;
A->height = Max(Height(A->lchild),Height(A->rchild))+1;
B->height = Max(Height(B->lchild),Height(B->rchild))+1;
A = B;
}
3、在K3的左孩子(K1)的右子树插入。第一次对K1进行右旋变换,第二次对K3进行左旋变换。
左右调整:
void modifiedLR(BSTNode *&A)
{
modifiedRR(A->lchild);
modifiedLL(A);
}
4、在K3的右孩子(K1)的左子树插入。第一次对K1进行左旋变换,第二次对K3进行右旋变换。
右左调整:
void modifiedRL(BSTNode *&A)
{
modifiedLL(A->rchild);
modifiedRR(A);
}
依次插入节点代码如下:
BSTNode* Insert(BSTNode *A,int dt)
{
if (A== NULL)
{
A = new BSTNode;
A->height = 0;
A->data = dt;
A->lchild = A->rchild = NULL;
}
else
{
if (dt < A->data)
{
A->lchild = Insert(A->lchild,dt);
if (Height(A->lchild)-Height(A->rchild)==2)
{
if (dt < A->lchild->data)
{
modifiedLL(A);
}
else
{
modifiedLR(A);
}
}
}
else
if(dt > A->data)
{
A->rchild = Insert(A->rchild,dt);
if (Height(A->rchild)-Height(A->lchild)==2)
{
if (dt > A->rchild->data)
{
modifiedRR(A);
}
else
{
modifiedRL(A);
}
}
}
}
A->height = Max(Height(A->lchild),Height(A->rchild))+1;
return A;
}
最后附上本次创建AVL树的测试结果:
(测试的内容为对16个输入的数据创建AVL树,然后打印出其中序、先序遍历结果)
下图为中序、先序遍历结果最终确定的二叉树形态: