[重温数据结构]一种自平衡二叉查找树avl树的实现方法

最近重温《数据结构》,发现其中的东西我上学的时候几乎都没写过。。。 惭愧啊。于是打算一一写点。算是对我逝去青春的纪念。。。

avl树的代码网上有很多, 这个在平衡二叉树里面算是比较简单的。 需要注意的就是树的平衡因子和其子树的平衡因子符号相反的旋转情况。这个在函数avl_rotate_right等中有处理. 目前只做了插入,删除等哪天想做了再做吧。

avl.h

 1 #define INSERT_ERROR -1
 2 #define INSERT_OK 1
 3
 4 #define LEFT_LEAN 2
 5 #define RIGHT_LEAN -2
 6 #define LEFT_LEAN_A_BIT 1
 7 #define RIGHT_LEAN_A_BIT -1
 8 #define NOT_LEAN 0
 9
10 struct AvlNode;
11 typedef struct AvlNode{
12     struct AvlNode* left;          /*left sub tree*/
13     struct AvlNode* right;         /*left sub tree*/
14     unsigned int  key;
15     void *data;
16     unsigned int  height;   /*current height*/
17  //   int bf;                 /*balance param*/
18 }AvlNode;
19
20 typedef struct {
21     AvlNode *root;
22 }AvlTree;
23
24
25 extern int AvlInsert( AvlTree* tree,   void* data , int key );
26 extern int AvlDel( AvlTree* tree,   int key  );
27 extern void* AvlFindData( AvlTree* tree,   int key  );
28 extern AvlTree* AvlCreateTree();

avl.c

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <stdlib.h>
  4 #include "avl.h"
  5
  6 /*************
  7 current: current sub-tree to be inserted
  8 data : data to be inserted
  9 key   : key
 10 **************/
 11 static int avl_insert_into(AvlNode** current, void* data,int key);
 12 static void avl_rotate_left(AvlNode** current);
 13 static void avl_rotate_right(AvlNode** current);
 14 static AvlNode* avl_create_node(void* data, int key);
 15 static unsigned avl_adjust_height(AvlNode* node);
 16 static int avl_is_balance(AvlNode* node);
 17
 18 AvlNode* avl_create_node(void* data, int key)
 19
 20 {
 21     AvlNode* node = malloc(sizeof(AvlNode));
 22     node->left = NULL;
 23     node->right = NULL;
 24     node->key = key;
 25     node->data = data;
 26     node->height = 1;
 27 }
 28
 29
 30 unsigned avl_adjust_height(AvlNode* node)
 31 {
 32     unsigned height;
 33     if(!node->left && !node->right){
 34         node->height = 1;
 35         return  node->height;
 36     }
 37     if(!node->left){
 38         node->height = node->right->height + 1;
 39         return node->height;
 40     }
 41     if(!node->right){
 42         node->height = node->left->height + 1;
 43         return node->height;
 44     }
 45     node->height = node->left->height > node->right->height ?  node->left->height + 1  : node->right->height + 1 ;
 46     return node->height;
 47 }
 48
 49 //if th avl tree is balance? the (left_h - right_h) is balance f
 50 int avl_is_balance(AvlNode* current){
 51     unsigned left_h , right_h;
 52     if(!current->left)
 53         left_h = 0;
 54     else
 55         left_h = current->left->height;
 56
 57     if(!current->right)
 58         right_h = 0;
 59     else
 60         right_h = current->right->height;
 61
 62     return left_h -right_h;
 63 }
 64
 65 int avl_insert_into(AvlNode **current_addr, void *data,int key)
 66 {
 67     AvlNode *current = NULL;
 68
 69     if(!current_addr)
 70         return INSERT_ERROR;
 71     else
 72         current= *current_addr;
 73
 74     if(!current){
 75         current = avl_create_node(data , key);
 76         avl_adjust_height(current);
 77         *current_addr = current;
 78         return INSERT_OK;
 79     }
 80
 81     /*insert into left or right*/
 82     if(key > current->key){
 83         if(INSERT_ERROR  == avl_insert_into( &current->right, data, key ))
 84                 return INSERT_ERROR;
 85     } else if(key < current->key) {
 86          if(INSERT_ERROR == avl_insert_into( &current->left, data , key) )
 87                 return  INSERT_ERROR;
 88     } else
 89         return INSERT_ERROR;
 90
 91     avl_adjust_height(current);
 92     /*if not balance rotate*/
 93     switch(avl_is_balance(current))
 94     {
 95         case LEFT_LEAN:
 96             avl_rotate_right(current_addr);
 97             break;
 98         case RIGHT_LEAN:
 99             avl_rotate_left(current_addr);
100             break;
101         default:
102             break;
103     }
104     return INSERT_OK;
105 }
106
107
108 void avl_rotate_left(AvlNode **current_addr)
109 {
110     AvlNode *current = *current_addr;
111     if( LEFT_LEAN_A_BIT == avl_is_balance(current->right) )
112         avl_rotate_right(&current->right);
113
114     AvlNode* tmp =  current->right;
115     current->right = current->right->left;
116     tmp->left = current;
117     current = tmp;
118     *current_addr = tmp;
119     avl_adjust_height(current->left);
120     avl_adjust_height(current);
121 }
122
123
124 void avl_rotate_right(AvlNode **current_addr)
125 {
126     AvlNode *current = *current_addr;
127     if( RIGHT_LEAN_A_BIT == avl_is_balance(current->left) ) {
128         avl_rotate_left(&current->left);
129     }
130     AvlNode* tmp = current->left;
131     current->left = current->left->right;
132     tmp->right =  current;
133     current = tmp;
134     *current_addr = tmp;
135     avl_adjust_height(current->right);
136     avl_adjust_height(current);
137 }
138
139 AvlTree* AvlCreateTree()
140 {
141    AvlTree* tree = (AvlTree*)malloc(sizeof(AvlTree));
142    return tree;
143 }
144
145 int AvlInsert( AvlTree* tree,  void* data , int key  )
146 {
147     return avl_insert_into( &tree->root, data, key);
148 }
149
150 int AvlDel( AvlTree* tree,   int key  )
151 {
152     return 0;
153 }
154
155
156 void* AvlFindData( AvlTree* tree,   int key  )
157 {
158     return NULL;
159 }

