平衡二叉樹(Balanced Binary Tree 或 Height-Balanced Tree)又稱AVL樹
阿新 • • 發佈:2018-08-14
binary strong 但是 inf ++i 平衡二叉樹 data 效率 assert
平衡二叉樹(Balanced Binary Tree 或 Height-Balanced Tree)又稱AVL樹
(a)和(b)都是排序二叉樹,但是查找(b)的93節點就需要查找6次,查找(a)的93節點就需要查找3次,所以(b)的效率不高。
平衡二叉樹(Balanced Binary Tree 或 Height-Balanced Tree)又稱AVL樹。它或者是一顆空樹,或者是具有下列性質的二叉樹:它的左子樹和右子樹的深度只差的絕對值不超過1。若將二叉樹上節點的平衡因子BF(Balance Factor)定義為該節點的左子樹的深度減去它右子樹的深度,則平衡二叉樹上所有節點的平衡因子只可能是-1,0,1。只要二叉樹上有一個節點的平衡因子的絕對值大於1,則該二叉樹就是不平衡的。
上圖(a)是平衡二叉樹,(b)不是平衡二叉樹,因為有的節點的平衡因子大於1了。
插入節點的大致思路:
- 首先找到插入節點的位置,插入節點
- 插入節點後,調整相關節點的平衡因子
- 調整平衡因子後,如果發現樹不平衡了,就要進行節點的調整(單左旋轉,或單右旋轉,或雙旋轉(先左後又,或者先右後左)。
avl_tree.h
#ifndef __AVLTREE__ #define __AVLTREE__ #include<stdio.h> #include<malloc.h> #include<assert.h> #include "nodestack.h" #define Type int #define FALSE 0 #define TRUE 1 #define BOOL int typedef struct AVLNode{ Type data; struct AVLNode* left; struct AVLNode* right; int bf;//平衡因子 }AVLNode; typedef struct AVLTree{ struct AVLNode* root; }AVLTree; void init_avl_tree(AVLTree* avl); //插入節點 BOOL insert_avl(AVLTree* avl, Type t); #endif
avl_tree.c
#include "avl_tree.h" void init_avl_tree(AVLTree* avl){ avl->root = NULL; } AVLNode* malNode(Type x){ AVLNode* t = (AVLNode*)malloc(sizeof(AVLNode)); assert(NULL != t); t->data = x; t->left = NULL; t->right = NULL; t->bf = 0; return t; } //右旋轉 void rotateR(AVLNode** t){ AVLNode* subR = *t; *t = (*t)->left; subR->left = (*t)->right; (*t)->right = subR; (*t)->bf = 0; subR->bf = 0; } //左旋轉 void rotateL(AVLNode** t){ AVLNode* subL = *t; *t = (*t)->right; subL->right = (*t)->left; (*t)->left = subL; (*t)->bf = 0; subL->bf = 0; } //左右旋轉 void rotateLR(AVLNode** t){ AVLNode* subR = *t; AVLNode* subL = subR->left; *t = subL->right; subL->right = (*t)->left; (*t)->left = subL; if((*t)->bf <= 0){///?? subL->bf = 0; } else{ subL->bf = -1; } subR->left = (*t)->right; (*t)->right = subR; if((*t)->bf == -1){ subR->bf = 1;//??? } else{ subR->bf = 0;//??? } (*t)->bf = 0; } //右左旋轉 void rotateRL(AVLNode** t){ AVLNode* subL = *t; AVLNode* subR = subL->right; *t = subR->left; subR->left = (*t)->right; (*t)->right = subR; if((*t)->bf >= 0){ subR->bf = 0; } else{ subR->bf = 1; } subL->right = (*t)->left; (*t)->left = subL; if((*t)->bf == 1){ subL->bf = -1; } else{ subL->bf = 0; } (*t)->bf = 0; } //插入樹的節點 BOOL insert_avl_node(AVLNode** t, Type x){ AVLNode* p = *t; AVLNode* parent = NULL; nodestack st; init(&st); while(p != NULL){ if(x == p->data) return FALSE; parent = p; push(&st, parent); if(x < p->data) p = p->left; else p = p->right; } p = malNode(x); //插入節點為root節點 if(parent == NULL){ *t = p; return TRUE; } //插入節點不是root節點 if(x < parent->data) parent->left = p; else parent->right = p; //調整BF while(length(&st) != 0){ parent = getTop(&st); pop(&st); if(parent->left == p){ parent->bf--; } else{ parent->bf++; } if(parent->bf == 0){ break; } if(parent->bf == 1 || parent->bf == -1){ p = parent; } else{ //旋轉樹,讓樹變成平衡樹 int flag = (parent->bf < 0) ? -1 : 1; //符號相同,說明是一條直線,不是折線,所以單旋轉 if(p->bf == flag){ //因為是撇/,所以右旋轉 if(flag == -1){ rotateR(&parent); } //因為是捺\,所以左旋轉 else{ rotateL(&parent); } } //符號不同,說明是折線,所以雙旋轉 else{ //折線的角指向右> if(flag == 1){ rotateRL(&parent); } //折線的角指向左< else{ rotateLR(&parent); } } break; } } if(length(&st) == 0){ *t = parent; } else{ AVLNode* q = getTop(&st); if(q->data > parent->data){ q->left = parent; } else{ q->right = parent; } } clear(&st); return TRUE; } //插入節點 BOOL insert_avl(AVLTree* avl, Type t){ return insert_avl_node(&avl->root, t); }
avl_treemain.c
#include "avl_tree.h"
int main(){
AVLTree avl;
init_avl_tree(&avl);
//Type ar[] = {13,24,37,90,53};
//Type ar[] = {30,20,10};
//Type ar[] = {30,20,40,10,25,5,22,28,21};
//Type ar[] = {30,20,10};
//Type ar[] = {50,40,60,10,45,70,5,30,20,12};
Type ar[] = {30,20,50,10,40,70,60,80,55};
int n = sizeof(ar) / sizeof(Type);
for(int i = 0; i < n; ++i){
insert_avl(&avl, ar[i]);
}
return 0;
}
完整代碼
編譯方法:g++ -g nodestack.c avl_tree.c avl_treemain.c
平衡二叉樹(Balanced Binary Tree 或 Height-Balanced Tree)又稱AVL樹