AVL树-C实现

我一直对平衡二叉树感兴趣,数据结构和算法妙趣横生,仔细体会,对编程莫大裨益。花了一个星期的业余时间,初步写完了AVL Tree,目前还在继续查找Bug中。
AVL树使用平衡因子来决定是否对树进行旋转。对树进行旋转有四种情况。但首先是某个平衡因子的值达到了2或者-2,再根据该节点的子节点的平衡因子是1还是-1,进行相应的旋转。
关于AVL的一些特性,可以参考国外教材《算法和数据结构 C语言描述》这本书。

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

typedef struct AVLNode {
    void *value;
    struct AVLNode *parent;
    struct AVLNode *lchild;
    struct AVLNode *rchild;
    int gap;
}AVLNode , *Node;

typedef struct AVLTree {
    Node root;
    int (*Compare) (void *value1 , void *value2);
}Tree , *AVLTree;


static Node Search (AVLTree avltr , void *value);
static Node NodeInitial (void *value);
static AVLTree TreeInitial (int (*Compare) (void *value1 , void *value2));
static void ReplaceNode (AVLTree avltr , Node node1 , Node node2);
static void Insert (AVLTree avltr , Node avlnode);
static void Delete (AVLTree avltr , Node avlnode);
static void AVLPrint (Node root);
static void FreeAVL (Node root);

static Node FindSubMax (Node avlnode);
static Node FindSubMin (Node avlnode);
static Node FindMax (AVLTree avltr);
static Node FindMin (AVLTree avltr);
static Node FindSuccessor (Node avlnode);

void LeftRotate (AVLTree avltr , Node avlnode);
void RightRotate (AVLTree avltr , Node avlnode);
void LeftRightRotate (AVLTree avltr , Node avlnode);
void RightLeftRotate (AVLTree avltr , Node avlnode);
void AVLInsertBalance (AVLTree avltr , Node avlnode);
void AVLDeleteBalance (AVLTree avltr , Node avlnode);


void LeftRotate (AVLTree avltr , Node avlnode) {
    Node righttree = avlnode->rchild;
    Node pa_node = avlnode->parent;
    Node rlchild = righttree->lchild;

    righttree->parent = pa_node;
    if(pa_node == NULL) {
        avltr->root = righttree;
    } else if(pa_node->lchild == avlnode) {
        pa_node->lchild = righttree;
    } else {
        pa_node->rchild = righttree;
    }

    avlnode->parent = righttree;
    righttree->lchild = avlnode;

    avlnode->rchild = rlchild;
    if(rlchild != NULL) {
        rlchild->parent = avlnode;
    }
}

void RightRotate (AVLTree avltr , Node avlnode) {
    Node lefttree = avlnode->lchild;
    Node pa_node = avlnode->parent;
    Node lrchild = lefttree->rchild;

    lefttree->parent = pa_node;
    if(pa_node == NULL) {
        avltr->root = lefttree;
    } else if(pa_node->lchild == avlnode) {
        pa_node->lchild = lefttree;
    } else {
        pa_node->rchild = lefttree;
    }

    avlnode->parent = lefttree;
    lefttree->rchild = avlnode;

    avlnode->lchild = lrchild;
    if(lrchild != NULL) {
        lrchild->parent = avlnode;
    }
}

void LeftRightRotate (AVLTree avltr , Node avlnode) {
    LeftRotate(avltr , avlnode->rchild);
    RightRotate(avltr , avlnode);
}

void RightLeftRotate (AVLTree avltr , Node avlnode) {
    RightRotate(avltr , avlnode->lchild);
    LeftRotate(avltr , avlnode);
}

int IntComp (void *value1 , void *value2) {
    if (*(int *)value1 > *(int *)value2) return 1;
    if (*(int *)value1 < *(int *)value2) return -1;
    return 0;
}

static AVLTree TreeInitial (int (*Compare) (void *value1 , void *value2)) {
    AVLTree tree = (AVLTree) malloc (sizeof (Tree));
    printf ("Size of Tree is %d\n",sizeof(Tree));
    tree->Compare = Compare;
    tree->root = NULL;
    return tree;
}