testmain.c

 1 #include "stdio.h"
 2 #include "avl.h"
 3
 4
 5 int main()
 6 {
 7     AvlTree* tree = AvlCreateTree();
 8     AvlInsert(tree, NULL, 1);
 9     AvlInsert(tree, NULL, 3);
10     AvlInsert(tree, NULL, 5);
11     AvlInsert(tree, NULL, 7);
12     AvlInsert(tree, NULL, 6);
13     AvlInsert(tree, NULL, 9);
14     AvlInsert(tree, NULL, 8);
15     AvlInsert(tree, NULL, 0);
16     AvlInsert(tree, NULL, 11);
17     AvlInsert(tree, NULL, 4);
18     AvlInsert(tree, NULL, 2);
19 }

Makefile

PRJ_ROOT=$(pwd)
CC=gcc
CFLAGS= -g
LDFLAGS= 

###########源文件,每增加一个目标,依样增加下面一段#############
#源文件列表1
i:=1
SOURCES_C_$(i):= testmain.c  avl.c   #在这里添加、修改当前目标需要的C源码
TARGET_$(i):=avl        #目标名称
OBJS_C_$(i):= $(patsubst %.c,%.o, $(SOURCES_C_$(i)))
OBJS_$(i):= $(OBJS_C_$(i))

#######目标和清除 每增加一个目标,依样增加一个target##########
all: $(TARGET_1)
    @echo "outputfile : $(TARGET_1) "
clean:
    rm -f *.o  *.d  $(TARGET_1)

##########目标, 每增加一个目标,依样增加下面一段#############
#目标1
$(TARGET_1):$(OBJS_1)
    $(CC) $(OBJS_1) $(LDFLAGS) -o $(TARGET_1)

###########包含 每增加一个目标,依样增加下面一行#############
sinclude $(OBJS_1:.o=.d)

#下面这边都是获取依赖关系 ,属于约定俗成的写法
%.d: %.c
    @rm -f [email protected];
    @$(CC) -MM $< > [email protected]1111;     sed ‘s,/($*/)/.o[ :]*,/1.o [email protected] : ,g‘ < [email protected]1111 > [email protected];      rm -f [email protected]1111
时间: 2024-10-10 07:15:47

[重温数据结构]一种自平衡二叉查找树avl树的实现方法的相关文章

平衡二叉查找树——AVL树

二叉查找树在最坏情况下高度可能为N-1,即插入元素时后插入的元素总比以前插入的元素大或者小.为了解决这种不平衡的情况,引入了平衡条件来限制树中节点的深度不能过深,其中最老的一种平衡树称为AVL树.这种树限制树中每个节点的左右子树的高度相差不能超过一.(另一种更严格的树限制节点的左右子树高度必须相等,但这样的树要求树中的节点数目为2的k次幂减1,是一种理想平衡树,但是要求太严格,无法实际使用.) AVL树平衡条件分析 AVL树是一棵特殊的二叉查找树,对AVL树的操作中,除了插入操作与普通二叉查找树

13、自平衡二叉查找树AVL

