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

[重温数据结构]一种自平衡二叉查找树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 =http://www.mamicode.com/ 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=gccCFLAGS= -g  LDFLAGS= ###########源文件,每增加一个目标,依样增加下面一段##############源文件列表1i:=1SOURCES_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 $@;    @$(CC) -MM $< > $@.1111;     sed s,/($*/)/.o[ :]*,/1.o $@ : ,g < $@.1111 > $@;      rm -f $@.1111

 

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