static Node NodeInitial (void *value) {
    printf("Initial Node.\n");
    Node avlnode = (Node) malloc (sizeof (AVLNode));
    if (avlnode == NULL) printf("Initial Node with error.\n");
    avlnode->gap = 0;
    avlnode->lchild = NULL;
    avlnode->parent = NULL;
    avlnode->rchild = NULL;
    avlnode->value = value;
    printf ("Initilized Node value is %d.\n",*(int *)avlnode->value);
    return avlnode;
}

static Node Search (AVLTree avltr , void *value) {
    Node root = avltr->root;
    while (root != NULL) {
        if(avltr->Compare(root->value , value) == 0) {
            return root;
        } else if (avltr->Compare(root->value , value) < 0) {
            root = root->rchild;
        } else {
            root = root->lchild;
        }
    }
    return NULL;
}

static Node FindSubMax (Node avlnode) {
    Node node = avlnode;
    while (node->rchild != NULL) {
        node = node->rchild;
    }
    return node;
}

static Node FindSubMin (Node avlnode) {
    Node node = avlnode;
    while (node->lchild !=NULL) {
        node = node->lchild;
    }
    return node;
}

static Node FindMax (AVLTree avltr) {
    Node node = avltr->root;
    if(node == NULL) {
        return NULL;
    } else {
        return FindSubMax(node);
    }
}

static Node FindMin (AVLTree avltr) {
    Node node = avltr->root;
    if (node == NULL) {
        return NULL;
    } else {
        return FindSubMin(node);
    }
}

static Node FindSuccessor (Node avlnode) {
    Node node = avlnode;
    if (node->rchild != NULL) {
        return FindSubMin (node->rchild);
    } else {
        Node pa = node->parent;
        while ( pa != NULL && node == pa->rchild ) {
            node = pa;
            pa = pa->parent;
        }
        return pa;
    }
}

static void ReplaceNode (AVLTree avltr , Node node1 , Node node2) {
    if (avltr->Compare(node1->value , node2->value)!=0) {
        return;
    } else {
        node1->value = node2->value;
    }
}

static void Insert (AVLTree avltr , Node avlnode) {
    if (avlnode == NULL) {
        return;
    }
    if (avltr == NULL) {
        return;
    }
    if (avltr->root == NULL) {
        avltr->root = avlnode;      
    } else {
        Node node = avltr->root;
        Node pa_node = NULL;
        while (node != NULL) {
            pa_node = node;
            if (avltr->Compare(node->value,avlnode->value) < 0) {
                node = node->rchild;
            } else if (avltr->Compare(node->value,avlnode->value) > 0) {
                node = node->lchild;
            } else {
                ReplaceNode(avltr,node,avlnode);
                return;
            }
        }
        avlnode->parent = pa_node;
        if(avltr->Compare(pa_node->value , avlnode->value) >0) {
            pa_node->lchild = avlnode;
            pa_node->gap++; 
        } else {
            pa_node->rchild = avlnode;
            pa_node->gap--;
        }

        AVLInsertBalance (avltr , pa_node);
    }
}

static void Delete (AVLTree avltr , Node avlnode) {
    if (avltr == NULL || avltr->root == NULL) return;

    Node p_node = NULL , d_node = NULL , s_node = NULL;

    if(avlnode->lchild != NULL && avlnode->rchild != NULL) {
        d_node = FindSuccessor(avlnode);
    } else {
        d_node = avlnode;
    }
    p_node = d_node->parent;
    if (d_node->rchild != NULL) {
        s_node = d_node->rchild;
    } else {
        s_node = d_node->lchild;
    }
    if (p_node->lchild == d_node) {
        p_node->lchild = s_node;
        p_node->gap--;
    } else {
        p_node->rchild = s_node;
        p_node->gap++;
    }
    if (s_node != NULL) {
        s_node->parent = p_node;
    }
    if (d_node != avlnode) {
        avlnode->value = d_node->value;
    }

    AVLDeleteBalance(avltr , p_node);
    free(d_node);
}