1 package ren.laughing.datastructure.baseImpl; 2 3 /** 4 * 自平衡二叉查找树AVL 继承二叉查找树 5 * 6 * @author Laughing_Lz 7 * @time 2016年4月20日 8 */ 9 public class AVLTree extends BSTree { 10 /** 11 * 统一平衡方法 旋转操作 12 * 13 * @param z 14 * z是失衡的结点 15 * @return 返回平衡后子树的

二叉查找树(BST),平衡二叉查找树(AVL),红黑树(RBT),B~/B+树(B-tree)的比较

http://www.iteye.com/topic/614070 此少侠总结的特棒,直接收藏了. 我们这个专题介绍的动态查找树主要有: 二叉查找树(BST),平衡二叉查找树(AVL),红黑树(RBT),B~/B+树(B-tree).这四种树都具备下面几个优势: (1) 都是动态结构.在删除,插入操作的时候,都不需要彻底重建原始的索引树.最多就是执行一定量的旋转,变色操作来有限的改变树的形态.而这些操作所付出的代价都远远小于重建一棵树.这一优势在<查找结构专题(1):静态查找结构概论 >中讲到

【查找结构3】平衡二叉查找树 [AVL]

在上一个专题中,我们在谈论二叉查找树的效率的时候.不同结构的二叉查找树,查找效率有很大的不同(单支树结构的查找效率退化成了顺序查找).如何解决这个问题呢?关键在于如何最大限度的减小树的深度.正是基于这个想法,平衡二叉树出现了. 平衡二叉树的定义 (AVL—— 发明者为Adel'son-Vel'skii 和 Landis) 平衡二叉查找树,又称 AVL树. 它除了具备二叉查找树的基本特征之外,还具有一个非常重要的特点:它 的左子树和右子树都是平衡二叉树,且左子树和右子树的深度之差的绝对值(平衡因子

数据结构14.自平衡二叉查找树_AVL树

引言 在计算机科学中,AVL树是最先发明的自平衡二叉查找树.在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树.查找.插入和删除在平均和最坏情况下都是O(log n).增加和删除可能需要通过一次或多次树旋转来重新平衡这个树. AVL树得名于它的发明者G.M. Adelson-Velsky和E.M. Landis,他们在1962年的论文<An algorithm for the organization of information>中发表了它. 一. AVL树定义 平衡

平衡二叉查找树AVL

1.AVL简介 这篇文章我们要介绍的是能够在key插入时一直保持平衡的二叉查找树(AVL树,AVL是发明者的名字缩写) 利用AVL实现ADT MAP,基本上与BST的实现相同.不同之处在于二叉树的生成与维护过程. 2.AVL中的概念 AVL树的实现中,需要对每个节点跟踪"平衡因子balance factor"参数. 平衡因子是根据节点的左右子树的高度来定义的.确切的来说,是左右子树的高度差.balanceFactor = height(leftSubTree) - height(rig

数据结构与算法系列----平衡二叉树(AVL树)

一:背景 平衡二叉树(又称AVL树)是二叉查找树的一个进化体,由于二叉查找树不是严格的O(logN),所以引入一个具有平衡概念的二叉树,它的查找速度是O(logN).所以在学习平衡二叉树之前,读者需要了解二叉查找树的实现,具体链接:二叉查找树 那么平衡是什么意思?我们要求对于一棵二叉查找树 ,它的每一个节点的左右子树高度之差不超过1.(对于树的高度的约定:空节点高度是0:叶子节点高度是1.)例如下图: 如果我们的二叉查找树是不平衡该怎么办?进行旋转.经过分析发现,出现不平衡无外乎四种情况,下面我

看数据结构写代码(57) AVL树的删除

上一节 已经说了 AVL树的插入 操作,可是 只有 插入,没有删除,怎么能叫 动态 查找表呢. 呵呵,博主 赶紧 去 研究了一番.下面 是成果: AVL树的删除 大致 分为 两大块: 1. 查找节点 并 删除 2. 保持 删除 后 平衡因子的 影响 1. 首先 找到 这个 节点,如果 节点 不存在,直接 退出 函数 if (*tree == NULL){//没找到 return false; } 2.如果 存在,分为 四种情况:(根 二叉 排序树的 删除 类似) 1.节点 为 叶子 节点,直接

二叉树-二叉查找树-AVL树

一.二叉树 定义:每个节点都不能有多于两个的儿子的树. 二叉树节点声明: 1 struct treeNode 2 { 3 elementType element; 4 treeNode * left; 5 treeNode * right; 6 } 应用: 中缀表达式——>后缀表达式(栈的应用)——>表达式树(栈的应用2) 栈的应用2:读取后缀表达式,操作数入栈,遇操作符后,指向栈里前两位元素t1和t2的指针出栈(t1先弹出,作为该操作符的右儿子),并将指向该操作符的指针入栈. 二.二叉查找树