算法与数据结构☞自平衡二叉树☞AVL树

266 阅读3分钟

AVL树

  1. 是一棵二叉树,任意节点至多2个子节点;
  2. 是一棵二叉排序树,任一节点的左子节点的数据都比自身数据小,右子节点的数据都比自身数据大;
  3. 任意节点的子树高度之差不超过1。

AVL树 “插入删除三步走”

  1. 找到要插入、删除的位置,进行插入或删除操作;
  2. 检查树的平衡性,找到失衡节点(递归);
  3. 辨别失衡节点的形态,进行相应的高度调整操作。

Q1:怎么找到插入的位置?
A: 根据二叉排序树的性质。

  • 如果树的根节点为空,则用新节点替换根节点,高度为 0;
  • 如果要插入的数据小于根节点的数据,则在树的左子树中查找插入位置;
  • 如果要插入的数据大于根节点的数据,则在树的右子树中查找插入位置。

AVL树节点的定义

#include <stdio.h>
#include <stdlib.h>

typdef int DataType;

/**
 * @data: 数据域
 * @left: 指向左子节点的指针
 * @right: 指向右子节点的指针
 * @height: 树的高度(子树高者高度+1)
typedef struct avl_node {
    DataType data;
    struct avl_node* left;
    struct avl_node* right;
    int height;
} AVLNode;

查找操作(非递归)

AVLNode* Find(AVLNode* root, DataType data) {
    if(root == NULL) {
        return NULL;
    }
    while(1) {
        if(data == root->data)
            return root;
        if(data < root->data && root->left != NULL) {
            root = root->left;
        else if(data > root->data && root->right != NULL) {
            root = root->right;
        else
            return NULL;
    }
}

计算高度

int HEIGHT(AVLNode* root) {
    if(root == NULL) {
        return 0;
    }
    else if(root->left == NULL && root->right == NULL) {
        return 1;
    }
    else {
        return HEIGHT(root->left) > HEIGHT(root->right) ? root->left->height+1 : root->right->height+1;
    }
}

前序、中序、后序遍历

void PreOrderTraverse(AVLNode* root) {
    if(root != NULL) {
        printf("data=%d, height=%d\n", root->data, root->height);
        PreOrderTraverse(root->left);
        PreOrderTraverse(root->right);
    }
}

void InOrderTraverse(AVLNode* root) {
    if(root != NULL) {
        InOrderTraverse(root->left);
        printf("data=%d, height=%d\n", root->data, root->height);
        InOrderTraverse(root->right);
    }
}

void PostOrderTraverse(AVLNode* root) {
    if(root != NULL) {
        PostOrderTraverse(root->left);
        PostOrderTraverse(root->right);
        printf("data=%d, height=%d\n", root->data, root->height);
    }
}

旋转

AVLNode* L(AVLNode* node) {
    AVLNode* t1 = node->left->right;
    AVLNode* t2 = node->left;
    node->left->right = node;
    node->left = t1;
    node = t2;
    node->right->height = HEIGHT(node->right);
    node->height = HEIGHT(node);
    return node;
}

AVLNode* R(AVLNode* node) {
    AVLNode* t1 = node->right->left;
    AVLNode* t2 = node->right;
    node->right->left = node;
    node->right = t1;
    node = t2;
    node->left->height = HEIGHT(node->left);
    node->height = HEIGHT(node);
    return node;
}

插入

AVLNode* Insert(AVLNode* root, DataType data) {
    AVLNode* t1 = NULL;
    AVLNode* t2 = NULL;
    if(root == NULL) {
        root = (AVLNode*)malloc(sizeof(struct AVLNode));
        if(root == NULL) {
            perror("malloc failed");
            return NULL;
        }
        root->data = data;
        root->left = NULL;
        root->right = NULL:
        root->height = 0;
    }
    else if(data < root->data) {
        root->left = Insert(root->left, data);
        if(HEIGHT(root->left) - HEIGHT(root->right) > 1 {
            if(data < root->left->data) { // <=> HEIGHT(root->left->left > HEIGHT(root->left->right)
                root = L(root);
            } else {
                root->left = R(root->left);
                root = L(root);
            }
        }
    }
    else if(data > root->data) {
        root->right = Insert(root->right, data);
        root->height = HEIGHT(root);
        if(HEIGHT(root->left) - HEIGHT(root->right) < -1 {
            if(data > root->right->data) {
                root = R(root);
            } else {
                root->right = L(root->right);
                root = R(root);
            }
        }
    }
    return root;
}

删除


AVLNode* FindMax(AVLNode* root) {
    if(root == NULL) {
        perror("illegal call");
        return NULL;
    }
    while(root->right != NULL)
        root = root->right;
    return root;
}
AVLNode* Delete(AVLNode* root, DataType data) {
    AVLNode* temp = NULL;
    if(root == NULL) {
        perror("empty tree");
        return NULL;
    }
    else if(data < root->data) {
        root->left = Delete(root->left, data);
        if(HEIGHT(root->left) - HEIGHT(root->right) < -1 {
            if(HEIGHT(root->right->left) < HEIGHT(root->right->right)) {
                root = R(root);
            }
            else {
                root->right = L(root->right);
                root = R(root);
        }
    }
    else if(data > root->data) {
        root->right = Delete(root->right, data);
        if(HEIGHT(root->left) - HEIGHT(root->right) > 1 {
            if(HEIGHT(root->left->left) > HEIGHT(root->left->right)) {
                root = L(root);
            }
            else {
                root->left = R(root->left);
                root = L(root);
            }
        }
    }
    else {
        if(root->left == NULL && root->right == NULL) {
            free(root);
            return NULL;
        }
        else if(root->left == NULL && root->right != NULL) {
            temp = root->right;
            free(root);
            return temp;
 
        }
        else if(root->left != NULL && root->right == NULL) {
            temp = root->left;
            free(root);
            return temp;
        }
        else {
            temp = FindMax(root->left);
            root->data = temp->data;
            root->left = Delete(root->left, temp->data);
            if(HEIGHT(root->left) - HEIGHT(root->right) < -1 {
                if(HEIGHT(root->right->left) < HEIGHT(root->right->right)) {
                    root = R(root);
                }
                else {
                    root->right = L(root->right);
                    root = R(root);
                }
            }
        }
    }
}