C语言 AVL树

      • AVL树简介
        • 实现过程
        • 代码实现

AVL树简介

AVL树的基本操作一般涉及运做同在不平衡的二叉查找树所运做的同样的算法。但是要进行预先或随后做一次或多次所谓的”AVL 旋转”。

AVL树的模拟过程可以看链接:AVLtree

对于AVL树的详细简介和实现过程可以参照链接:数据结构图文解析之:AVL树详解及C++模板实现

我在这里主要是选出重点:AVL旋转

实现过程

首先我们需要知道什么情况下需要AVL旋转。
节点的左右子树的高度差大于 1 的时候,二叉树不平衡了,这个时候我们需要进行AVL操作。

主要有以下几种情况:
C语言 AVL树_第1张图片

通过右旋,左旋,右旋左旋,左旋右旋使得二叉树平衡。
那么怎么实现四种AVL旋转?可以发现右旋和左旋的实现比较简单,都是将中心节点变换为根节点,而右旋左旋,左旋右旋则比较复杂。
实际上,我们可以这样看,右旋左旋其实相当于进行了两次旋转,一次旋转是右旋,它并不是将三个节点进行旋转,而是将后两个节点先进行一轮旋转(可以想象为两个节点最后带一个空节点),另外一个节点是对旋转完成后进行了一次左旋。比如:
C语言 AVL树_第2张图片

所以对于右旋左旋,左旋右旋的实现就变得简单很多:

BtreePtr rightLeftRotate(BtreePtr a) {
    a->right_child = rightRotate(a->right_child);
    a = leftRotate(a);
    return a;
}

BtreePtr leftRightRotate(BtreePtr a) {
    a->left_child = leftRotate(a->left_child);
    a = leftRotate(a);
    return a;
}

代码实现

节点的结构体

typedef struct Bi{
    int val;
    int pos;

    int height;
    struct Bi *parent;
    struct Bi *left_child;
    struct Bi *right_child;
} Btree, *BtreePtr;

抽象数据结构(ADT):

void freeTree(BtreePtr b); //释放节点

BtreePtr rightRotate(BtreePtr a); //右旋
BtreePtr leftRotate(BtreePtr a);  //左旋
BtreePtr leftRightRotate(BtreePtr a);  //左旋右旋
BtreePtr rightLeftRotate(BtreePtr a);  //右旋左旋

BtreePtr _checkHeight(BtreePtr a);   //判断二叉树是不是平衡
BtreePtr insertAVLTree(BtreePtr a, BtreePtr b);  //插入节点

完整代码

#include <stdio.h>
#include <malloc.h>
#include <memory.h>
#define HEIGHT(p)    ( (p==NULL) ? 0 : (((BtreePtr)(p))->height) )
#define MAX(a, b)    ( (a) > (b) ? (a) : (b) )

typedef struct Bi{
    int val;
    int pos;

    int height;
    struct Bi *parent;
    struct Bi *left_child;
    struct Bi *right_child;
} Btree, *BtreePtr;

int midSearch(const BtreePtr a, const int key) {
    if (a != NULL) {
        if (key > a->val) {
            return midSearch(a->right_child, key);
        }
        else if(key < a->val) {
            return midSearch(a->left_child, key);
        }
        else {
            return a->pos;
        }
    }
    else {
        return -1;
    }
}

void freeTree(BtreePtr b) {
    if (b->right_child !=NULL) {
        freeTree(b->right_child);
    }
    if (b->left_child != NULL) {
        freeTree(b->left_child);
    }
}

BtreePtr rightRotate(BtreePtr a) {
    BtreePtr b = (BtreePtr)malloc(sizeof(Btree));

    b = a->left_child;
    b->parent = a->parent;
    a->left_child = b->right_child;
    b->right_child = a;

    b->right_child->parent = b;

    a->height = MAX(HEIGHT(a->left_child), HEIGHT(a->right_child)) + 1;
    b->height = MAX(HEIGHT(b->left_child), a->height) + 1;

    return b;
}

BtreePtr leftRotate(BtreePtr a) {
    BtreePtr b = (BtreePtr)malloc(sizeof(Btree));;

    b = a->right_child;
    a->right_child = b->left_child;
    b->left_child = a;

    b->parent = a->parent;
    b->left_child->parent = b; //

    a->height = MAX(HEIGHT(a->left_child), HEIGHT(a->right_child)) + 1;
    b->height = MAX(HEIGHT(b->right_child), a->height) + 1;
    return b;
}

BtreePtr rightLeftRotate(BtreePtr a) {
    a->right_child = rightRotate(a->right_child);
    a = leftRotate(a);
    return a;
}

BtreePtr leftRightRotate(BtreePtr a) {
    a->left_child = leftRotate(a->left_child);
    a = leftRotate(a);
    return a;
}

BtreePtr _checkHeight(BtreePtr a) {
    int left = HEIGHT(a->left_child);
    int right = HEIGHT(a->right_child);


    if (right - left > 1) {  //一个节点的左右子树高度差不能大于2
        if (HEIGHT(a->right_child->right_child) - HEIGHT(a->right_child->left_child)>0){  //右节点高度大于左节点高度
            a = leftRotate(a); //同方向旋转
        }
        else {
            a = rightLeftRotate(a); //异方向旋转
        }
    }
    if (left - right > 1) {
        if (HEIGHT(a->left_child->right_child) - HEIGHT(a->left_child->left_child)>0) {
            a = leftRightRotate(a); //异方向旋转
        }
        else {  //左节点高度大于右节点高度
            a = rightRotate(a); //同方向旋转
        }
    }

    return a;
}

BtreePtr insertAVLTree(BtreePtr a, BtreePtr b) {
    //new value in b
    if (a->height == 0) {
        *a = *b;  //不能用a = b, copy b中所有内容
        //puts("hello");
        free(b);
    }
    else {
        if (a->val < b->val) {
            if (a->right_child != NULL) {
                b->parent = a->right_child;

                a->right_child = insertAVLTree(a->right_child, b);
            }
            else {
                b->parent = a;

                a->right_child = b;  //不能用 *(a-> right_child) = *b
            }
        }
        else {
            if (a->left_child != NULL) {
                b->parent = a->left_child;

                a->left_child = insertAVLTree(a->left_child, b);
            }
            else {
                b->parent = a;

                a->left_child = b; //不能用 *(a-> left_child) = *b
            }
        }

        //节点高度
        if (a->left_child != NULL) {
            if (a->left_child->height == a->height) {
                (a->height)++;
            }
        }
        if (a->right_child != NULL) {
            if (a->right_child->height == a->height) {
                (a->height)++;
            }
        }

        a = _checkHeight(a);

    }
    return a;
}


int AVLTreeSearch(const int *a, const int length, const int key) {
    BtreePtr root = (BtreePtr)malloc(sizeof(Btree));;
    memset(root, 0, sizeof(Btree));  //将结构体中的指针初始化
    for (int i = 0; i < length; i++) {
        BtreePtr p = (BtreePtr)malloc(sizeof(Btree));
        memset(p, 0, sizeof(Btree));
        p->val = a[i];
        p->pos = i;
        p->height = 1;
        root = insertAVLTree(root, p);  //构建二叉树
    }
    int pos = midSearch(root, key);
    freeTree(root); //不能直接使用free(b)
    return pos;
}



void main() {
    const int length = 6;
    int my_array[6] = { 1 ,7, 6, 8, 0,1 };
    printf("%d \n", AVLTreeSearch(my_array, length, 6));
}

你可能感兴趣的:(c,算法,搜索)