github項目地址:https://github.com/jobbofhe/Learning_Data_Structure_and_Algorithms/tree/master/c_cpp
什麼是AVL樹?
AVL樹是根據它的發明者G.M. Adelson-Velsky和E.M. Landis命名的。
AVL樹的特點?
它是最先發明的自平衡二叉查找樹,也被稱爲高度平衡樹。相比於"二叉查找樹",它的特點是:AVL樹中任何節點的兩個子樹的高度最大差別爲1。
AVL樹的算法效率?
AVL樹的查找、插入和刪除在平均和最壞情況下都是O(logn)。
學習AVL樹重點是什麼?
在AVL樹中插入或刪除節點後,使得高度之差大於1。此時,AVL樹的平衡狀態就被破壞,它就不再是一棵二叉樹;爲了讓它重新維持在一個平衡狀態,就需要對其進行旋轉處理。學AVL樹,重點的地方也就是它的旋轉算法。
爲什麼設計AVL樹(應用場景是什麼)?
- AVL樹適合用於插入刪除次數比較少,但查找多的情況。
- AVL樹相對其他數據結構應用的比較少。windows對進程地址空間的管理用到了AVL樹。
/*
* @Author: jobbofhe
* @Date: 2019-08-18 16:54:31
* @Last Modified by: Administrator
* @Last Modified time: 2019-08-26 20:13:21
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
// 定義節點
typedef int Type;
typedef struct AVLTreeNode
{
Type key; // 值
int height; // 樹的高度
struct AVLTreeNode *left;
struct AVLTreeNode *right;
}Node, *AVLTree;
// 本文采用維基百科上的定義:樹的高度爲最大層次。
// 即空的二叉樹的高度是0,非空樹的高度等於它的最大層次(根的層次爲1,根的子節點爲第2層,依次類推)。
#define HEIGHT(p) ((p == NULL) ? 0 : ((Node *)(p))->height)
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
int avltree_height(AVLTree tree);
// 創建節點
static Node *avltree_create_node(Type key, Node *left, Node *right);
static Node *left_left_rotation(AVLTree keyRoot);
static Node *right_right_rotation(AVLTree keyRoot);
/**
* LR 旋轉: 要恢復,先右單旋,後左單旋
*/
static Node *left_right_rotation(AVLTree keyRoot);
static Node *right_left_rotation(AVLTree keyRoot);
/**
* 將結點插入AVL樹,返回根節點
*/
Node *avltree_insert_node(AVLTree tree, Type key);
/**
* 遞歸實現
* 查找書中值爲 key的節點
* @return [返回找到的節點]
*/
Node *avltree_search(AVLTree tree, Type key);
/**
* 循環實現
* 查找書中值爲 key的節點
* @return [返回找到的節點]
*/
Node *loop_avltree_search(AVLTree tree, Type key);
/**
* 獲取樹中最大的節點
* 最右邊的節點最大
* @param tree [description]
* @return [description]
*/
Node *avltree_max_node(AVLTree tree);
/**
* 獲取書中最小的節點
* 最左邊的節點最小
* @param tree [description]
* @return [description]
*/
Node *avltree_min_node(AVLTree tree);
/**
* 刪除節點
* @param tree [樹根節點]
* @param node [被刪除的節點]
* @return [返回根節點]
*/
Node *avltree_delete_node(AVLTree tree, Node *node);
/**
* 根據key 值闡述樹中的節點
* @return [返回根節點]
*/
Node *avltree_delete(AVLTree tree, Type key);
/**
* 銷燬樹
* @param tree [description]
*/
void avltree_destroy(AVLTree tree);
/**
* 打印樹
* @param tree [節點]
* @param key [key]
* @param direction [方向 0:根節點, -1: 左孩子, 1:右孩子]
*/
void avltree_print(AVLTree tree, Type key, int direction);
// 前根序遍歷
void pre_order_bstree(AVLTree tree);
// 中根序遍歷
void middle_order_bstree(AVLTree tree);
// 後根序遍歷
void behind_order_bstree(AVLTree tree);
int avltree_height(AVLTree tree)
{
return HEIGHT(tree);
}
// 創建節點
static Node *avltree_create_node(Type key, Node *left, Node *right)
{
Node *p = (Node *)malloc(sizeof(Node));
if (!p)
{
return NULL;
}
p->key = key;
p->height = 0;
p->left = left;
p->right = right;
return p;
}
static Node *left_left_rotation(AVLTree keyRoot)
{
// 失去平衡的節點
AVLTree keyTmp;
keyTmp = keyRoot->left;
keyRoot->left = keyTmp->right;
keyTmp->right = keyRoot;
keyRoot->height = MAX(HEIGHT(keyRoot->left), HEIGHT(keyRoot->right)) + 1;
keyTmp->height = MAX(HEIGHT(keyTmp->left), keyRoot->height) + 1;
return keyTmp;
}
static Node *right_right_rotation(AVLTree keyRoot)
{
// 失去平衡的節點
AVLTree keyTmp;
keyTmp = keyRoot->right;
keyRoot->right = keyTmp->left;
keyTmp->left = keyRoot;
keyRoot->height = MAX(HEIGHT(keyRoot->left), HEIGHT(keyRoot->right)) + 1;
keyTmp->height = MAX(HEIGHT(keyTmp->right), keyRoot->height) + 1;
return keyTmp;
}
/**
* LR 旋轉: 要恢復,先右單旋,後左單旋
*/
static Node *left_right_rotation(AVLTree keyRoot)
{
keyRoot->left = right_right_rotation(keyRoot->left);
return left_left_rotation(keyRoot);
}
static Node *right_left_rotation(AVLTree keyRoot)
{
keyRoot->right = left_left_rotation(keyRoot->right);
return right_right_rotation(keyRoot);
}
/**
* 將結點插入AVL樹,返回根節點
*/
Node *avltree_insert_node(AVLTree tree, Type key)
{
if (NULL == tree)
{
tree = avltree_create_node(key, NULL, NULL);
if (NULL == tree)
{
printf("[%s] 創建節點失敗!\n");
return NULL;
}
}
else if (key > tree->key) // 插入的值大於節點的值,插入其右子樹
{
tree->right = avltree_insert_node(tree->right, key);
// 插入節點之後,檢查樹是否平衡
if (HEIGHT(tree->right) - HEIGHT(tree->left) == 2)
{
if (key > tree->right->key)
{
tree = right_right_rotation(tree);
}
else
{
tree = right_left_rotation(tree);
}
}
}
else if (key < tree->key)
{
tree->left = avltree_insert_node(tree->left, key);
if (HEIGHT(tree->left) - HEIGHT(tree->right) == 2)
{
if(key < tree->left->key)
{
tree = left_left_rotation(tree);
}
else
{
tree = left_right_rotation(tree);
}
}
}
else // 插入節點與樹中節點相等
{
printf("該節點已存在!不允許添加相同節點!\n");
}
tree->height = MAX(HEIGHT(tree->left), HEIGHT(tree->right)) + 1;
return tree;
}
/**
* 遞歸實現
* 查找書中值爲 key的節點
* @return [返回找到的節點]
*/
Node *avltree_search(AVLTree tree, Type key)
{
if(NULL == tree || tree->key == key)
{
return tree;
}
if (key < tree->key)
{
return avltree_search(tree->left, key);
}
else
{
return avltree_search(tree->right, key);
}
}
/**
* 循環實現
* 查找書中值爲 key的節點
* @return [返回找到的節點]
*/
Node *loop_avltree_search(AVLTree tree, Type key)
{
AVLTree p = tree;
while(p != NULL && p->key != key)
{
if (key < p->key)
{
p = p->left;
}
else
{
p = p->right;
}
}
return p;
}
/**
* 獲取樹中最大的節點
* 最右邊的節點最大
* @param tree [description]
* @return [description]
*/
Node *avltree_max_node(AVLTree tree)
{
Node *p = tree;
if (tree == NULL)
{
return NULL;
}
while(p->right != NULL)
{
p = p->right;
}
return p;
}
/**
* 獲取書中最小的節點
* 最左邊的節點最小
* @param tree [description]
* @return [description]
*/
Node *avltree_min_node(AVLTree tree)
{
Node *p = tree;
if (tree == NULL)
{
return NULL;
}
while(p->left != NULL)
{
p = p->left;
}
return p;
}
/**
* 刪除節點
* @param tree [樹根節點]
* @param node [被刪除的節點]
* @return [返回根節點]
*/
Node *avltree_delete_node(AVLTree tree, Node *node)
{
if (NULL == tree || NULL == node)
{
return tree;
}
// 要刪除的節點在 tree節點的左子樹
if (node->key < tree->key)
{
tree->left = avltree_delete_node(tree->left, node);
// 如果因爲刪除節點導致AVL樹失去平衡
if (HEIGHT(tree->right) - HEIGHT(tree->left) == 2)
{
// 刪除左子樹,導致右子樹失衡
Node *rTree = tree->right;
if (HEIGHT(rTree->left) > HEIGHT(rTree->right))
{
tree = right_left_rotation(tree);
}
else
{
tree = right_right_rotation(tree);
}
}
}
else if (node->key > tree->key) // 要刪除的節點在 tree節點的右子樹
{
tree->right = avltree_delete_node(tree->right, node);
if (HEIGHT(tree->left) - HEIGHT(tree->right) == 2)
{
// 刪除右子樹的節點,導致左子樹失衡
Node *lTree = tree->left;
if (HEIGHT(lTree->right) > HEIGHT(lTree->left))
{
tree = left_right_rotation(tree);
}
else
{
tree = left_left_rotation(tree);
}
}
}
else // 要刪除的節點就是根節點
{
// 如果樹的左右子樹都不爲空
if ((tree->left != NULL) && (tree->right != NULL))
{
if(HEIGHT(tree->left) > HEIGHT(tree->right))
{
// 左子樹高於右子樹
// 找出左子樹中最大的節點
// 將最大節點的值賦值給tree
// 將最大的節點刪除
Node *max = avltree_max_node(tree->left);
tree->key = max->key;
tree->left = avltree_delete_node(tree->left, max);
}
else
{
Node *min = avltree_min_node(tree->right);
tree->key = min->key;
tree->right = avltree_delete_node(tree->right, min);
}
}
else
{
// 至少有一個子樹爲空
Node *tmp = tree;
tree = tree->left != NULL ? tree->left : tree->right;
free(tmp);
}
}
return tree;
}
/**
* 根據key 值闡述樹中的節點
* @return [返回根節點]
*/
Node *avltree_delete(AVLTree tree, Type key)
{
Node * dst = avltree_search(tree, key);
if (dst != NULL)
{
avltree_delete_node(tree, dst);
}
return tree;
}
/**
* 銷燬樹
* @param tree [description]
*/
void avltree_destroy(AVLTree tree)
{
if (NULL == tree)
{
return;
}
if (tree->left)
{
avltree_destroy(tree->left);
}
if (tree->right)
{
avltree_destroy(tree->right);
}
free(tree);
}
/**
* 打印樹
* @param tree [節點]
* @param key [key]
* @param direction [方向 0:根節點, -1: 左孩子, 1:右孩子]
*/
void avltree_print(AVLTree tree, Type key, int direction)
{
if (tree == NULL)
{
return ;
}
if (direction == 0)
{
printf("%3d is root.\n", tree->key);
}
else
{
printf("%3d is %3d’s %6s child\n", tree->key, key, direction == 1 ? "right" : "left");
}
avltree_print(tree->left, tree->key, -1);
avltree_print(tree->right, tree->key, 1);
}
// 前根序遍歷
void pre_order_bstree(AVLTree tree)
{
if (NULL == tree)
{
return ;
}
printf("%d ", tree->key);
pre_order_bstree(tree->left);
pre_order_bstree(tree->right);
}
// 中根序遍歷
void middle_order_bstree(AVLTree tree)
{
if (NULL == tree)
{
return ;
}
middle_order_bstree(tree->left);
printf("%d ", tree->key);
middle_order_bstree(tree->right);
}
// 後根序遍歷
void behind_order_bstree(AVLTree tree)
{
if (NULL == tree)
{
return ;
}
behind_order_bstree(tree->left);
behind_order_bstree(tree->right);
printf("%d ", tree->key);
}
static int arr[]= {3,2,1,4,5,6,7,16,15,14,13,12,11,10,8,9};
#define ARRAY_SIZE(a) ( (sizeof(a)) / (sizeof(a[0])) )
int main(int argc, char const *argv[])
{
AVLTree root = NULL;
int i = 0;
printf("== 高度: %d\n", avltree_height(root));
printf("--> 新建結點: ");
for (i=0; i < ARRAY_SIZE(arr); ++i)
{
printf("%d ", arr[i]);
root = avltree_insert_node(root, arr[i]);
}
printf("\n--> 前序遍歷: ");
pre_order_bstree(root);
printf("\n--> 中序遍歷: ");
middle_order_bstree(root);
printf("\n--> 後序遍歷: ");
behind_order_bstree(root);
printf("\n");
printf("== 高度: %d\n", avltree_height(root));
printf("== 最小值: %d\n", avltree_min_node(root)->key);
printf("== 最大值: %d\n", avltree_max_node(root)->key);
printf("== 樹的詳細信息: \n");
avltree_print(root, root->key, 0);
int j = 0;
for ( ; j < 5; j++)
{
int tmp = rand() % 100;
root = avltree_insert_node(root, tmp);
}
printf("\n");
printf("== 高度: %d\n", avltree_height(root));
printf("== 最小值: %d\n", avltree_min_node(root)->key);
printf("== 最大值: %d\n", avltree_max_node(root)->key);
printf("== 樹的詳細信息: \n");
avltree_print(root, root->key, 0);
root = avltree_delete(root, 11);
printf("\n");
printf("== 高度: %d\n", avltree_height(root));
printf("== 最小值: %d\n", avltree_min_node(root)->key);
printf("== 最大值: %d\n", avltree_max_node(root)->key);
printf("== 樹的詳細信息: \n");
avltree_print(root, root->key, 0);
avltree_destroy(root);
return 0;
}