AVL树在ROS系统中应用广泛,如路由表管理模块和FEC表,这些大容量又操作频繁的数据,采用AVL树存储结构可以有效提高系统效率。
AVL树又称为高度平衡的二叉搜索树(BST),是1962年由两位俄罗斯数学家G.M.Adel’ son-Vel’sky和E.M.Landis在论文《An algorithm for theorganization of information》中提出的。引入它的目的,是为了提高BST的搜索效率,即减少平均搜索长度。为此,向BST中每插入或删除一个新结点时,就必须调整树的结构,使得BST继续保持平衡,从而尽可能降低树的高度。
下面先讲讲AVL树的一些基本概念:
AVL树的定义:一棵ALV树或者是空树,或者是具有下列性质的二叉搜索树:它的左子树和右子树都是AVL树,且左子树和右子树的高度之差的绝对值不超过1。
AVL树的高度:(固定节点数计算最大高度)
记N(h)为一棵高度为h的AVL树具有的最小节点数,则最坏情况是它的左右子树的高度不等,即一个是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)。
树的旋转:
在介绍插入和删除操作之前首先介绍树的旋转操作
树的旋转操作是为了改变树的结构,使其达到平衡。旋转总共分为左旋和右旋两类
如图为树的以B为轴左旋示意图(反过来看,从右到左是以A为轴右旋)。树的旋转操作要特别注意儿子节点是否为空
顶层节点是否为根节点。
AVL树的插入操作:
插入操作只会改变被插入节点到根节点路径上的节点的平衡因子。
因为在插入之前树是AVL树,因此各个节点的平衡因子是1,-1或0
一、如果路径上节点平衡因子是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情况类似,旋转后只需再次改变两个节点的平衡因子
如下图为RL的情况,LR类似,旋转后需要再次改变三个节点的平衡因子
至此,插入操作已经完成,可见最多多做两次旋转操作调整树的结构使之平衡。
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为例,称A为L不平衡
如果A的右节点的平衡因子是0,则进行一次左旋转,如图:
由于子树的高度和删除前一样,因此树已经平衡。
如果A的右节点的平衡因子是-1,则称为L-1不平衡,也要进行一次做旋转。
树的高度减少1,这使得上面的祖先节点可能不平衡,一次还要沿着路径在向上
寻找新的不平衡点,再次更新平衡因子,调整等。
如果A的右节点的平衡因子是1,则称为L1不平衡,要进行两次旋转。
此时要根据BL的情况决定A和B的新的平衡因子。
由于树的高度减少了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 ************************** */