二叉搜索树之AVL树



《二叉搜索树之AVL树》

AVL树在ROS系统中应用广泛,如路由表管理模块和FEC表,这些大容量又操作频繁的数据,采用AVL树存储结构可以有效提高系统效率。

AVL树又称为高度平衡的二叉搜索树(BST),是1962年由两位俄罗斯数学家GMAdel’ son-Vel’skyEMLandis在论文《An algorithm for theorganization of information》中提出的。引入它的目的,是为了提高BST的搜索效率,即减少平均搜索长度。为此,向BST中每插入或删除一个新结点时,就必须调整树的结构,使得BST继续保持平衡,从而尽可能降低树的高度。

 

下面先讲讲AVL树的一些基本概念:

AVL树的定义:一棵ALV树或者是空树,或者是具有下列性质的二叉搜索树:它的左子树和右子树都是AVL树,且左子树和右子树的高度之差的绝对值不超过1

AVL树的高度:(固定节点数计算最大高度)

N(h)为一棵高度为hAVL树具有的最小节点数,则最坏情况是它的左右子树的高度不等,即一个是N(h-1)和另一个是N(h-2),从而得到,

N(h)=N(h-1)+N(h-2)+1,N(0)=0, N(1)=1

上述类似于Fibonacci数列:F(n)=F(n-1)+F(n-2), F(0)=0, F(1)=1

F(h)=(1+sqrt(5))^h/sqrt(5),N(h) = F(h+3)-1,h>=0,

h = 1.44log2(N(h)+1)-1.33

从而高度h和节点数是对数关系,因此h=O(log(N(h)))

由此容易知道在不考虑恢复AVL树的前提下,它的插入、删除和查找的工作量不超过O(n)


树的一些概念

图(父结点,祖父结点,兄弟结点,叔叔结点、左孩子、右孩子)


旋转(不改变BST性质)

左旋:

右旋:

细分4种类型:

LL型

LR型

RR型

RL型

平衡因子的调整

 

如果一棵二叉搜索树是高度平衡的,它就成为AVL树,如果它有N个结点,其高度可保持在O(log2n),平均搜索长度也可保持在O(log2n)。


树的旋转:

在介绍插入和删除操作之前首先介绍树的旋转操作

树的旋转操作是为了改变树的结构,使其达到平衡。旋转总共分为左旋和右旋两类

《二叉搜索树之AVL树》

如图为树的以B为轴左旋示意图(反过来看,从右到左是以A为轴右旋)。树的旋转操作要特别注意儿子节点是否为空

顶层节点是否为根节点。


AVL树的插入操作:

插入操作只会改变被插入节点到根节点路径上的节点的平衡因子。

因为在插入之前树是AVL树,因此各个节点的平衡因子是1-10

一、如果路径上节点平衡因子是0,则插入后不会打破这个节点的平衡性。

二、如果路径上的节点的平衡因子是1-1,则可能会打破平衡性,在这种情况下如果此节点的新的平衡

因子是0,则刚好将其补的更加平衡,平衡性未打破;否则平衡因子变成2-2,则需要进行调整。

三、我们在对树进行调整后恢复子树相对于插入前的高度,不改变子子树的平衡因子。

由以上三点:只需向根部查找从插入点开始第一个平衡因子不为0的节点,令该节点为A

更新步骤:

(1).若A不存在,说明插入节点不影响平衡性,则自下而上更新平衡因子直到根部即可。

(2).bf(A)=1且插入节点在A地右子树中,或者bf(A)=-1且插入节点在A的左子树中,则自下而上更新

