【DSA】樹-AVL樹接口封裝(2)

github項目地址:https://github.com/jobbofhe/Learning_Data_Structure_and_Algorithms/tree/master/c_cpp

什麼是AVL樹?

AVL樹是根據它的發明者G.M. Adelson-VelskyE.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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章