- #include <stdio.h>
#include <stdlib.h>
typedef struct node *position;
typedef int ElementTP;
struct node {
int depth;
position parent;
ElementTP element;
position lchild;
position rchild;
};
/* pointer => root node of the tree */
typedef struct node *TREE;
position insert_value(TREE, ElementTP);
int depth(TREE);
static void insert_node_to_nonempty_tree(TREE, position);
static void update_root_depth(TREE);
static TREE recover_avl(TREE, position);
static int depth_diff(TREE);
static position insert_leaf(TREE, ElementTP);
static void insert_node_to_nonempty_tree(TREE, position);
static TREE left_single_rotate(TREE);
static TREE left_double_rotate(TREE);
static TREE right_single_rotate(TREE);
static TREE right_double_rotate(TREE);
int main(void)
{
TREE tr;
position np;
ElementTP element;
tr = NULL;
tr = insert_value(tr, 18);
tr = insert_value(tr, 5);
printf("root: %d\n", tr->element);
printf("depth: %d\n", depth(tr));
tr = insert_value(tr, 2);
printf("root: %d\n", tr->element);
printf("depth: %d\n", depth(tr));
tr = insert_value(tr, 4);
printf("root: %d\n", tr->element);
printf("depth: %d\n", depth(tr));
printf("root->lchild: %d\n", tr->lchild->element);
tr = insert_value(tr, 3);
printf("root: %d\n", tr->element);
printf("depth: %d\n", depth(tr));
printf("root->lchild: %d\n", tr->lchild->element);
printf("root->lchild->lchild: %d\n", tr->lchild->lchild->element);
}
/*
* insert value
*
*/
position insert_value(TREE tr, ElementTP value)//插入叶子节点
{
position New;
/* insert a value to a binary search tree */
New = insert_leaf(tr, value);
update_root_depth(New);
if (tr == NULL) {
tr = New;
}
else {
tr = recover_avl(tr, New);
}
return tr;
}
/*
* get the depth of the tree
* use this function to access depth
*/
int depth(TREE tr) {
if (tr == NULL) {
return 0;
}
else {
return tr->depth;
}
}
//========================================
// static functions: for internal use
/*
* traverse the path from new node to root node
* make one rotation, recover AVL and stop
*/
static TREE recover_avl(TREE tr, position np)
{
int myDiff;
while (np != NULL) {
update_root_depth(np);
myDiff = depth_diff(np);
if (myDiff > 1 || myDiff < -1) {
if (myDiff > 1) {
/* left rotate needed */
if(depth_diff(np->rchild) > 0) {
np = left_single_rotate(np);
}
else {
np = left_double_rotate(np);
}
}
if (myDiff < -1) {
if(depth_diff(np->lchild) < 0) {
np = right_single_rotate(np);
}
else {
np = right_double_rotate(np);
}
}
/* if rotation changes root node */
if (np->parent == NULL) tr = np;
break;
}
np = np->parent;
}
return tr;
}
/*
* difference of rchild->depth and lchild->depth
*/
static int depth_diff(TREE tr)
{
if (tr == NULL) {
return 0;
}
else {
return depth(tr->rchild) - depth(tr->lchild);
}
}
/*
* left single rotation
* return the new root
*/
static TREE left_single_rotate(TREE tr)
{
TREE newRoot, parent;
parent = tr->parent;
newRoot = tr->rchild;
/* detach & attach */
if (newRoot->lchild != NULL) newRoot->lchild->parent = tr;
tr->rchild = newRoot->lchild;
update_root_depth(tr);
/* raise new root node */
newRoot->lchild = tr;
newRoot->parent = parent;
if (parent != NULL) {
if (parent->lchild == tr) {
parent->lchild = newRoot;
}
else {
parent->rchild = newRoot;
}
}
tr->parent = newRoot;
update_root_depth(newRoot);
return newRoot;
}
/*
* right single rotation
* return the new root
*/
static TREE right_single_rotate(TREE tr)
{
TREE newRoot, parent;
parent = tr->parent;
newRoot = tr->lchild;
/* detach & attach */
if (newRoot->rchild != NULL) newRoot->rchild->parent = tr;
tr->lchild = newRoot->rchild;
update_root_depth(tr);
/* raise new root node */
newRoot->rchild = tr;
newRoot->parent = parent;
if (parent != NULL) {
if (parent->lchild == tr) {
parent->lchild = newRoot;
}
else {
parent->rchild = newRoot;
}
}
tr->parent = newRoot;
update_root_depth(newRoot);
return newRoot;
}
/*
* left double rotation
* return
*/
static TREE left_double_rotate(TREE tr)
{
right_single_rotate(tr->rchild);
return left_single_rotate(tr);
}
/*
* right double rotation
* return
*/
static TREE right_double_rotate(TREE tr)
{
left_single_rotate(tr->lchild);
return right_single_rotate(tr);
}
/*
* update tr->depth
* assume lchild->depth and rchild->depth are correct
*/
static void update_root_depth(TREE tr)
{
int maxChildDepth;
int depLChild, depRChild;
if (tr==NULL) return;
else {
depLChild = depth(tr->lchild);
depRChild = depth(tr->rchild);
maxChildDepth = depLChild > depRChild ? depLChild : depRChild;
tr->depth = maxChildDepth + 1;
}
}
/*
* insert a new value into the tree as a leaf
* return address of the new node
*/
static position insert_leaf(TREE tr, ElementTP value)
{
position np;
/* prepare the node */
np = (position) malloc(sizeof(struct node));
np->element = value;
np->parent = NULL;
np->lchild = NULL;
np->rchild = NULL;
if (tr != NULL) {
insert_node_to_nonempty_tree(tr, np);
}
return np;
}
/*
* insert a node to a non-empty tree
* called by insert_value()
*/
static void insert_node_to_nonempty_tree(TREE tr, position np)
{
/* insert the node */
if(np->element <= tr->element) {
if (tr->lchild == NULL) {
/* then tr->lchild is the proper place */
tr->lchild = np;
np->parent = tr;
return;
}
else {
insert_node_to_nonempty_tree(tr->lchild, np);
}
}
else if(np->element > tr->element) {
if (tr->rchild == NULL) {
tr->rchild = np;
np->parent = tr;
return;
}
else {
insert_node_to_nonempty_tree(tr->rchild, np);
}
}
}
输出如下:
root: 18
depth: 2
root: 5
depth: 2
root: 5
depth: 3
root->lchild: 2
depth: 3
root->lchild: 3
root->lchild->lchild: 2
模板二:
#ifndef HEAD_H_
#define HEAD_H_
#include <stdio.h>
#include <stdlib.h>
typedef int ElementType;
typedef struct AvlNode // AVL树的节点
{
ElementType data;
struct AvlNode *left; // 左孩子
struct AvlNode *right; // 右孩子
int Height;
}*Position,*AvlTree;
AvlTree MakeEmpty(AvlTree T);
Position Find(ElementType x,AvlTree T);
Position FindMin(AvlTree T);
Position FindMax(AvlTree T);
AvlTree Insert(ElementType x,AvlTree T);
AvlTree Delete(ElementType x,AvlTree T);
ElementType Retrieve(Position P);
void Display(AvlTree T);
#endif /* HEAD_H_ */
/*
* 初始化AVL树
*/
AvlTree MakeEmpty(AvlTree T)
{
if( T != NULL)
{
MakeEmpty(T->left);
MakeEmpty(T->right);
free(T);
}
return NULL;
}
/*
* 查找 可以像普通二叉查找树一样的进行,所以耗费O(log n)时间,因为AVL树总是保持平衡的。
* 不需要特殊的准备,树的结构不会由于查找而改变。(这是与伸展树查找相对立的,它会因为查找而变更树结构。)
*/
Position Find(ElementType x,AvlTree T)
{
if(T == NULL)
return NULL;
if(x < T->data)
return Find(x,T->left);
else if(x > T->data)
return Find(x,T->right);
else
return T;
}
/*
* FindMax,FindMin 查找最大和最小值,
*/
Position FindMin(AvlTree T)
{
if(T == NULL)
return NULL;
if( T->left == NULL)
return T;
else
return FindMin(T->left);
}
Position FindMax(AvlTree T)
{
if(T != NULL)
while(T->right != NULL)
T=T->right;
return T;
}
/*
* 返回节点的高度
*/
static int Height(Position P)
{
if(P == NULL)
return -1;
else
return P->Height;
}
static int Max(int h1,int h2)
{
return h1 > h2 ?h1:h2;
}
/*
* 此函数用于k2只有一个左孩子的单旋转,
* 在K2和它的左孩子之间旋转,
* 更新高度,返回新的根节点
*/
static Position SingleRotateWithLeft(Position k2) // LL旋转
{
Position k1;
k1=k2->left;
k2->left=k1->right;
k1->right=k2;
// 因为比较的是左右孩子的高度,所以求父节点的高度要加1
k2->Height=Max(Height(k2->left),Height(k2->right)) + 1;
k1->Height=Max(Height(k1->left),Height(k2->right)) + 1;
return k1;
}
/*
* 此函数用于k1只有一个右孩子的单旋转,
* 在K1和它的右孩子之间旋转,
* 更新高度,返回新的根节点
*/
static Position SingleRotateWithRight(Position k1) // RR旋转
{
Position k2;
k2=k1->right;
k1->right=k2->left;
k2->left=k1;
/*结点的位置变了, 要更新结点的高度值*/
k1->Height=Max(Height(k1->left),Height(k1->right)) + 1;
k2->Height=Max(Height(k2->left),Height(k2->right)) + 1;
return k2;
}
/*
* 此函数用于当 如果 k3有一个左孩子,以及
* 它的左孩子又有右孩子,执行这个双旋转
* 更新高度,返回新的根节点
*/
static Position DoubleRotateLeft(Position k3) // LR旋转
{
//在 k3 的左孩子,执行右侧单旋转
k3->left=SingleRotateWithRight(k3->left);
// 再对 k3 进行 左侧单旋转
return SingleRotateWithLeft(k3);
}
/*
* 此函数用于当 如果 k4有一个右孩子,以及
* 它的右孩子又有左孩子,执行这个双旋转
* 更新高度,返回新的根节点
*/
static Position DoubleRotateRight(Position k4) // RL旋转
{
//在 k4 的右孩子,执行左侧单旋转
k4->right = SingleRotateWithLeft(k4->right);
// 再对 k4 进行 右侧单旋转
return SingleRotateWithRight(k4);
}
/*
* 向AVL树插入可以通过如同它是未平衡的二叉查找树一样把给定的值插入树中,
* 接着自底向上向根节点折回,于在插入期间成为不平衡的所有节点上进行旋转来完成。
* 因为折回到根节点的路途上最多有1.5乘log n个节点,而每次AVL旋转都耗费恒定的时间,
* 插入处理在整体上耗费O(log n) 时间。
*/
AvlTree Insert(ElementType x,AvlTree T)
{
//如果T不存在,则创建一个节点树
if(T == NULL)
{
T = (AvlTree)malloc(sizeof(struct AvlNode));
{
T->data = x;
T->Height = 0;
T->left = T->right = NULL;
}
}
// 如果要插入的元素小于当前元素
else if(x < T->data)
{
//递归插入
T->left=Insert(x,T->left);
//插入元素之后,若 T 的左子树比右子树高度 之差是 2,即不满足 AVL平衡特性,需要调整
if(Height(T->left) - Height(T->right) == 2)
{
//把x插入到了T->left的左侧,只需 左侧单旋转
if(x < T->left->data)
T = SingleRotateWithLeft(T); // LL旋转
else
// x 插入到了T->left的右侧,需要左侧双旋转
T = DoubleRotateLeft(T); // LR旋转
}
}
// 如果要插入的元素大于当前元素
else if(x > T->data)
{
T->right=Insert(x,T->right);
if(Height(T->right) - Height(T->left) == 2)
{
if(x > T->right->data)
T = SingleRotateWithRight(T); //RR 旋转
else
T = DoubleRotateRight(T); //RL旋转
}
}
T->Height=Max(Height(T->left),Height(T->right)) + 1;
return T;
}
/*
* 对单个节点进行的AVL调整
*/
AvlTree Rotate(AvlTree T)
{
if(Height(T->left) - Height(T->right) == 2)
{
if(Height(T->left->left) >= Height(T->left->right))
T = SingleRotateWithLeft(T); // LL旋转
else
T = DoubleRotateLeft(T); // LR旋转
}
if(Height(T->right) - Height(T->left) == 2)
{
if(Height(T->right->right) >= Height(T->right->left))
T = SingleRotateWithRight(T); // RR旋转
else
T = DoubleRotateRight(T); // RL旋转
}
return T;
}
/*
* 首先定位要删除的节点,然后用该节点的右孩子的最左孩子替换该节点,
* 并重新调整以该节点为根的子树为AVL树,具体调整方法跟插入数据类似
* 删除处理在整体上耗费O(log n) 时间。
*/
AvlTree Delete(ElementType x,AvlTree T)
{
if(T == NULL)
return NULL;
if(T->data == x) // 要删除的 x 等于当前节点元素
{
if(T->right == NULL ) // 若所要删除的节点 T 的右孩子为空,则直接删除
{
AvlTree tmp = T;
T = T->left;
free(tmp);
}
else /* 否则找到 T->right 的最左儿子代替 T */
{
AvlTree tmp = T->right;
while(tmp->left)
tmp=tmp->left;
T->data = tmp->data;
/* 对于替代后的T 即其字节点进行调整*/
T->right = Delete(T->data,T->right);
T->Height = Max(Height(T->left),Height(T->right))+1;
}
return T;
}
else if(x > T->data) // 要删除的 x 大于当前节点元素,在T的右子树中查找删除
{
T->right=Delete(x,T->right);
}
else // 要删除的 x 小于当前节点元素,在T的左子树中查找删除
{
T->left=Delete(x,T->left);
}
/*
* 当删除元素后调整平衡
*/
T->Height=Max(Height(T->left),Height(T->right)) + 1;
if(T->left != NULL)
T->left = Rotate(T->left);
if(T->right != NULL)
T->right = Rotate(T->right);
if(T)
T=Rotate(T);
return T;
}
/*
* 返回当前位置的元素
*/
ElementType Retrieve(Position P)
{
return P->data;
}
/*
* 遍历输出
*/
void Display(AvlTree T)
{
static int n=0;
if(NULL != T)
{
Display(T->left);
printf("[%d] ndata=%d \n",++n,T->data);
Display(T->right);
}
}
#define N 15
int main(void) {
AvlTree T=NULL;
int i;
int j = 0;
T = MakeEmpty( NULL );
for( i = 0; i < N; i++, j = ( j + 7 ) % 50 )
{
printf("j=%d \n",j);
T = Insert( j, T );
}
puts("插入 4 \n");
T = Insert( 4, T );
Display(T);
for( i = 0; i < N; i += 2 )
{
printf("delelte: %d \n",i);
T = Delete( i, T );//删除元素为i的节点
}
printf("detele:\n");
printf("height=%d \n",T->Height);
Display(T);
printf( "Min is %d, Max is %d\n", Retrieve( FindMin( T ) ),
Retrieve( FindMax( T ) ) );
return 0;
}
输出:
j=0
j=7
j=14
j=21
j=28
j=35
j=42
j=49
j=6
j=13
j=20
j=27
j=34
j=41
j=48
插入 4
[1] ndata=0
[2] ndata=4
[3] ndata=6
[4] ndata=7
[5] ndata=13
[6] ndata=14
[7] ndata=20
[8] ndata=21
[9] ndata=27
[10] ndata=28
[11] ndata=34
[12] ndata=35
[13] ndata=41
[14] ndata=42
[15] ndata=48
[16] ndata=49
delelte: 0
delelte: 2
delelte: 4
delelte: 6
delelte: 8
delelte: 10
delelte: 12
delelte: 14
detele:
height=3
[17] ndata=7
[18] ndata=13
[19] ndata=20
[20] ndata=21
[21] ndata=27
[22] ndata=28
[23] ndata=34
[24] ndata=35
[25] ndata=41
[26] ndata=42
[27] ndata=48
[28] ndata=49
Min is 7, Max is 49