AVL树呢,是平衡树中一个非常经典的例子。因为普通的查找树在插入和删除的过程有可能会产生树的一端子树高度比另一边大很多的情况,也就是所谓的退化为链表(查找是一个一个节点去找),降低了查找的效率。
AVL平衡树通过一系列旋转的方式让左子树和右子树的高度相差不大(<=1),这样搜索的效率将会维持在较好的水平。
方法就是当插入一个节点之后,
更新父节点的高度,判断父节点的左右子树高度差是否为2,若是,进行相应旋转操作(4种)来降低左右子树高度差。若不是,判断父节点的父的左右子树高度差是否为2,以此类推,直到根节点(当然是递归中完成)。
单左旋,单右旋,左右旋,右左旋就是将3个节点间调整次序来,代码如下,具体样子就不画图了,在这些点调节次序的过程中,我们可以发现搜索树节点大小顺序还是正常排列的。
也就是中序遍历的结果还是1234567这样从小到大排列。
avl_tree.h
#ifndef _Avltree_h
#define _Avltree_h
#define Max(a,b) ((a)>(b)?(a):(b))
struct AvlNode;
typedef struct AvlNode*Position;
typedef struct AvlNode*AvlTree;
typedef int ElementType ;
Position Find(ElementType X,AvlTree T);
Position FindMin(AvlTree T);
Position FindMax(AvlTree T);
AvlTree MakeEmpty(AvlTree T);
AvlTree Insert(ElementType X,AvlTree T);
void InOrder_2(AvlTree T,int depth);
int PostOrder_2(AvlTree T,int depth);
void PreOrder_2(AvlTree T,int depth);
void PreOrder(AvlTree T);
void InOrder(AvlTree T);
void PostOrder(AvlTree T);
struct AvlNode
{
ElementType Element;
AvlTree Left;
AvlTree Right;
int Height;
};
#endif
avl_tree.c
#include<stdio.h>
#include<stdlib.h>
#include"avl_tree.h"
static Position SingleRotateWithLeft(Position K2);
static Position DoubleRotateWithLeft(Position K3);
static Position SingleRotateWithRight(Position K2);
static Position DoubleRotateWithRight(Position K3);
static int Height (Position P);
static Position SingleRotateWithLeft(Position K2)
{
// puts("右旋");
Position K1;
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;
return K1;
}
static Position DoubleRotateWithLeft(Position K3