平衡因子直到A。(注:A的平衡因子变为0

(3).A的平衡性被打破,首先依然自下而上更新平衡因子,在按照下面进行分类:LL, LR, RR, RL

bf(A)=1,新的bf(A)=2, LL, LR,

bf(A)=-1,新的bf(A)=-2, RR, RL

如图为RR的情况,LL情况类似,旋转后只需再次改变两个节点的平衡因子

《二叉搜索树之AVL树》

如下图为RL的情况,LR类似,旋转后需要再次改变三个节点的平衡因子

《二叉搜索树之AVL树》

至此,插入操作已经完成,可见最多多做两次旋转操作调整树的结构使之平衡。


AVL树的删除操作:

删除操作和插入操作一样,也是先直接删除二叉树节点,然后在更新平衡因子,

调整AVL树使之平衡。

这里所指的删除的节点是实际被删除的节点,删除操作不影响其子树的平衡因子。

首先删除节点,然后沿着该节点的父节点向根部更新平衡因子,考虑更新后的节点A

新的平衡因子,分为下面三种情况:

(1)、如果bf(A)=0,则高度减少了1,从而继续向上找非平衡点。

(2)、如果bf(A)=1或者-1,则之前必为0,从而不影响平衡性,结束。

(3)、如果bf(A)=2(原来为1)或者-2(原来为-1),则A点非平衡。调整。

bf(A)=-2为例,称AL不平衡

如果A的右节点的平衡因子是0,则进行一次左旋转,如图:

《二叉搜索树之AVL树》

由于子树的高度和删除前一样,因此树已经平衡。

如果A的右节点的平衡因子是-1,则称为L-1不平衡,也要进行一次做旋转。

《二叉搜索树之AVL树》

树的高度减少1,这使得上面的祖先节点可能不平衡,一次还要沿着路径在向上

寻找新的不平衡点,再次更新平衡因子,调整等。

如果A的右节点的平衡因子是1,则称为L1不平衡,要进行两次旋转。

《二叉搜索树之AVL树》

此时要根据BL的情况决定AB的新的平衡因子。

由于树的高度减少了1,因此还要沿着路径继续向上寻找新的不平衡点。

至此树节点的删除操作完成。


总结:

归纳起来,AVL树的查找操作(符合中序遍历)等同于一般二叉搜索树,插入和删除操作除了一般的二叉树插入和删除,还要更新树的平衡因子,当平衡因子被打破时要通过旋转恢复。而且在调整平衡时尽量影响局部范围。平衡调整过程总是至下而上进行,把不平衡消灭在最开始阶段。

最后附上avl实现源码,在VC6.0上验证通过。

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/*****************************************************************
 * 文件名:AVL.c
 * 需求:  实现AVL树的插入、删除、查找、遍历等基本功能
 * 作者:  韩立忠  2012.04.10
 ****************************************************************/

/************************* 引入的头文件 *************************/

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <assert.h>

/**************************** 宏定义 ****************************/

#define DEBUG_VERSION 1

#if DEBUG_VERSION
#define ASSERT(x) assert(x)
#else
#define ASSERT(x) (1 == 1)
#endif

/* 宏定义栈深度 */
#define STACK_SIZE 40

/************************* 定义数据结构 *************************/

/* 函数返回值的枚举 */
enum
{
 FALSE = 0,
 TRUE  = 1,
 ERROR = 0xffffffff
};

/* typedefs */
typedef int status_t;
typedef int BOOL;
typedef int key_t;  /* 可根据用户需要定义为多成员变量的结构体 */
typedef int data_t;

/* 定义AVL树结点平衡因子的枚举类型 */
typedef enum BF_E
{
 EH = 0,    /* 等高 */
 LH = 1,    /* 左高 */
 RH = 2     /* 右高 */
}bf_e;

/* 定义AVL树结点相对于父结点位置关系的枚举类型 */
typedef enum POS_E
{
 ROOT = 0,        /* 标识本结点为根结点 */
 LCHILD = 1,      /* 标识本结点为父结点的左孩子 */
 RCHILD = 2       /* 标识本结点为父结点的右孩子 */
}pos_e;

/* 定义AVL树的数据结点 */
typedef struct avlNode_s
{
 //struct avlNode_s *prev;  /* 用于AVL树的线索化 */
 //struct avlNode_s *next;
 struct avlNode_s *lChild;  /* 指向左孩子的指针 */
 struct avlNode_s *rChild;  /* 指向右孩子的指针 */
 bf_e bf;                   /* 结点的平衡因子 */
}avlNode_t;

/* 用户定义的AVL树数据结点 */
typedef struct myAvlNode_s
{
 //struct myAvlNode_s *prev;  /* 用于AVL树的线索化 */
 //struct myAvlNode_s *next;
 struct myAvlNode_s *lChild;  /* 指向左孩子的指针 */
 struct myAvlNode_s *rChild;  /* 指向右孩子的指针 */
 bf_e bf;                      /* 结点的平衡因子 */
 key_t key;                    /* 键值项 */
 //data_t data;                  /* 数据项 */
}myAvlNode_t;

/* 定义缓存栈,用于存放AVL树搜索路径上的结点指针 */
typedef struct stack_s
{
 avlNode_t *buff[STACK_SIZE];  /* 记录结点指针 */
 pos_e pos[STACK_SIZE];        /* 记录结点相对于父结点的位置关系 */
 unsigned char top;            /* 栈顶指针 */
 char res[3];                  /* 保留bit,用于字节对齐 */
}stack_t;

/************************* 定义回调函数 *************************/

typedef int (*nodeCmp_f)(avlNode_t *, avlNode_t *);
typedef void (*nodeCpy_f)(avlNode_t *, avlNode_t *);
typedef void (*nodeFree_f)(avlNode_t *);
typedef void (*nodePrint_f)(avlNode_t *);

/* 定义AVL树指向根结点的Root结点 */
typedef struct avlRoot_s
{
 avlNode_t *root;           /* 指向AVL根结点的指针 */
 unsigned int count;        /* AVL结点总数 */
 unsigned char height;      /* AVL树高度 */
 char res[3];
 nodeCmp_f nodeCmp;        /* 结点键值比较函数 */
 nodeCpy_f nodeCpy;        /* 结点数据复制函数 */
 nodeFree_f nodeFree;       /* 结点内存释放函数 */
 nodePrint_f nodePrint;     /* 结点数据打印函数 */
}avlRoot_t;

/************************* 全局函数声明 *************************/

/* AVL树结点插入操作 */
status_t AVL_insert(avlRoot_t *pRoot, avlNode_t *pNode);
/* AVL树结点删除操作 */
status_t AVL_delete(avlRoot_t *pRoot, avlNode_t *pNode);
/* AVL树查找函数 */
avlNode_t *AVL_find(avlRoot_t *pRoot, avlNode_t *pfindNode);
/* AVL树查找函数(递归方法) */
avlNode_t *AVL_find_R(avlNode_t *pNode, avlNode_t *pfindNode);
/* 根据当前data值查找其父结点函数 */
avlNode_t *AVL_findParent(avlRoot_t *pRoot, avlNode_t *pNode);
/* AVL树中序遍历函数 */
void AVL_traverseInOrder(avlRoot_t *pRoot);
/* AVL树结点内存释放函数 */
void AVL_free(avlRoot_t **ppRoot);

/*————————– 内部函数 ————————–*/

static void leftRotate(avlNode_t **P);     /* AVL树以根结点P左旋处理函数 */
static void rightRotate(avlNode_t **P);    /* AVL树以根结点P右旋处理函数 */
static void leftBalance(avlNode_t **T);    /* AVL树以T为根结点作左平衡处理函数 */
static void rightBalance(avlNode_t **T);   /* AVL树以T为根结点作右平衡处理函数 */

/*———————— 用户定义函数 ————————*/

void AVL_rootInit(avlRoot_t **ppRoot);             /* AVL树根节点初始化函数 */
avlNode_t *encapNode(key_t *key);
int nodeCmp(avlNode_t *pNode1, avlNode_t *pNode2); /* AVL树结点键值比较函数 */
void nodeFree(avlNode_t *pNode);                   /* AVL树结点内存释放函数 */
void nodePrint(avlNode_t *pNode);                  /* AVL树结点数据打印函数 */

/*———————— 栈的相关函数 ————————*/

static void stackInit(stack_t **);                             /* 栈初始化函数 */
static void stackPush(stack_t *, avlNode_t *, pos_e);          /* 压栈函数 */
static void stackPop(stack_t *, avlNode_t **, pos_e *);        /* 出栈函数 */
static void stackGet(stack_t *, avlNode_t **, pos_e *);        /* 取栈顶元素函数 */
static void stackReplace(stack_t *, avlNode_t *, avlNode_t *); /* 栈元素替换函数 */
static void stackFree(stack_t **);                             /* 栈内存释放函数 */
static BOOL stackIsEmpty(stack_t *);                           /* 判栈是否为空函数 */

/************************* 定义全局变量 *************************/

#define N 10000
//key_t a[10] = {3, 2, 1, 4, 5, 6, 7, 10, 9, 8};
key_t a[N] = {0};

/****************************************************************/

/**************************** 主函数 ****************************/

void test(void)
{
 int i = 0;
 avlRoot_t *pRoot = NULL;
 avlNode_t *pNode = NULL;

 AVL_rootInit(&pRoot);
 for (i = 0; i < N; i++)
 {
  a[i] = i + 1;
 }

 for (i = 0; i < N; i++)
 {
  AVL_insert(pRoot, encapNode(&a[i]));
 }
 AVL_traverseInOrder(pRoot);

 for (i = N/20; i < N*3/4; i++)
 {
  pNode = encapNode(&a[i]);
  AVL_delete(pRoot, pNode);
  pRoot->nodeFree(pNode);
 }
 AVL_traverseInOrder(pRoot);

 AVL_free(&pRoot);

 return;
}

void main(void)
{
 test();
 return;
}

/****************************************************************/
/****************************************************************/

/* AVL树以根结点P右旋处理函数 */
static void rightRotate(avlNode_t **P)
{
 avlNode_t *L = NULL;
 if ((NULL == P) || (NULL == *P))
 {
  ASSERT(0);
  return;
 }

 L = (*P)->lChild;
 ASSERT(L != NULL);
 (*P)->lChild = L->rChild;
 L->rChild = *P;
 *P = L;     /* P指向新的根结点 */

 return;
}

/* AVL树以根结点P左旋处理函数 */
static void leftRotate(avlNode_t **P)
{
 avlNode_t *R = NULL;
 if ((NULL == P) || (NULL == *P))
 {
  ASSERT(0);
  return;
 }

 R = (*P)->rChild;
 ASSERT(R != NULL);
 (*P)->rChild = R->lChild;
 R->lChild = *P;
 *P = R;

 return;
}

/* AVL树以T所指结点为根作左平衡旋转处理函数,算法结束T指向新的根节点 */
static void leftBalance(avlNode_t **T)
{
 avlNode_t *L = NULL;
 avlNode_t *Lr = NULL;
 if ((NULL == T) || (NULL == *T))
 {
  ASSERT(0);
  return;
 }

 L = (*T)->lChild;
 ASSERT(L != NULL);
 /* 检查T左子树的平衡度,并作相应平衡处理 */
 switch (L->bf)
 {
 case LH:  /* T左孩子左高,作LL单旋处理 */
  {
   (*T)->bf = EH;
   L->bf = EH;
   rightRotate(T);
   break;
  }
 case RH:  /* T左孩子右高,作LR双旋处理 */
  {
   Lr = L->rChild;
   ASSERT(Lr != NULL);
   /* 根据T左孩子的右孩子bf,修改T及其左孩子的bf */
   switch (Lr->bf)
   {
   case LH:
    {
     (*T)->bf = RH;
     L->bf = EH;
     break;
    }
   case EH:
    {
     (*T)->bf = EH;
     L->bf = EH;
     break;
    }
   case RH:
    {
     (*T)->bf = EH;
     L->bf = LH;
     break;
    }
   default:
    {
     ASSERT(0);
     return;
    }
   }
   Lr->bf = EH;
   leftRotate(&((*T)->lChild)); /* 对T的左子树作左旋处理 */
   rightRotate(T);              /* 对T作右旋处理 */
   break;
  }
 case EH:  /* T左右孩子等高,仅删除操作时会出现该情况 */
  {
   (*T)->bf = LH;
   L->bf = RH;
   rightRotate(T);
   break;
  }
 default:
  {
   ASSERT(0);
   return;
  }
 }

 return;
}

/* AVL树以T所指结点为根作右平衡旋转处理函数,算法结束T指向新的根节点 */
static void rightBalance(avlNode_t **T)
{
 avlNode_t *R = NULL;
 avlNode_t *Rl = NULL;
 if ((NULL == T) || (NULL == *T))
 {
  ASSERT(0);
  return;
 }

 R = (*T)->rChild;
 ASSERT(R != NULL);
 /* 检查T右子树的平衡度,作相应平衡处理 */
 switch (R->bf)
 {
 case LH:  /* T右孩子左高,作RL双旋处理 */
  {
   Rl = R->lChild;
   ASSERT(Rl != NULL);
   switch (Rl->bf)
   {
   case LH:
    {
     (*T)->bf = EH;
     R->bf = RH;
     break;
    }
   case EH:
    {
     (*T)->bf = EH;
     R->bf = EH;
     break;
    }
   case RH:
    {
     (*T)->bf = LH;
     R->bf = EH;
     break;
    }
   default:
    {
     ASSERT(0);
     return;
    }
   }
   Rl->bf = EH;
   rightRotate(&((*T)->rChild)); /* 对T的右子树作右旋处理 */
   leftRotate(T);                /* 对T作左旋处理 */
   break;
  }
 case RH:  /* T右孩子右高,作RR单旋处理 */
  {
   (*T)->bf = EH;
   R->bf = EH;
   leftRotate(T);
   break;
  }
 case EH:  /* T左右孩子等高,仅删除操作会出现该情况 */
  {
   (*T)->bf = RH;
   R->bf = LH;
   leftRotate(T);
   break;
  }
 default:
  {
   ASSERT(0);
   return;
  }
 }

 return;
}

/* AVL树根节点初始化函数 */
void AVL_rootInit(avlRoot_t **ppRoot)
{
 if (NULL == ppRoot)
 {
  ASSERT(0);
  return;
 }

 *ppRoot = (avlRoot_t *)malloc(sizeof(avlRoot_t));
 if (NULL == *ppRoot)
 {
  ASSERT(0);
  return;
 }

 memset(*ppRoot, 0, sizeof(avlRoot_t)); 
 (*ppRoot)->nodeCmp = nodeCmp;
 (*ppRoot)->nodeFree = nodeFree;
 (*ppRoot)->nodePrint = nodePrint;
 
 return;
}

/* AVL树插入函数 */
status_t AVL_insert(avlRoot_t *pRoot, avlNode_t *pNode)
{
 stack_t *pStack = NULL;
 pos_e pos = ROOT;
 pos_e parPos = ROOT;
 pos_e childPos = ROOT;
 avlNode_t *pTmpNode = NULL;
 avlNode_t *pParNode = NULL;
 int rtnValue = 0;
 
 if ((NULL == pRoot) || (NULL == pNode))
 {
  ASSERT(0);
  return ERROR;
 }

 /* 树为空,直接插入新结点返回 */
 pTmpNode = pRoot->root;
 if (NULL == pTmpNode)
 {
  pRoot->root = pNode;
  pRoot->count = 1;
  pRoot->height = 1;
  return TRUE;
 }

 /* 该栈用于记录搜索路径上的结点指针和相对于上级结点的位
 置关系,记录结点包括根结点和最后的NULL指针 */
 stackInit(&pStack);
 stackPush(pStack, pTmpNode, ROOT);  /* 记录根结点 */

 /* (1)树不为空,查找插入位置 */
 do
 {
  rtnValue = pRoot->nodeCmp(pNode, pTmpNode);
  /* 树中已存在相同结点,不再插入 */
  if (0 == rtnValue)
  {
   pRoot->nodeFree(pNode);
   stackFree(&pStack);
   return FALSE;
  }

  if (rtnValue < 0)
  {
   pTmpNode = pTmpNode->lChild;
   stackPush(pStack, pTmpNode, LCHILD);
  }
  else
  {
   pTmpNode = pTmpNode->rChild;
   stackPush(pStack, pTmpNode, RCHILD);
  }
 } while (pTmpNode != NULL);

 /* (2)找到插入位置,执行插入操作 */
 stackPop(pStack, &pTmpNode, &pos);
 ASSERT((NULL == pTmpNode) && (LCHILD == pos) || (RCHILD == pos));
 ASSERT(!stackIsEmpty(pStack));
 stackGet(pStack, &pParNode, &parPos);
 ASSERT(pParNode != NULL);
 if (LCHILD == pos)
 {
  pParNode->lChild = pNode;
 }
 else
 {
  pParNode->rChild = pNode;
 }
 pRoot->count++;

 /* (3)已插入结点,执行平衡处理 */
 do
 {
  childPos = pos;
  stackPop(pStack, &pTmpNode, &pos);
  /* 若插入在pTmpNode结点左子树上 */
  if (LCHILD == childPos)
  {
   /* 检查pTmpNode的平衡度 */
   switch (pTmpNode->bf)
   {
   case LH:  /* 原本左子树比右子树高,作左平衡处理 */
    {
     leftBalance(&pTmpNode);
     /* 平衡处理后,重新连好pTmpNode与父结点的关系 */
     if (stackIsEmpty(pStack))
     {
      ASSERT(ROOT == pos);
      pRoot->root = pTmpNode;
     }
     else
     {
      ASSERT((LCHILD == pos) || (RCHILD == pos));
      stackGet(pStack, &pParNode, &parPos);
      ASSERT(pParNode != NULL);
      if (LCHILD == pos)
      {
       pParNode->lChild = pTmpNode;
      }
      else
      {
       pParNode->rChild = pTmpNode;
      }
     }
     stackFree(&pStack);
     return TRUE;
    }
   case EH:  /* 原本左右子树等高,现因左子树增高而增高 */
    {
     pTmpNode->bf = LH;
     if (pTmpNode == pRoot->root)
     {
      pRoot->height++;
     }
     break;
    }
   case RH:  /* 原本右子树比左子树高,现左右子树等高 */
    {
     pTmpNode->bf = EH;
     stackFree(&pStack);
     return TRUE;
    }
   default:
    {
     ASSERT(0);
     stackFree(&pStack);
     return ERROR;
    }
   }
  }
  /* 若插入在pTmpNode结点右子树上 */
  else
  {
   ASSERT(RCHILD == childPos);
   switch (pTmpNode->bf)
   {
   case LH:  /* 原本左子树比右高,现左右等高 */
    {
     pTmpNode->bf = EH;
     stackFree(&pStack);
     return TRUE;
    }
   case EH:  /* 原本左右子树等高,现因右增高而增高 */
    {
     pTmpNode->bf = RH;
     if (pTmpNode == pRoot->root)
     {
      pRoot->height++;
     }
     break;
    }
   case RH:  /* 原本右子树比左高,作右平衡处理 */
    {
     rightBalance(&pTmpNode);
     if (stackIsEmpty(pStack))
     {
      ASSERT(ROOT == pos);
      pRoot->root = pTmpNode;
     }
     else
     {
      ASSERT((LCHILD == pos) || (RCHILD == pos));
      stackGet(pStack, &pParNode, &parPos);
      ASSERT(pParNode != NULL);
      if (LCHILD == pos)
      {
       pParNode->lChild = pTmpNode;
      }
      else
      {
       pParNode->rChild = pTmpNode;
      }
     }
     stackFree(&pStack);
     return TRUE;
    }
   default:
    {
     ASSERT(0);
     stackFree(&pStack);
     return ERROR;
    }
   }
  }
 } while (!stackIsEmpty(pStack));
 
 stackFree(&pStack);
 return TRUE;
}

/* AVL树删除函数 */
status_t AVL_delete(avlRoot_t *pRoot, avlNode_t *pNode)
{
 stack_t *pStack = NULL;
 BOOL lower = FALSE;
 pos_e pos = ROOT;         /* 该结点相应于上级结点的位置关系 */
 pos_e dPos = ROOT;
 pos_e nPos = ROOT;
 pos_e parPos = ROOT;
 pos_e dParPos = ROOT;
 pos_e nParPos = ROOT;
 pos_e childPos = ROOT;
 avlNode_t *pTmpNode = NULL;
 avlNode_t *pParNode = NULL;     /* 父结点 */
 avlNode_t *pDelNode = NULL;     /* 待删结点 */
 avlNode_t *pDelParNode = NULL;  /* 待删结点的父结点 */
 avlNode_t *pNearNode = NULL;    /* 待删结点的直接前驱或后继结点 */
 avlNode_t *pNearParNode = NULL; /* 邻近结点的父结点 */
 int rtnValue = 0;
 
 if ((NULL == pRoot) || (NULL == pNode))
 {
  ASSERT(0);
  return ERROR;
 }

 pTmpNode = pRoot->root;
 /* 该栈用于记录搜索路径的结点指针和相对上级结点的位置,
 包括根结点,或包括最后的NULL指针 */
 stackInit(&pStack);
 stackPush(pStack, pTmpNode, ROOT);   /* 记录根结点 */

 /* (1)查找删除结点位置 */
 while (pTmpNode != NULL)
 {
  rtnValue = pRoot->nodeCmp(pNode, pTmpNode);
  /* 找到待删结点,跳出循环 */
  if (0 == rtnValue)
  {
   break;
  }

  if (rtnValue < 0)
  {
   pTmpNode = pTmpNode->lChild;
   stackPush(pStack, pTmpNode, LCHILD);
  }
  else
  {
   pTmpNode = pTmpNode->rChild;
   stackPush(pStack, pTmpNode, RCHILD);
  }
 }

 /* 未找到待删结点,返回FALSE */
 if (NULL == pTmpNode)
 {
  stackFree(&pStack);
  return FALSE;
 }

 /* (2)找到待删结点,执行删除操作 */
 stackPop(pStack, &pDelNode, &dPos);  /* 弹出待删结点 */
 if (stackIsEmpty(pStack))
 {
  ASSERT((pDelNode == pRoot->root) && (ROOT == dPos));
 }
 else
 {
  ASSERT((LCHILD == dPos) || (RCHILD == dPos));
  stackGet(pStack, &pDelParNode, &dParPos);
  ASSERT(pDelParNode != NULL);
 }
 
 /* (2)-1若待删结点右孩子为空,或左右孩子都空 */
 if (NULL == pDelNode->rChild)
 {
  if (pDelNode == pRoot->root)
  {
   pRoot->root = pDelNode->lChild;
  }
  else
  {
   if (LCHILD== dPos)
   {
    pDelParNode->lChild = pDelNode->lChild;
   }
   else
   {
    pDelParNode->rChild = pDelNode->lChild;
   }
  }

  /* 记录待删结点位置,用于后续平衡处理 */
  stackPush(pStack, (avlNode_t *)NULL, dPos);
 }
 /* (2)-2若待删结点右孩子非空,左孩子为空 */
 else if (NULL == pDelNode->lChild)
 {
  if (pDelNode == pRoot->root)
  {
   pRoot->root = pDelNode->rChild;
  }
  else
  {
   if (LCHILD== dPos)
   {
    pDelParNode->lChild = pDelNode->rChild;
   }
   else
   {
    pDelParNode->rChild = pDelNode->rChild;
   }
  }

  stackPush(pStack, (avlNode_t *)NULL, dPos);
 }
 /* (2)-3若待删结点左右孩子都非空 */
 else
 {
  /* 这种情况,考虑使用待删结点的直接前驱或后继结点替代
  待删结点。为减少平衡处理,做一次判断,用待删结点平衡
  因子高的一侧的邻近结点替换之 */
  /* (2)-3-1查找邻近结点,即直接前驱或后继结点 */
  stackPush(pStack, pDelNode, dPos);  /* 待删结点再次入栈 */
  switch (pDelNode->bf)
  {
  case LH:
  case EH:
   {
    pTmpNode = pDelNode->lChild;
    stackPush(pStack, pTmpNode, LCHILD);
    do
    {
     pTmpNode = pTmpNode->rChild;
     stackPush(pStack, pTmpNode, RCHILD);
    } while (pTmpNode != NULL); 
    break;
   }
  case RH:
   {
    pTmpNode = pDelNode->rChild;
    stackPush(pStack, pTmpNode, RCHILD);
    do
    {
     pTmpNode = pTmpNode->lChild;
     stackPush(pStack, pTmpNode, LCHILD);
    } while (pTmpNode != NULL); 
    break;
   }
  default:
   {
    ASSERT(0);
    stackFree(&pStack);
    return ERROR;
   }
  }

  /* (2)-3-2找到邻近结点,用它替换待删结点 */
  stackPop(pStack, &pTmpNode, &pos);
  stackPop(pStack, &pNearNode, &nPos);  /* 弹出邻近结点 */
  /* 邻近结点的左右孩子必定至少有一个为空,否则不为待删
  结点的直接前驱或后继结点 */
  ASSERT((LCHILD == nPos) || (RCHILD == nPos));
  ASSERT((NULL == pNearNode->lChild) || (NULL == pNearNode->rChild));
  ASSERT(!stackIsEmpty(pStack));
  stackGet(pStack, &pNearParNode, &nParPos);
  ASSERT(pNearParNode != NULL);
  /* (2)-3-2-1摘除pNearNode结点 */
  /* 若邻近结点的右子树为空,或左右皆空 */
  if (NULL == pNearNode->rChild)
  {
   if (LCHILD == nPos)
   {
    pNearParNode->lChild = pNearNode->lChild;
   }
   else
   {
    pNearParNode->rChild = pNearNode->lChild;
   }
  }
  /* 若邻近结点的右子树非空,则左子树必定为空 */
  else
  {
   if (LCHILD == nPos)
   {
    pNearParNode->lChild = pNearNode->rChild;
   }
   else
   {
    pNearParNode->rChild = pNearNode->rChild;
   }
  }

  /* (2)-3-2-2用pNearNode结点替换pDelNode结点 */
  pNearNode->lChild = pDelNode->lChild;
  pNearNode->rChild = pDelNode->rChild;
  pNearNode->bf = pDelNode->bf;
  if (pDelNode == pRoot->root)
  {
   pRoot->root = pNearNode;
  }
  else
  {
   if (LCHILD == dPos)
   {
    pDelParNode->lChild = pNearNode;
   }
   else
   {
    pDelParNode->rChild = pNearNode;
   }
  }

  /* 记录邻近结点位置,用于后续平衡处理 */
  stackPush(pStack, (avlNode_t *)NULL, nPos);
  /* 替换栈中记录的pDelNode指针为pNearNode指针,平衡因子保持
  原来pDelNode的bf不变,用于后续平衡处理 */
  stackReplace(pStack, pDelNode, pNearNode);
 }

 /* (2)-4释放待删结点 */
 pRoot->count–;
 pRoot->nodeFree(pDelNode);
 pDelNode = NULL;

 /* (3)结点删除完成,进行平衡处理 */
 /* 弹出删除或替换结点相应于上级结点的位置关系pos */
 stackPop(pStack, &pTmpNode, &pos);
 if (stackIsEmpty(pStack))
 {
  /* 树结点小于2时删除根结点,无需平衡处理 */
  ASSERT(ROOT == pos);
  pRoot->height–;
  stackFree(&pStack);
  return TRUE;
 }
 ASSERT((LCHILD == pos) || (RCHILD == pos));
 
 do
 {
  childPos = pos;
  stackPop(pStack, &pTmpNode, &pos);
  ASSERT(pTmpNode != NULL);
  /* 若删除或替换结点在pTmpNode左子树 */
  if (LCHILD == childPos)
  {
   /* 检查pTmpNode的平衡度 */
   switch (pTmpNode->bf)
   {
   case LH:  /* 原本左子树比右子树高,现在等高 */
    {
     pTmpNode->bf = EH;
     if (pTmpNode == pRoot->root)
     {
      pRoot->height–;
     }
     /* 由于该子树整体高度减低,需向上回溯平衡处理 */
     break;
     
    }
   case EH:  /* 原本左右子树等高,现因左降低而右高 */
    {
     pTmpNode->bf = RH;
     stackFree(&pStack);
     return TRUE;
    }
   case RH:  /* 原本右子树比左子树高,做右平衡处理 */
    {
     /* 根据pTmpNode右孩子的平衡因子情况,判断平衡
     处理后子树高度是否降低。仅当pTmpNode的右孩子
     平衡因子为EH时,以pTmpNode为根结点平衡处理后
     子树的高度不变 */
     ASSERT(pTmpNode->rChild != NULL);
     if (pTmpNode->rChild->bf != EH)
     {
      lower = TRUE;
     }
     else
     {
      lower = FALSE;
     }
     
     rightBalance(&pTmpNode);
     /* 平衡处理后,重新连接pTmpNode与父结点关系 */
     if (stackIsEmpty(pStack))
     {
      ASSERT(ROOT == pos);
      pRoot->root = pTmpNode;
     }
     else
     {
      ASSERT((LCHILD == pos) || (RCHILD == pos));
      stackGet(pStack, &pParNode, &parPos);
      ASSERT(pParNode != NULL);
      if (LCHILD == pos)
      {
       pParNode->lChild = pTmpNode;
      }
      else
      {
       pParNode->rChild = pTmpNode;
      }
     }

     if (TRUE == lower)
     {
      if (pTmpNode == pRoot->root)
      {
       pRoot->height–;
      }
      /* 平衡处理后该子树高度减低,需向上回溯 */
      break;
     }
     else
     {
      stackFree(&pStack);
      return TRUE;
     }
    }
   default:
    {
     ASSERT(0);
     stackFree(&pStack);
     return ERROR;
    }
   }
  }
  /* 若删除或替换结点在pTmpNode右子树 */
  else
  {
   ASSERT(RCHILD == childPos);
   switch (pTmpNode->bf)
   {
   case LH:  /* 原本左子树比右高,作左平衡处理 */
    {
     ASSERT(pTmpNode->lChild != NULL);
     if (pTmpNode->lChild->bf != EH)
     {
      lower = TRUE;
     }
     else
     {
      lower = FALSE;
     }
     
     leftBalance(&pTmpNode);
     /* 平衡处理后,重新连好pTmpNode与父结点的关系 */
     if (stackIsEmpty(pStack))
     {
      ASSERT(ROOT == pos);
      pRoot->root = pTmpNode;
     }
     else
     {
      ASSERT((LCHILD == pos) || (RCHILD == pos));
      stackGet(pStack, &pParNode, &parPos);
      ASSERT(pParNode != NULL);
      if (LCHILD == pos)
      {
       pParNode->lChild = pTmpNode;
      }
      else
      {
       pParNode->rChild = pTmpNode;
      }
     }

     if (TRUE == lower)
     {
      if (pTmpNode == pRoot->root)
      {
       pRoot->height–;
      }
      break;
     }
     else
     {
      stackFree(&pStack);
      return TRUE;
     }
    }
   case EH:  /* 原本左右子树等高,现因右降低而左高 */
    {
     pTmpNode->bf = LH;
     stackFree(&pStack);
     return TRUE;
    }
   case RH:  /* 原本右子树比左高,现在等高 */
    {
     pTmpNode->bf = EH;
     if (pTmpNode == pRoot->root)
     {
      pRoot->height–;
     }
     break;
    }
   default:
    {
     ASSERT(0);
     stackFree(&pStack);
     return ERROR;
    }
   }
  }
 } while (!stackIsEmpty(pStack));
 
 stackFree(&pStack);
 return TRUE;
}

/* AVL树查找函数(非递归方法) */
avlNode_t *AVL_find(avlRoot_t *pRoot, avlNode_t *pfindNode)
{
 avlNode_t *pNode = NULL;
 int rtnValue = 0;
 if ((NULL == pRoot) || (NULL == pfindNode))
 {
  ASSERT(0);
  return NULL;
 }

 pNode = pRoot->root;
 while (pNode != NULL)
 {
  rtnValue = pRoot->nodeCmp(pfindNode, pNode);
  if (0 == rtnValue)
  {
   break;
  }

  if (rtnValue < 0)
  {
   pNode = pNode->lChild;
  }
  else
  {
   pNode = pNode->rChild;
  }
 }

 return pNode;
}

/* AVL树查找函数(递归方法) */
avlNode_t *AVL_find_R(avlNode_t *pNode, avlNode_t *pfindNode)
{
 if ((NULL == pNode) || (NULL == pfindNode))
 {
  return NULL;
 }

 if (0 == nodeCmp(pfindNode, pNode))
 {
  return pNode;
 }

 if (nodeCmp(pfindNode, pNode) < 0)
 {
  return AVL_find_R(pNode->lChild, pfindNode);
 }
 else
 {
  return AVL_find_R(pNode->rChild, pfindNode);
 }
}

/* 由当前结点数据查找其父结点(非递归方法) */
avlNode_t *AVL_findParent(avlRoot_t *pRoot, avlNode_t *pNode)
{
 stack_t *pStack = NULL;
 avlNode_t *pTmpNode = NULL;
 pos_e pos = ROOT;
 if (NULL == pRoot)
 {
  ASSERT(0);
  return NULL;
 }

 pTmpNode = pRoot->root;
 stackInit(&pStack); 
 while((pTmpNode != NULL) || (!stackIsEmpty(pStack)))
 {
  if (pTmpNode != NULL)
  {
   stackPush(pStack, pTmpNode, pos);
   pTmpNode = pTmpNode->lChild;
  }
  else
  {
   stackPop(pStack, &pTmpNode, &pos);
   pTmpNode = pTmpNode->rChild;
  }

  if ((pTmpNode != NULL) && (0 == pRoot->nodeCmp(pTmpNode, pNode)))
  {
   break;
  }
 }
 stackPop(pStack, &pTmpNode, &pos);  /* 弹出父结点指针 */
 stackFree(&pStack);

 return pTmpNode;
}

/* AVL树中序遍历函数 */
void AVL_traverseInOrder(avlRoot_t *pRoot)
{
 stack_t *pStack = NULL;
 avlNode_t *pNode = NULL;
 pos_e pos = ROOT;
 if (NULL == pRoot)
 {
  ASSERT(0);
  return;
 }

 pNode = pRoot->root;
 stackInit(&pStack);
 printf(“Count:%13d\nHeight:%12d\n”, pRoot->count, pRoot->height);
 while ((pNode != NULL) || (!stackIsEmpty(pStack)))
 {
  while (pNode != NULL)
  {
   stackPush(pStack, pNode, pos);
   pNode = pNode->lChild;
  }
  stackPop(pStack, &pNode, &pos);
  pRoot->nodePrint(pNode);
  pNode = pNode->rChild;
 }
 printf(“\n”);
 stackFree(&pStack);

 return;
}

/* 释放AVL树函数,包括根结点和数据结点,从左侧底开始释放 */
void AVL_free(avlRoot_t **ppRoot)
{
 stack_t *pStack = NULL;
 avlNode_t *pNode = NULL;
 avlNode_t *pParNode = NULL;
 pos_e pos = ROOT;
 if ((NULL == *ppRoot) || (NULL == ppRoot))
 {
  ASSERT(0);
  return;
 }

 pNode = (*ppRoot)->root;
 stackInit(&pStack); 
 while ((pNode != NULL) || (!stackIsEmpty(pStack)))
 {
  while (pNode != NULL)
  {
   stackPush(pStack, pNode, pos);
   pNode = pNode->lChild;
  }
  stackPop(pStack, &pNode, &pos);
  ASSERT(pNode != NULL);
  
  if (pNode->rChild != NULL)
  {
   stackPush(pStack, pNode, pos);
   pNode = pNode->rChild;
   continue;
  }
  
  /* 树结点的左右孩子都空,释放之 */
  if (!stackIsEmpty(pStack))  /* 树的非根结点释放 */
  {
   stackPop(pStack, &pParNode, &pos);
   if (pParNode->lChild == pNode)
   {
    pParNode->lChild = NULL;
   }
   else
   {
    pParNode->rChild = NULL;
   }
   (*ppRoot)->nodeFree(pNode);
   pNode = pParNode;
  }
  else                        /* 树的根结点释放 */
  {
   ASSERT(((*ppRoot)->root == pNode) && stackIsEmpty(pStack));
   (*ppRoot)->nodeFree(pNode);
   pNode = NULL;
   (*ppRoot)->root = NULL;
  }
 }
 //(*ppRoot)->count = 0;

 /* 释放完所有树结点,最后释放Root结点 */
 free(*ppRoot);
 *ppRoot = NULL;
 stackFree(&pStack);

 return;
}

/* 封装avl树结点,并初始化结点数据 */
avlNode_t *encapNode(key_t *key)
{
 myAvlNode_t *pNode = NULL;
 if (NULL == key)
 {
  ASSERT(0);
  return NULL;
 }

 pNode = (myAvlNode_t *)malloc(sizeof(myAvlNode_t));
 if (NULL == pNode)
 {
  ASSERT(0);
  return NULL;
 }
 //pNode->prev = NULL;
 //pNode->next = NULL;
 pNode->lChild = NULL;
 pNode->rChild = NULL;
 pNode->bf = EH;
 memcpy(&(pNode->key), key, sizeof(key_t));
 //data encap

 return (avlNode_t *)pNode;
}

/* AVL树结点键值比较函数 */
int nodeCmp(avlNode_t *pNode1, avlNode_t *pNode2)
{
 myAvlNode_t *pMyNode1 = (myAvlNode_t *)pNode1;
 myAvlNode_t *pMyNode2 = (myAvlNode_t *)pNode2;
 int rtnValue = 0; 
 if ((NULL == pNode1) || (NULL == pNode2))
 {
  ASSERT(0);
  return ERROR;
 }

 rtnValue = (pMyNode1->key == pMyNode2->key) ? \
  0 : ((pMyNode1->key > pMyNode2->key) ? 1 : (-1));

 return rtnValue;
}

/* AVL树结点内存释放函数 */
void nodeFree(avlNode_t *pNode)
{
 myAvlNode_t *pMyNode = (myAvlNode_t *)pNode;
 if (NULL == pNode)
 {
  ASSERT(0);
  return;
 }

 free(pMyNode);

 return;
}

/* AVL树结点数据打印函数 */
void nodePrint(avlNode_t *pNode)
{
 myAvlNode_t *pMyNode = (myAvlNode_t *)pNode;
 if (NULL == pNode)
 {
  ASSERT(0);
  return;
 }

 printf(“%d\t”, pMyNode->key);

 return;
}

/****************************************************************/
/************************ 栈的相关函数 **************************/

/* 栈初始化函数 */
static void stackInit(stack_t **ppStack)
{
 if (NULL == ppStack)
 {
  ASSERT(0);
  return;
 }
 
 *ppStack = (stack_t *)malloc(sizeof(stack_t));
 if (NULL == *ppStack)
 {
  ASSERT(0);
  return;
 }
 memset((char *)(*ppStack), 0, sizeof(stack_t));

 return;
}

/* 压栈函数 */
static void stackPush(stack_t *pStack, avlNode_t *pNode, pos_e pos)
{
 if (NULL == pStack)
 {
  ASSERT(0);
  return;
 }
 if (STACK_SIZE == pStack->top)
 {
  printf(“stackPush:Stack is full!\n”);
  return;
 }

 (pStack->buff)[pStack->top] = pNode;
 (pStack->pos)[pStack->top] = pos;
 pStack->top++;

 return;
}

/* 出栈函数 */
static void stackPop(stack_t *pStack, avlNode_t **pNode, pos_e *pPos)
{
 if ((NULL == pStack) || (NULL == pNode) || (NULL == pPos))
 {
  ASSERT(0);
  return;
 }
 if (0 == pStack->top)
 {
  printf(“stackPop:Stack is empty!\n”);
  return;
 }

 pStack->top–;
 *pNode = (pStack->buff)[pStack->top];
 *pPos = (pStack->pos)[pStack->top];
 
 return;
}

/* 取栈顶元素函数 */
static void stackGet(stack_t *pStack, avlNode_t **pNode, pos_e *pPos)
{
 if ((NULL == pStack) || (NULL == pNode) || (NULL == pPos))
 {
  ASSERT(0);
  return;
 }
 if (0 == pStack->top)
 {
  printf(“stackPop:Stack is empty!\n”);
  return;
 }

 *pNode = (pStack->buff)[pStack->top – 1];
 *pPos = (pStack->pos)[pStack->top – 1];
 
 return;
}

/* 判栈是否为空:若空返回TRUE,非空返回FALSE */
static BOOL stackIsEmpty(stack_t *pStack)
{
 if (NULL == pStack)
 {
  ASSERT(0);
  return FALSE;
 }
 
 return (0 == pStack->top) ? TRUE : FALSE;
}

/* 栈元素替换函数 */
static void stackReplace(stack_t *pStack, avlNode_t *pInitNode, avlNode_t *pRepNode)
{
 int idx = 0;
 if (NULL == pStack)
 {
  ASSERT(0);
  return;
 }

 for (idx = pStack->top; idx >= 0; idx –)
 {
  if (pInitNode == (pStack->buff)[idx])
  {
   (pStack->buff)[idx] = pRepNode;
   break;
  }
 }

 return;
}

/* 栈内存释放函数 */
static void stackFree(stack_t **ppStack)
{
 if ((NULL == ppStack) || (NULL == *ppStack))
 {
  ASSERT(0);
  return;
 }

 free(*ppStack);
 *ppStack = NULL;

 return;
}

/****************************************************************/
/* ************************* The End ************************** */



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