平衡二叉树(AVL)的实现,附可运行C语言代码
最近几月一直在自学C语言和数据结构,先是写了排序二叉树,觉得平衡二叉树作为一个经典数据结构,有必要实现一下。
网上看了些资料,在AVL和红黑树之间考虑,最后个人还是倾向于AVL。
不同于标准AVL的是,笔者没有使用平衡因子,直接根据左右孩子的高度差值判断是否平衡。整个平衡二叉树是在普通二叉查找树的基础上修改得到的,对于学习数据结构的同学来说,这样逐步提高难度,写起来挑战性没那么大。
代码经测试是可以运行,并实现插入、删除、修改节点时都可以保持平衡。相对于普通二叉查找树,AVL在查找时效率高耗时短,但为了保持高度平衡,必须牺牲插入和删除操作的复杂度。本文将分步讲解如何编写平衡二叉树,全文最后附有完整代码。
当左右子树的高度差超过1时(即≥2,在实际处理时,等于2即为不平衡,进行调整操作,所以不会出现大于2的情况),整棵树失去平衡。写代码之前先了解AVL是如何使二叉树保持平衡,这里涉及到对节点的旋转操作,分四种情况,左左,右右,左右,右左。下面分别解释:
一、左左单旋转
在节点x的左孩子插入节点b
①x无右孩子,旋转节点a即可达到平衡
②x有右孩子c,旋转节点a后,根据a>c>x,需将节点c移动到a的左子树
函数代码如下:
static BTNode *singleRotateLL(BTree *BT, BTNode *phead)
{//不平衡情况为左左的单旋转操作
BTNode *temp; if(phead == NULL)
return ; temp = phead->lchild; if(temp->rchild != NULL){
phead->lchild = temp->rchild;
phead->lchild->height = tree_node_height(BT, phead->lchild);
}
else
phead->lchild = NULL; temp->rchild = phead;
if(temp->rchild->data == BT->phead->data){
BT->phead = temp;
}
phead = temp;
temp->rchild->height = tree_node_height(BT, temp->rchild);
temp->height = tree_node_height(BT, temp);
phead->height = tree_node_height(BT, phead); return phead;
}
二、右右单旋转
在节点x的右孩子插入节点b
①x无左孩子,旋转节点a即可达到平衡
②x有左孩子c,旋转节点a后,根据x>c>a,需将节点c移动到a的右子树
函数代码如下:
static BTNode *singleRotateRR(BTree *BT, BTNode *phead)
{//不平衡情况为右右的单旋转操作
BTNode *temp; if(phead == NULL)
return ; temp = phead->rchild; if(temp->lchild != NULL){
phead->rchild = temp->lchild;
phead->rchild->height = tree_node_height(BT, phead->rchild);
}
else
phead->rchild = NULL; temp->lchild = phead;
if(temp->lchild->data == BT->phead->data){
BT->phead = temp;
}
phead = temp;
temp->lchild->height = tree_node_height(BT, temp->lchild);
temp->height = tree_node_height(BT, temp);
phead->height = tree_node_height(BT, phead); return phead;
}
注:需要注意的是节点旋转后,节点赋值和高度的更新,初学者很容易忽略或是弄错赋值顺序
三、左右双旋转
在节点x的右孩子插入节点b
①x无左孩子,②x有左孩子c,这两种情况的处理相同,首先对x节点进行右右单旋转操作,然后对a节点进行左左单旋转操作
函数代码如下:
static BTNode *doubleRotateLR(BTree *BT, BTNode *phead)
{//不平衡情况为左右的双旋转操作
BTNode *temp; if(phead == NULL)
return ; temp = phead->lchild;
phead->lchild = singleRotateRR(BT, temp);
temp = phead;
phead = singleRotateLL(BT, temp); return phead;
}
四、右左双旋转
在节点x的右孩子插入节点b
①x无右孩子,②x有右孩子c,这两种情况的处理相同,首先对x节点进行左左单旋转操作,然后对a节点进行右右单旋转操作
函数代码如下:
static BTNode *doubleRotateRL(BTree *BT, BTNode *phead)
{//不平衡情况为右左的双旋转操作
BTNode *temp; if(phead == NULL)
return ; temp = phead->rchild;
phead->rchild = singleRotateLL(BT, temp);
temp = phead;
phead = singleRotateRR(BT, temp); return phead;
}
弄清楚了怎样通过旋转达到平衡状态,接下来一步一步构造平衡二叉树。
第一步,我们要在二叉树的节点中加一个属性:高度,在后面的插入和删除函数中将会用到。
结构体代码如下:
typedef struct _BTNode{
TYPE data;
int height;
struct _BTNode *lchild;
struct _BTNode *rchild;
}BTNode;
第二步,需要添加三个辅助函数,一是求节点的高度,而是遍历求树中每个节点的高度(在删除函数中会用到),三是求两个高度的最大值。
static int tree_node_height(BTree *BT, BTNode *phead)
{//求节点的高度,写成函数解决指针为空的情况,默认空节点的高度为-1,只有一个根节点的节点的高度为0,每多一层高度加1
if(phead != NULL){
if(phead->lchild == NULL && phead->rchild == NULL){
return ;
}
else{
return phead->height = max_height(tree_node_height(BT, phead->lchild), tree_node_height(BT, phead->rchild)) + ;
}
}
else{
return -;
}
} static void tree_height(BTree *BT, BTNode *phead)
{//遍历求树中每个节点的高度
if(phead == NULL)
return; tree_node_height(BT, phead);
if(phead->lchild != NULL)
tree_node_height(BT, phead->lchild);
if(phead->rchild != NULL)
tree_node_height(BT, phead->rchild);
} static int max_height(int height1, int height2)
{//求两个高度的最大值
if(height1 > height2)
return height1;
else
return height2;
}
第三步,插入
插入操作与二叉查找树的操作基本相同,只是在插入后需判断是否平衡,如果不平衡,进行旋转调整。因为BTNode没有使用父节点属性,所以需要用变量存储插入位置,以便调整后可以接回到二叉树上。树顶的根节点需特殊处理
static BOOL tree_add(BTree *BT, BTNode *phead, TYPE value)
{//按序插入结点
if(phead == NULL)
return ; if(phead->data == value)
return ; else{
if(phead->data > value){
if(phead->lchild == NULL){
BTNode *newnode = (BTNode*)calloc(, sizeof(BTNode));
newnode->data = value;
newnode->lchild = newnode->rchild = NULL;
phead->lchild = newnode;
}
else{
tree_add(BT, phead->lchild, value); //判断插入节点后是否平衡,并调整
BTNode *root;
if(phead = BT->phead)
root = phead;
else
root = phead->lchild; if(tree_node_height(BT, root->lchild) - tree_node_height(BT, root->rchild) == ){
if(root->lchild->data > value){
root = singleRotateLL(BT, root);
}
else{
root = doubleRotateLR(BT, root);
}
}
phead = root;
}
}
else{
if(phead->rchild == NULL){
BTNode *newnode = (BTNode*)calloc(, sizeof(BTNode));
newnode->data = value;
newnode->lchild = newnode->rchild = NULL;
phead->rchild = newnode;
}
else{
tree_add(BT, phead->rchild, value); //判断插入节点后是否平衡,并调整
BTNode *root;
if(phead = BT->phead)
root = phead;
else
root = phead->rchild; if(tree_node_height(BT, root->rchild) - tree_node_height(BT, root->lchild) == ){
if(root->rchild->data < value){
root = singleRotateRR(BT, root);
}
else{
root = doubleRotateRL(BT, root);
}
}
phead = root;
}
}
phead->height = tree_node_height(BT, phead);
return ;
} return ;
}
第四步,删除
平衡二叉树的删除操作比插入更复杂,因为删除后会引起一系列节点高度的改变,删除后将剩余子树接回二叉树时,要分三种情况处理,被删除节点是:顶部根节点、底部叶子(无子树)、普通节点。
static BOOL tree_del(BTree *BT, BTNode **phead, TYPE value)
{//删除结点
BTNode *temp;
BTNode *root;
int flag; //flag标记被删除的节点,默认顶部节点flag为0,左边节点flag为-1,右边节点flag为1 if(*phead == NULL)
return ; if(*phead == BT->phead){
flag = ;
root = *phead;
} else if((*phead)->lchild != NULL){
flag = -;
root = (*phead)->lchild;
} else if((*phead)->rchild != NULL){
flag = ;
root = (*phead)->rchild;
}
else if((*phead)->lchild == NULL && (*phead)->rchild == NULL)
root = *phead; if(root->data == value){
if(root->lchild != NULL){
temp = BT->search_max(BT, &root->lchild, );
temp->lchild = root->lchild;
temp->rchild = root->rchild;
free(root);
root = temp;
if(flag == )
BT->phead = root;
else
(*phead)->lchild = root;
}
else if(root->rchild != NULL){
temp = BT->search_min(BT, &root->rchild, );
temp->lchild = root->lchild;
temp->rchild = root->rchild;
free(root);
root = temp;
if(flag == )
BT->phead = root;
else
(*phead)->rchild = root;
}
else{
if(flag == )
free(*phead);
else if(flag = -){
free((*phead)->lchild);
(*phead)->lchild = NULL;
}
else if(flag = ){
free((*phead)->rchild);
(*phead)->rchild = NULL;
}
} tree_height(BT, BT->phead); //删除节点后,求每个节点的新高度 if(flag == )
return ;
if(flag == -){
if(tree_node_height(BT, (*phead)->rchild) - tree_node_height(BT, (*phead)->lchild) == ){
if((*phead)->rchild->rchild != NULL){
root = singleRotateRR(BT, *phead);
}
else{
root = doubleRotateRL(BT, *phead);
}
}
}
else{
if(tree_node_height(BT, (*phead)->lchild) - tree_node_height(BT, (*phead)->rchild) == ){
if((*phead)->lchild->lchild != NULL){
root = singleRotateLL(BT, *phead);
}
else{
root = doubleRotateLR(BT, *phead);
}
}
} return ;
}
else if(root->data > value)
return BT->del(BT, &root->lchild, value);
else
return BT->del(BT, &root->rchild, value); return ;
}
除了插入和删除操作,其他操作均与普通二叉查找树一样。
如果读者发现错误或有更好的处理方法,请指出,以便修改完善。
头文件binary.h代码:
#ifndef BINARY_H
#define BINARY_H typedef int TYPE;
typedef int BOOL; typedef struct _BTNode{
TYPE data;
int height;
struct _BTNode *lchild;
struct _BTNode *rchild;
}BTNode; typedef struct _BTree{
BTNode *phead; void(*init)(struct _BTree *BT, TYPE head_value);
void(*exit)(struct _BTree *BT);
void(*print)(struct _BTree *BT, BTNode *phead); BOOL(*add)(struct _BTree *BT, BTNode *phead, TYPE value);
BOOL(*del)(struct _BTree *BT, BTNode **phead, TYPE value);
BOOL(*del_tree)(struct _BTree *BT, BTNode **phead);
BOOL(*alter)(struct _BTree *BT, BTNode *phead, TYPE value, TYPE new_value);
BTNode *(*search)(struct _BTree *BT, BTNode *phead, TYPE value); BTNode *(*search_min)(struct _BTree *BT, BTNode **phead, int flag);
BTNode *(*search_max)(struct _BTree *BT, BTNode **phead, int flag); void(*pre_traverse)(struct _BTree *BT, BTNode *phead);
void(*mid_traverse)(struct _BTree *BT, BTNode *phead);
void(*last_traverse)(struct _BTree *BT, BTNode *phead); //以下为实现AVL所需函数
int (*node_height)(_BTree *BT, BTNode *phead);
void (*height)(_BTree *BT, BTNode *phead);
int (*max_height)(int height1, int height2);
BTNode *(*singleRotateLL)(_BTree *BT, BTNode *phead);
BTNode *(*singleRotateRR)(_BTree *BT, BTNode *phead);
BTNode *(*doubleRotateLR)(_BTree *BT, BTNode *phead);
BTNode *(*doubleRotateRL)(_BTree *BT, BTNode *phead);
}BTree; void tree_init(BTree *BT, TYPE value);
void tree_exit(BTree *BT); #endif
源文件binary.cpp代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h> #include "binary.h" void tree_init(BTree *BT, TYPE head_value);
void tree_exit(BTree *BT);
void tree_print(BTree *BT, BTNode *phead);
static BOOL tree_add(BTree *BT, BTNode *phead, TYPE value);
static BOOL tree_del(BTree *BT, BTNode **phead, TYPE value);
static BOOL tree_del_tree(BTree *BT, BTNode **phead);
static BOOL tree_alter(BTree *BT, BTNode *phead, TYPE value, TYPE new_value);
static BTNode *tree_search(BTree *BT, BTNode *phead, TYPE value);
static BTNode *tree_search_min(BTree *BT, BTNode **phead, int flag);
static BTNode *tree_search_max(BTree *BT, BTNode **phead, int flag);
static void tree_pre_traverse(BTree *BT, BTNode *phead);
static void tree_mid_traverse(BTree *BT, BTNode *phead);
static void tree_last_traverse(BTree *BT, BTNode *phead); //以下为实现AVL所需函数
static int tree_node_height(BTree *BT, BTNode *phead);
static void tree_height(BTree *BT, BTNode *phead);
static int max_height(int height1, int height2);
static BTNode *singleRotateLL(BTree *BT, BTNode *phead);
static BTNode *singleRotateRR(BTree *BT, BTNode *phead);
static BTNode *doubleRotateLR(BTree *BT, BTNode *phead);
static BTNode *doubleRotateRL(BTree *BT, BTNode *phead); void tree_init(BTree *BT, TYPE head_value)
{//初始化
BT->phead = (BTNode*)calloc(, sizeof(BTNode));
BT->phead->data = head_value; BT->phead->lchild = BT->phead->rchild = NULL; BT->add = tree_add;
BT->del = tree_del;
BT->print = tree_print;
BT->del_tree = tree_del_tree;
BT->alter = tree_alter;
BT->search = tree_search;
BT->search_min = tree_search_min;
BT->search_max = tree_search_max;
BT->pre_traverse = tree_pre_traverse;
BT->mid_traverse = tree_mid_traverse;
BT->last_traverse = tree_last_traverse;
BT->exit = tree_exit; BT->node_height = tree_node_height;
BT->height = tree_height;
BT->max_height = max_height;
BT->singleRotateLL = singleRotateLL;
BT->singleRotateRR = singleRotateRR;
BT->doubleRotateLR = doubleRotateLR;
BT->doubleRotateRL = doubleRotateRL;
} void tree_exit(BTree *BT)
{//结束操作
if(BT != NULL)
BT->del_tree(BT, &BT->phead);
} void tree_print(BTree *BT, BTNode *phead)
{//打印结点
if(phead != NULL)
printf("%d\n", phead->data);
} static BOOL tree_add(BTree *BT, BTNode *phead, TYPE value)
{//按序插入结点
if(phead == NULL)
return ; if(phead->data == value)
return ; else{
if(phead->data > value){
if(phead->lchild == NULL){
BTNode *newnode = (BTNode*)calloc(, sizeof(BTNode));
newnode->data = value;
newnode->lchild = newnode->rchild = NULL;
phead->lchild = newnode;
}
else{
tree_add(BT, phead->lchild, value); //判断插入节点后是否平衡,并调整
BTNode *root;
if(phead = BT->phead)
root = phead;
else
root = phead->lchild; if(tree_node_height(BT, root->lchild) - tree_node_height(BT, root->rchild) == ){
if(root->lchild->data > value){
root = singleRotateLL(BT, root);
}
else{
root = doubleRotateLR(BT, root);
}
}
phead = root;
}
}
else{
if(phead->rchild == NULL){
BTNode *newnode = (BTNode*)calloc(, sizeof(BTNode));
newnode->data = value;
newnode->lchild = newnode->rchild = NULL;
phead->rchild = newnode;
}
else{
tree_add(BT, phead->rchild, value); //判断插入节点后是否平衡,并调整
BTNode *root;
if(phead = BT->phead)
root = phead;
else
root = phead->rchild; if(tree_node_height(BT, root->rchild) - tree_node_height(BT, root->lchild) == ){
if(root->rchild->data < value){
root = singleRotateRR(BT, root);
}
else{
root = doubleRotateRL(BT, root);
}
}
phead = root;
}
}
phead->height = tree_node_height(BT, phead);
return ;
} return ;
} static BOOL tree_del(BTree *BT, BTNode **phead, TYPE value)
{//删除结点
BTNode *temp;
BTNode *root;
int flag; //flag标记被删除的节点,默认顶部节点flag为0,左边节点flag为-1,右边节点flag为1 if(*phead == NULL)
return ; if(*phead == BT->phead){
flag = ;
root = *phead;
} else if((*phead)->lchild != NULL){
flag = -;
root = (*phead)->lchild;
} else if((*phead)->rchild != NULL){
flag = ;
root = (*phead)->rchild;
}
else if((*phead)->lchild == NULL && (*phead)->rchild == NULL)
root = *phead; if(root->data == value){
if(root->lchild != NULL){
temp = BT->search_max(BT, &root->lchild, );
temp->lchild = root->lchild;
temp->rchild = root->rchild;
free(root);
root = temp;
if(flag == )
BT->phead = root;
else
(*phead)->lchild = root;
}
else if(root->rchild != NULL){
temp = BT->search_min(BT, &root->rchild, );
temp->lchild = root->lchild;
temp->rchild = root->rchild;
free(root);
root = temp;
if(flag == )
BT->phead = root;
else
(*phead)->rchild = root;
}
else{
if(flag == )
free(*phead);
else if(flag = -){
free((*phead)->lchild);
(*phead)->lchild = NULL;
}
else if(flag = ){
free((*phead)->rchild);
(*phead)->rchild = NULL;
}
} tree_height(BT, BT->phead); //删除节点后,求每个节点的新高度 if(flag == )
return ;
if(flag == -){
if(tree_node_height(BT, (*phead)->rchild) - tree_node_height(BT, (*phead)->lchild) == ){
if((*phead)->rchild->rchild != NULL){
root = singleRotateRR(BT, *phead);
}
else{
root = doubleRotateRL(BT, *phead);
}
}
}
else{
if(tree_node_height(BT, (*phead)->lchild) - tree_node_height(BT, (*phead)->rchild) == ){
if((*phead)->lchild->lchild != NULL){
root = singleRotateLL(BT, *phead);
}
else{
root = doubleRotateLR(BT, *phead);
}
}
} return ;
}
else if(root->data > value)
return BT->del(BT, &root->lchild, value);
else
return BT->del(BT, &root->rchild, value); return ;
} static BOOL tree_del_tree(BTree *BT, BTNode **phead)
{//删除二叉树
if(*phead == NULL)
return ; if((*phead)->lchild != NULL)
BT->del_tree(BT, &(*phead)->lchild);
if((*phead)->rchild != NULL)
BT->del_tree(BT, &(*phead)->rchild); free(*phead);
*phead = NULL; return ;
} static BOOL tree_alter(BTree *BT, BTNode *phead, TYPE value, TYPE new_value)
{//更改结点的值(先删除,后插入)
if(phead == NULL)
return ; if(value == new_value)
return ; if(BT->del(BT, &phead, value) != ){
if(BT->add(BT, phead, new_value) != )
return ;
else
return ;
}
else
return ;
} static BTNode *tree_search(BTree *BT, BTNode *phead, TYPE value)
{//查找结点
BTNode *temp; if(phead == NULL)
return NULL; if(phead->data == value)
return phead;
if(phead->lchild != NULL){
temp = BT->search(BT, phead->lchild, value);
if(temp != NULL)
return temp;
}
if(phead->rchild != NULL){
temp = BT->search(BT, phead->rchild, value);
if(temp != NULL)
return temp;
} return NULL;
} static BTNode *tree_search_min(BTree *BT, BTNode **phead, int flag)
{//查找最小结点
BTNode *temp; if(*phead == NULL)
return NULL; if((*phead)->lchild == NULL){
temp = *phead;
if(flag == )
*phead = (*phead)->rchild;
return temp;
}
else
return BT->search_min(BT, &(*phead)->lchild, flag);
} static BTNode *tree_search_max(BTree *BT, BTNode **phead, int flag)
{//查找最大结点
BTNode *temp; if(*phead == NULL)
return NULL; if((*phead)->rchild == NULL){
temp = *phead;
if(flag == )
*phead = (*phead)->lchild;
return temp;
}
else
return BT->search_max(BT, &(*phead)->rchild, flag);
} static void tree_pre_traverse(BTree *BT, BTNode *phead)
{//先序遍历二叉树
if(phead == NULL)
return; BT->print(BT, phead);
if(phead->lchild != NULL)
BT->pre_traverse(BT, phead->lchild);
if(phead->rchild != NULL)
BT->pre_traverse(BT, phead->rchild);
} static void tree_mid_traverse(BTree *BT, BTNode *phead)
{//中序遍历二叉树
if(phead == NULL)
return; if(phead->lchild != NULL)
BT->mid_traverse(BT, phead->lchild);
BT->print(BT, phead);
if(phead->rchild != NULL)
BT->mid_traverse(BT, phead->rchild);
} static void tree_last_traverse(BTree *BT, BTNode *phead)
{//后序遍历二叉树
if(phead == NULL)
return; if(phead->lchild != NULL)
BT->last_traverse(BT, phead->lchild);
if(phead->rchild != NULL)
BT->last_traverse(BT, phead->rchild);
BT->print(BT, phead);
} static int tree_node_height(BTree *BT, BTNode *phead)
{//求节点的高度,写成函数解决指针为空的情况,默认空节点的高度为-1,只有一个根节点的节点的高度为0,每多一层高度加1
if(phead != NULL){
if(phead->lchild == NULL && phead->rchild == NULL){
return ;
}
else{
return phead->height = max_height(tree_node_height(BT, phead->lchild), tree_node_height(BT, phead->rchild)) + ;
}
}
else{
return -;
}
} static void tree_height(BTree *BT, BTNode *phead)
{//遍历求树中每个节点的高度
if(phead == NULL)
return; tree_node_height(BT, phead);
if(phead->lchild != NULL)
tree_node_height(BT, phead->lchild);
if(phead->rchild != NULL)
tree_node_height(BT, phead->rchild);
} static int max_height(int height1, int height2)
{//求两个高度的最大值
if(height1 > height2)
return height1;
else
return height2;
} static BTNode *singleRotateLL(BTree *BT, BTNode *phead)
{//不平衡情况为左左的单旋转操作
BTNode *temp; if(phead == NULL)
return ; temp = phead->lchild; if(temp->rchild != NULL){
phead->lchild = temp->rchild;
phead->lchild->height = tree_node_height(BT, phead->lchild);
}
else
phead->lchild = NULL; temp->rchild = phead;
if(temp->rchild->data == BT->phead->data){
BT->phead = temp;
}
phead = temp;
temp->rchild->height = tree_node_height(BT, temp->rchild);
temp->height = tree_node_height(BT, temp);
phead->height = tree_node_height(BT, phead); return phead;
} static BTNode *singleRotateRR(BTree *BT, BTNode *phead)
{//不平衡情况为右右的单旋转操作
BTNode *temp; if(phead == NULL)
return ; temp = phead->rchild; if(temp->lchild != NULL){
phead->rchild = temp->lchild;
phead->rchild->height = tree_node_height(BT, phead->rchild);
}
else
phead->rchild = NULL; temp->lchild = phead;
if(temp->lchild->data == BT->phead->data){
BT->phead = temp;
}
phead = temp;
temp->lchild->height = tree_node_height(BT, temp->lchild);
temp->height = tree_node_height(BT, temp);
phead->height = tree_node_height(BT, phead); return phead;
}
static BTNode *doubleRotateLR(BTree *BT, BTNode *phead)
{//不平衡情况为左右的双旋转操作
BTNode *temp; if(phead == NULL)
return ; temp = phead->lchild;
phead->lchild = singleRotateRR(BT, temp);
temp = phead;
phead = singleRotateLL(BT, temp); return phead;
} static BTNode *doubleRotateRL(BTree *BT, BTNode *phead)
{//不平衡情况为右左的双旋转操作
BTNode *temp; if(phead == NULL)
return ; temp = phead->rchild;
phead->rchild = singleRotateLL(BT, temp);
temp = phead;
phead = singleRotateRR(BT, temp); return phead;
} int main(int argc, char* argv[])
{//测试
BTree testtree;
testtree.init = tree_init;
testtree.init(&testtree, ); testtree.add(&testtree, testtree.phead, );
testtree.add(&testtree, testtree.phead, );
testtree.add(&testtree, testtree.phead, );
testtree.add(&testtree, testtree.phead, );
testtree.add(&testtree, testtree.phead, );
testtree.add(&testtree, testtree.phead, );
testtree.add(&testtree, testtree.phead, );
testtree.add(&testtree, testtree.phead, ); testtree.pre_traverse(&testtree, testtree.phead);
printf("\n");
testtree.mid_traverse(&testtree, testtree.phead);
printf("\n");
testtree.last_traverse(&testtree, testtree.phead);
printf("\n"); printf("%d\n", (testtree.search(&testtree, testtree.phead, ))->data);
printf("\n"); testtree.del(&testtree, &testtree.phead, );
testtree.del(&testtree, &testtree.phead, );
testtree.del(&testtree, &testtree.phead, );
testtree.alter(&testtree, testtree.phead, , ); testtree.pre_traverse(&testtree, testtree.phead);
printf("\n");
testtree.mid_traverse(&testtree, testtree.phead);
printf("\n");
testtree.last_traverse(&testtree, testtree.phead);
printf("\n"); return ;
}
欢迎转载,请备注原始连接http://www.cnblogs.com/liuliuliu/p/3941748.html,并注明转载。
作者bibibi_liuliu,联系方式395985239@qq.com
平衡二叉树(AVL)的实现,附可运行C语言代码的更多相关文章
- 【数据结构】平衡二叉树—AVL树
(百度百科)在计算机科学中,AVL树是最先发明的自平衡二叉查找树.在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树.查找.插入和删除在平均和最坏情况下都是O(log n).增 ...
- Java 树结构实际应用 四(平衡二叉树/AVL树)
平衡二叉树(AVL 树) 1 看一个案例(说明二叉排序树可能的问题) 给你一个数列{1,2,3,4,5,6},要求创建一颗二叉排序树(BST), 并分析问题所在. 左边 BST 存在的问题分析: ...
- 数据结构与算法--从平衡二叉树(AVL)到红黑树
数据结构与算法--从平衡二叉树(AVL)到红黑树 上节学习了二叉查找树.算法的性能取决于树的形状,而树的形状取决于插入键的顺序.在最好的情况下,n个结点的树是完全平衡的,如下图"最好情况&q ...
- 二叉查找树(BST)、平衡二叉树(AVL树)(只有插入说明)
二叉查找树(BST).平衡二叉树(AVL树)(只有插入说明) 二叉查找树(BST) 特殊的二叉树,又称为排序二叉树.二叉搜索树.二叉排序树. 二叉查找树实际上是数据域有序的二叉树,即对树上的每个结点, ...
- 二叉查找树(BST)、平衡二叉树(AVL树)
二叉查找树(BST) 特殊的二叉树,又称为排序二叉树.二叉搜索树.二叉排序树. 二叉查找树实际上是数据域有序的二叉树,即对树上的每个结点,都满足其左子树上所有结点的数据域均小于或等于根结点的数据域,右 ...
- 平衡二叉树AVL - 插入节点后旋转方法分析
平衡二叉树 AVL( 发明者为Adel'son-Vel'skii 和 Landis)是一种二叉排序树,其中每一个节点的左子树和右子树的高度差至多等于1. 首先我们知道,当插入一个节点,从此插入点到树根 ...
- 二叉查找树、平衡二叉树(AVL)、B+树、联合索引
1. [定义] 二叉排序树(二拆查找树)中,左子树都比节点小,右子树都比节点大,递归定义. [性能] 二叉排序树的性能取决于二叉树的层数 最好的情况是 O(logn),存在于完全二叉排序树情况下,其访 ...
- 单点登录SSO:可一键运行的完整代码
单点登录方案不同于一个普通站点,它的部署比较繁琐:涉及到好几个站点,要改host.安装证书.配置HTTPS. 看到的不少这方面示例都是基于HTTP的,不认同这种简化: 1. 它体现不出混合HTTP/H ...
- SSL握手通信详解及linux下c/c++ SSL Socket代码举例(另附SSL双向认证客户端代码)
SSL握手通信详解及linux下c/c++ SSL Socket代码举例(另附SSL双向认证客户端代码) 摘自: https://blog.csdn.net/sjin_1314/article/det ...
随机推荐
- Cloudera Manager安装之时间服务器和时间客户端(二)
福利 => 每天都推送 欢迎大家,关注微信扫码并加入我的4个微信公众号: 大数据躺过的坑 Java从入门到架构师 人工智能躺过的坑 Java全栈大联盟 ...
- Web安全学习笔记之Nmap脚本使用指南
nmap是一个网络连接端扫描软件,用来扫描网上电脑开放的网络连接端.确定哪些服务运行在哪些连接端,并且推断计算机运行哪个操作系统.它是网络管理员必用的软件之一,以及用以评估网络系统安全. —— 来自百 ...
- pom.xml常用元素解析
project 最外层元素 modelVersion 指定Maven模型的版本号,对于Maven2和Maven3,它只能是4.0.0 version 版本信息 groupId 包id,会生成相应路径 ...
- 20145314郑凯杰《信息安全系统设计基础》第八周复习总结 Part A
20145314郑凯杰<信息安全系统设计基础>第八周复习总结 Part A 学习知识点内容总结 复习线索:http://group.cnblogs.com/topic/73069.html ...
- 20135302魏静静——linux课程第六周实验及总结
linux课程第六周实验及总结 实验及学习总结 1.进程描述符task_struct数据结构 进程的作用: 将信号.进程间通信.内存管理和文件系统联系起来 操作系统的三大功能: 进程管理.内存管理.文 ...
- ubuntu文字界面与图形界面切换
redhat: (据说是) 图形界面->文字界面:crtl+alt+F1~6 文字界面->图形界面:crtl+alt+F7 -------------------------------- ...
- dd命令参数解析
seek=N : 跳过N个输出块 skip=N : 跳过N个输入块 注意:sd卡的每个扇区的大小统一为512个字节
- [BZOJ1912]巡逻
Description Input 第一行包含两个整数 n, K(1 ≤ K ≤ 2).接下来 n – 1行,每行两个整数 a, b, 表示村庄a与b之间有一条道路(1 ≤ a, b ≤ n). Ou ...
- Android 图形基础类Rect,扎实基础助腾飞
转载请注明出处:王亟亟的大牛之路 上周把"垃圾桶动画写完了",然后这礼拜寻思着学习点啥,脑子闷逼了大半天,然后就找了点基础源码读读,把看的经历分享给大家. 先安利:https:// ...
- 【Semantic Segmentation】Segmentation综述
部分转自:https://zhuanlan.zhihu.com/p/37618829 一.语义分割基本介绍 1.1 概念 语义分割(semantic segmentation) : 就是按照" ...