AVL 树数据结构

以下内容为程序代码:

/* avl.h */
/*
* 高度平衡二*树的一种重要方案。
* 在 1962 年由 G. Adelson-Velsky 和 E. Landis 发明。
*/
typedef int typekey;
typedef struct avlnode {   /* 高度平衡树节点 */
   typekey k;   /* 键 */
   char *v; /* 值 */
   int bal;
   /* 平衡因子,当 bal==[-1,0,1] 时平衡,分别对应于左子树
    * 高过右子树一层,左右子树高度相同,右子树高过左子树一层 */
   struct avlnode *left, *right;   /* 指向子树的指针 */
} node, *tree;
extern tree search(typekey, tree);
extern tree insert(typekey, tree);
extern tree delete(typekey, tree);
extern int height(tree);
extern int count(tree);
extern int deltree(tree);
/* end of avl.h */
/*————————————————————————*/
/* avl.c */
#include <stdlib.h>
#include <stdio.h>
#include “./avl.h”

int incrhei; /* 高度增减标志 */

tree search(typekey, tree);
tree insert(typekey, tree);
tree delete(typekey, tree);
int height(tree);
int count(tree);
int deltree(tree );
static tree lrot(tree);
static tree rrot(tree);
static node* newNode(void);
static void freeNode(node*);
static void Error(void);

/*
* 二*树查找例程
*/
tree search(typekey key, tree t)
{
   while(t != NULL)
      if (t->k == key)
         return t;
      else if (t->k < key)
         t = t->right;
           else
         t = t->left;
    return NULL;
}
/*
* 插入例程。
*/
tree insert(typekey key, tree t)
{
   if(t == NULL){ /* 当前节点为空 */
        t = newNode(); /* 建立新节点 */
      t->k = key;
      t->left = NULL;
      t->right = NULL;
        t->bal = 0; /* 叶子节点等高平衡 */
        incrhei = 1; /* 高度增加 */
   }
   else if(t->k == key)/* 键已经在表中 */
        Error();
     else {
        if(t->k < key){
           t->right = insert(key, t->right);
           t->bal += incrhei; /* 右子树高度增加 */
        } else {
           t->left = insert(key, t->left);
           t->bal -= incrhei; /* 左子树高度增加 */
      }
      /* 某个子树增加了高度,并且两个子树高度不相同 */
      if(incrhei != 0 && t->bal != 0){
         /* 左子树高于右子树两层: 需要右旋 */
         if(t->bal < -1) {
            /* 当前节点的左子节点偏右平衡 */
                if(t->left->bal > 0)
               /* 使当前节点的左子节点偏左平衡 */
               t->left = lrot(t->left);
                t = rrot(t);
            incrhei = 0; /* 本节点的高度不增加 */
           }
         /* 右子树高于左子树两层: 需要左旋 */
         else if(t->bal > 1) {
             /* 当前节点的右子节点左平衡 */
                if(t->right->bal < 0)
               /* 使当前节点的右子节点偏右平衡 */
               t->right = rrot(t->right);
                t = lrot(t);
            incrhei = 0; /* 本节点的高度不增加 */
         }
         else /* 某个子树高度增加了,破坏了等高平衡  */
            incrhei = 1; /* 本节点的高度增加 */
       }
          else
         /* 它的子树未增加高度,或者某个子树增加高度后导致等高平衡  */
             incrhei = 0;/* 本节点的高度不增加 */
   }
   return(t);
}
/*
* 删除例程
*/
tree delete(typekey key, tree t)
{
   tree p;
   if(t == NULL) /* 未找到 */
      Error();
   /* 键找到 */
   else if (t->k == key) {
       /* 有一个子树为空 */
      if (t->left == NULL) {
         p = t;
         t = t->right;
         freeNode(p);
         incrhei = 1; /* 高度减少 */
         return(t); /* 无需调整平衡 */
      }
      else if (t->right == NULL) {
         p = t;
         t = t->left;
         freeNode(p);
         incrhei = 1; /* 有高度变化 */
         return(t); /* 无需调整平衡 */
      /* 没有一个子树为空 */
      } else {      
         if(t->bal<0) {
            p = t->left;
            while (p->right != NULL)
               p = p->right;
            t->k = p->k;
            t->v = p->v;
            t->left  = delete(p->k, t->left);
            t->bal += incrhei; /* 左子树高度减少 */
         } else {
            p = t->right;
            while (p->left != NULL)
               p = p->left;
            t->k = p->k;
            t->v = p->v;
            t->right  = delete(p->k, t->right);
            t->bal -= incrhei; /* 右子树高度减少 */
         }
      }
   }      
   /* 当前节点不是要删除的,继续查找 */
   else if(t->k < key) {
      t->right = delete(key, t->right);
      t->bal -= incrhei; /* 右子树高度减少 */
   }
   else {
      t->left  = delete(key, t->left);
      t->bal += incrhei; /* 左子树高度减少 */
   }
    if (incrhei == 0 )
      return(t); /* 无需调整平衡 */
   /* 某个子树减少了高度,并且两个子树高度不相同 */
   if(t->bal != 0){
      /* 左子树高于右子树两层: 需要右旋 */
      if(t->bal < -1) {
         /* 当前节点的左子节点偏右平衡 */
         if(t->left->bal > 0) {
            /* 使当前节点的左子节点偏左平衡 */
            t->left = lrot(t->left);
            incrhei = 1;/* 本节点的高度减少 */
         }
         else if (t->left->bal == 0)
            incrhei = 0;/* 本节点的高度不减少 */
            else
            incrhei = 1;/* 本节点的高度减少 */
         t = rrot(t);
        }
      /* 右子树高于左子树两层: 需要左旋 */
      else if(t->bal > 1) {
                         /* 当前节点的右子节点左平衡 */
         if(t->right->bal < 0) {
            /* 使当前节点的右子节点偏右平衡 */
            t->right = rrot(t->right);
            incrhei = 1;/* 本节点的高度减少 */
         }
         else if (t->right->bal == 0)
            incrhei = 0;/* 本节点的高度不减少 */
            else
            incrhei = 1;/* 本节点的高度减少 */
             t = lrot(t);
      }
      else /* 某个子树高度减少了,破坏了等高平衡 */
         incrhei = 0; /* 本节点的高度不减少 */
   }
   /* 某个子树减少高度后导致等高平衡 */
       else
      incrhei = 1; /* 本节点的高度减少 */
    return(t);
}