void AVLInsertBalance (AVLTree avltr , Node avlnode) {
    Node p_node = avlnode->parent;
    Node node = avlnode;
    while (p_node != NULL) {
        if (p_node->lchild == node) {
            p_node->gap++;
        } else {
            p_node->gap--;
        }

        if (p_node->gap == 0){
            return;
        }
        else if (p_node->gap == 1 || p_node->gap == -1) {
            node = p_node;
            p_node = p_node->parent;
        }
        else if (p_node->gap > 1) {
            if (node->gap == 1) {
                p_node->gap-=2;
                node->gap-=1;
                RightRotate(avltr , p_node);
                return;
            }
            if (node->gap == -1) {
                p_node->gap-=2;
                node->gap+=1;
                LeftRightRotate(avltr , p_node);
                return;
            }
        } 
        else {
            if (node->gap == -1) {
                p_node->gap+=2;
                node->gap+=1;
                LeftRotate(avltr , p_node);
                return;
            }
            if (node->gap == 1) {
                p_node->gap+=2;
                node->gap-=1;
                RightLeftRotate (avltr , p_node);
                return;
            }
        }
    }
}

void AVLDeleteBalance (AVLTree avltr , Node avlnode) {
    Node node = avlnode;
    Node pa_node = avlnode;
    while (pa_node != NULL) {
        node = pa_node;
        if (node->gap == 2) {
            Node lch_node = node->lchild;
            if (lch_node->gap == 1) {
                node->gap-=2;
                lch_node->gap-=1;
                RightRotate(avltr , node);
                pa_node = lch_node->parent;
                if (pa_node != NULL) {
                    if (pa_node->lchild == lch_node) {
                        pa_node->gap--;
                    } else {
                        pa_node->gap++;
                    }   
                }
            }
            if (lch_node->gap == -1) {
                node->gap-=2;
                lch_node->gap+=1;
                LeftRightRotate(avltr , node);
                Node new_root = lch_node->rchild;
                pa_node = new_root->parent;
                if (pa_node != NULL) {
                    if (pa_node->lchild == new_root) {
                        pa_node->gap--;
                    } else {
                        pa_node->gap++;
                    }
                }
            }
        }

        if (node->gap == -2) {
            Node rch_node = node->rchild;
            if (rch_node->gap == -1) {
                node->gap+=2;
                rch_node->gap+=1;
                LeftRotate (avltr , node);
                pa_node = rch_node->parent;
                if (pa_node != NULL) {
                    if (pa_node->lchild == rch_node) {
                        pa_node->gap--;
                    } else {
                        pa_node->gap++;
                    }
                }
            }

            if (rch_node->gap == 1) {
                node->gap+=2;
                rch_node->gap-=1;
                RightLeftRotate (avltr , node);
                Node new_root = rch_node->lchild;
                pa_node = new_root->parent;
                if (pa_node != NULL) {
                    if (pa_node->lchild == new_root) {
                        pa_node->gap--;
                    } else {
                        pa_node->gap++;
                    }
                }
            }       
        }

        if (node->gap == 0) {
            pa_node = node->parent;
            if (pa_node != NULL) {
                if (pa_node->lchild == node) {
                    pa_node->gap--;
                } else {
                    pa_node->gap++;
                }   
            }   
        }

        if (node->gap == 1 || node->gap == -1) return;
    }   
} 

static void AVLPrint (Node root) {
    Node node = root;
    if (node != NULL) {
        AVLPrint (node->lchild);
        printf("%d:%d  ",*(int *)node->value,node->gap);
        AVLPrint (node->rchild);
    }
}

static void FreeAVL (Node root) {
    Node node = root;
    if (node != NULL) {
        FreeAVL (node->lchild);
        free(node);
        FreeAVL (node->rchild);
    }
}

void main (void) {
    AVLTree avltr = TreeInitial (IntComp);
    int a = 100;
    Node node1 = NodeInitial (&a);
    Insert (avltr , node1);
    int b = 56;
    Node node2 = NodeInitial (&b);
    Insert (avltr , node2);
    int c = 32;
    Node node3 = NodeInitial (&c);
    Insert (avltr , node3);
    int d = 67;
    Node node4 = NodeInitial (&d);
    Insert (avltr , node4);
    int e = 21;
    Node node5 = NodeInitial (&e);
    Insert (avltr , node5);
    int f = 18;
    Node node6 = NodeInitial (&f);
    Insert (avltr , node6);
    int g = 17;
    Node node7 = NodeInitial (&g);
    Insert (avltr , node7);
    AVLPrint (avltr->root);
    printf("\n");
    Delete (avltr , node3);
    AVLPrint (avltr->root);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值