/*
* 左旋例程
*            A              C
*           / /            / /
*          B   C    ==>   A   E
*             / /        / /
*            D   E      B   D
* 前提:A, 偏右不平衡, C 偏右或等高平衡。
*/
static tree lrot(tree t)
{
   tree temp;
   int a;

   temp = t;
   t = t->right;
   temp->right = t->left;  
   t->left = temp;

   a = temp->bal;
   /* 调整平衡因子 */
   /* 假定 A 的平衡因子是 a, 节点 C 的平衡因子是 c, 节点 B 为高度 h,
    * 则节点 D 高度为 (c<0)?h+a-1;h+a-1-c => h+a-1-max(c,0);
    * 节点 E 的高度为 (c>0)?h+a-1?h+a-1+c, => h+a-1+min(c,0);
    * 节点 A 的新平衡因子是 a-1-max(c,0);
    * 节点 C 的新平衡因子是 E-(max(B,D)+1) => min(E-B-1,E-D-1)
    *     => min(a-2+min(c,0),c-1) => min(min(a-2+c,a-2),c-1)
    *     <=> min(a-2,min(a+c-2,c-1))
    */
   temp->bal = a – 1 – max(t->bal, 0);
   t->bal = min(a-2, min(a+t->bal-2, t->bal-1));
   return(t);
}
/*
* 右旋例程
*            A              B
*           / /            / /
*          B   C    ==>   D   A
*         / /                / /
*        D   E              E   C
* 前提:A 偏左不平衡,B 偏左或等高平衡。
*/
static tree rrot(tree t)
{
   tree temp;
   int b;

   temp = t;
   t = t->left;
   temp->left = t->right;
   t->right = temp;
   /* 调整平衡因子 */
   b = temp->bal;
   /* 调整平衡因子 */
   /* 假定 A 的平衡因子是 b, 节点 B 的平衡因子是 c, 节点 C 为高度 h,
    * 则节点 D 高度为 (c<0)?h-b-1:h-b-1-c => h-b-1-max(c,0);
    * 节点 E 的高度为 (c>0)?h-b-1:h-b-1+c, => h-b-1+min(c,0);
    * 节点 A 的新平衡因子是 b+1-min(c,0)
    * 节点 C 的新平衡因子是 max(E,C)+1-D => max(E-D+1,C-D+1)
    *     => max(c+1,b+2+max(c,0)) => max(c+1,max(b+2+c,b+2))
    *     <=> max(b+2,max(b+c+2,c+1))
    */
   temp->bal = b + 1 – min(t->bal, 0);
   t->bal = max(b+2, max(b+t->bal+2, t->bal+1));
   return(t);
}
static void Error(void)
{
   printf(“/nError: insert or delete key/n”);
}
static node* newNode(void)
{
   return (node*)calloc(1,sizeof(node));
}
static void freeNode(node * p)
{
   free(p);
}
int height(tree t)
{
   if (t == NULL)
      return 0;
   else
      return 1+max(height(t->left),height(t->right));
}
int count(tree t)
{
   if (t == NULL)
      return 0;
   else
      return 1+count(t->left)+count(t->right);
}
int deltree(tree t)
{
   int c=0;
   if (t==NULL)
      return 0;
   else {
      c+=deltree(t->left);
      c+=deltree(t->right);
      freeNode(t);
      return c+1;
   }
}

    原文作者:AVL树
    原文地址: https://blog.csdn.net/lionkid/article/details/466664
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