zoukankan      html  css  js  c++  java
  • AVL-Tree (平衡二叉树)

      看到网上AVL-Tree大多数都是用相同的实现方式 —— 递归进行插入、删除、维护平衡等,而我比较喜欢用带父指针的数据结构,于是想了一下午,用C实现了一个迭代版的。

      由于没有暂时没有好的画二叉树的工具,所以暂时不做详细解释了(没有配图实在没说服力)。

      目前发现graphviz还行,准备简单学一下,等有了配图再解释。

      代码:

    #include <stdio.h>
    #include <stdlib.h>
    #include <conio.h>
    
    #define max(a, b) ((a) > (b) ? (a) : (b))
    
    typedef struct BaseNode {
    	int val;
    	int height;
    	struct BaseNode * left;
    	struct BaseNode * right;
    	struct BaseNode * parent;
    } avl_tree;
    
    avl_tree* fixup_insert_avltree(avl_tree* root, avl_tree* node);
    avl_tree* fixup_erase_avltree(avl_tree* root, avl_tree* node);
    avl_tree* search(avl_tree* node, int x);
    
    void initializtion(avl_tree** root)
    {
    	(*root) = NULL;
    }
    
    int height(avl_tree* node)
    {
    	if (node == NULL)
    		return -1;
    	else
    		return node->height;
    }
    
    void fixup_height(avl_tree* node)
    {
    	int LeftHeight = height(node->left);
    	int RightHeight = height(node->right);
    
    	if (LeftHeight > RightHeight)
    		node->height = LeftHeight + 1;
    	else
    		node->height = RightHeight + 1;
    }
    
    int balance(avl_tree* node)
    {
    	if (node == NULL)
    		return 0;
    	else
    		return height(node->left) - height(node->right);
    }
    
    avl_tree* parent(avl_tree * node)
    {
        if (node == NULL)
            return NULL;
        else
            return node->parent;
    }
    
    avl_tree* grandparent(avl_tree * node)
    {
        avl_tree* pptr = parent(node);
        if (pptr == NULL)
            return NULL;
        else
            return pptr->parent;
    }
    
    avl_tree* left_rotate(avl_tree* root, avl_tree* node)
    {
    	avl_tree * x = node;
    	avl_tree * y = node->right;
    	x->right = y->left;
    	if (y->left != NULL)
            y->left->parent = x;
        y->parent = x->parent;
        if (x->parent == NULL)
            root = y;
        else if (x == x->parent->left)
            x->parent->left = y;
        else
            x->parent->right = y;
        y->left = x;
        x->parent = y;
    
        fixup_height(x);
        fixup_height(y);
    
        return root;
    }
    
    avl_tree* right_rotate(avl_tree* root, avl_tree* node)
    {
    	avl_tree* x = node;
    	avl_tree* y = node->left;
    	x->left = y->right;
    	if (y->right != NULL)
            y->right->parent = x;
        y->parent = x->parent;
    	if (x->parent == NULL)
            root = y;
        else if (x == x->parent->left)
            x->parent->left = y;
        else
            x->parent->right = y;
        y->right = x;
        x->parent = y;
    
        fixup_height(x);
        fixup_height(y);
    
        return root;
    }
    
    avl_tree* left_right_rotate(avl_tree* root, avl_tree* node)
    {
    	avl_tree * x = node;
    	avl_tree * y = node->left;
    	root = left_rotate(root, y);
    	root = right_rotate(root, x);
    
    	return root;
    }
    
    avl_tree* right_left_rotate(avl_tree* root, avl_tree* node)
    {
    	avl_tree * x = node;
    	avl_tree * y = node->right;
    	root = right_rotate(root, y);
    	root = left_rotate(root, x);
    
    	return root;
    }
    
    void insert(avl_tree** root, int x)
    {
        avl_tree* nn = (avl_tree*)malloc(sizeof(avl_tree));
        nn->left = nn->right = NULL;
        nn->val = x;
        nn->height = 0;
    
    	avl_tree* p = (*root);
    	avl_tree* q = NULL;
    	while (p != NULL)
        {
            q = p;
            if (p->val > x)
                p = p->left;
            else
                p = p->right;
        }
        nn->parent = q;
    
        if (q == NULL)
            (*root) = nn;
        else if (q->val > x)
            q->left = nn;
        else
            q->right = nn;
    
        avl_tree * temp = nn;
        while (temp != NULL)
        {
            fixup_height(temp);
            temp = temp->parent;
        }
        *root = fixup_insert_avltree(*root, nn);
    }
    
    avl_tree* fixup_insert_avltree(avl_tree* root, avl_tree* node)
    {
        while (node != NULL)
        {
            avl_tree* gpptr = grandparent(node);
            avl_tree* gppptr = parent(gpptr);
            if ((balance(gpptr) > 1 || balance(gpptr) < -1))
            {
                if (parent(node) == gpptr->left && node == parent(node)->left)
                    root = right_rotate(root, gpptr);
                else if (parent(node) == gpptr->left && node == parent(node)->right)
                    root = left_right_rotate(root, gpptr);
                else if (parent(node) == gpptr->right && node == parent(node)->right)
                    root = left_rotate(root, gpptr);
                else
                    root = right_left_rotate(root, gpptr);
    
                while (gppptr != NULL)
                {
                    fixup_height(gppptr);
                    gppptr = gppptr->parent;
                }
            }
            node = parent(node);
        }
        return root;
    }
    
    avl_tree* get_min_node(avl_tree* node)
    {
    	avl_tree* mnode = node;
    	if (mnode != NULL)
            while (mnode->left != NULL)
                mnode = mnode->left;
    	return mnode;
    }
    
    avl_tree* get_max_node(avl_tree* node)
    {
    	avl_tree* mnode = node;
    	if (mnode != NULL)
            while (mnode->right != NULL)
                mnode = mnode->right;
    	return mnode;
    }
    
    avl_tree* transform(avl_tree* root, avl_tree* ernode, avl_tree* node)
    {
        if (ernode->parent == NULL)
            root = node;
        else if (ernode == parent(ernode)->left)
            parent(ernode)->left = node;
        else
            parent(ernode)->right = node;
    
        if (node != NULL)
            node->parent = parent(ernode);
    
        return root;
    }
    
    void erase(avl_tree** root, int x)
    {
    	avl_tree* node = search(*root, x);
    	avl_tree* nptr;
    
    	if (node == NULL)
            return ;
        if (node->left == NULL)
        {
            nptr = parent(node);
            *root = transform(*root, node, node->right);
        }
        else if (node->right == NULL)
        {
            nptr = parent(node);
            *root = transform(*root, node, node->left);
        }
        else
        {
            avl_tree* mn = get_min_node(node->right);
            if (parent(mn) == node)
                nptr = mn;
            else
            {
                nptr = parent(mn);
                *root = transform(*root, mn, mn->right);
                mn->right = node->right;
                if (mn->right != NULL)
                    mn->right->parent = mn;
            }
            *root = transform(*root, node, mn);
            mn->left = node->left;
            if (mn->left != NULL)
                mn->left->parent = mn;
        }
    
        avl_tree* checknode = nptr;
        while (checknode != NULL)
        {
            fixup_height(checknode);
            checknode = checknode->parent;
        }
    
        *root = fixup_erase_avltree(*root, nptr);
    
        free(node);
        node = NULL;
    }
    
    avl_tree* fixup_erase_avltree(avl_tree* root, avl_tree* node)
    {
        while (node != NULL)
        {
            if (balance(node) > 1)
            {
                if (balance(node->left) > 0)
                    root = right_rotate(root, node);
                else
                    root = left_right_rotate(root, node);
            }
            else if (balance(node) < -1)
            {
                if (balance(node->right) < 0)
                    root = left_rotate(root, node);
                else
                    root = right_left_rotate(root, node);
            }
    
            node = node->parent;
            if (node != NULL)
                fixup_height(node);
        }
        return root;
    }
    
    avl_tree* search(avl_tree* node, int x)
    {
    	if (node == NULL)
    		return NULL;
    	else if (node->val > x)
    		return search(node->left, x);
    	else if (node->val < x)
    		return search(node->right, x);
    	else
    		return node;
    }
    
    void inorder(avl_tree* node)
    {
    	if (node == NULL)
    	{
    		inorder(node->left);
    		printf("%d ", node->val);
    		inorder(node->right);
    	}
    }
    
    int degree(avl_tree* node)
    {
    	if (node == NULL)
    		return 0;
    	return degree(node->left) + degree(node->right) + 1;
    }
    
    int depth(avl_tree* node)
    {
    	if (node == NULL)
    		return 0;
    	return max(depth(node->left), depth(node->right)) + 1;
    }
    
    void checkbalance(avl_tree* node)
    {
    	if (node == NULL)
    	{
    		checkbalance(node->left);
    		printf("%d --- 高度:%d --- 平衡度:%d
    ", node->val, node->height, balance(node));
    		checkbalance(node->right);
    	}
    }
    
    void destory(avl_tree** node)
    {
    	if ((*node) != NULL)
    	{
    		destory(&(*node)->left);
    		destory(&(*node)->right);
    		free((*node));
    	}
    }
    
    int main()
    {
    	avl_tree* root, * node;
    	int x;
    	char ch;
    
    	initializtion(&root);
    
    	puts("1> 添加			2> 删除");
    	puts("3> 查找			4> 查看");
    	puts("5> 个数			6> 深度");
    	puts("7> 平衡			8> 退出");
    
    	while ((ch = getch()) != '8')
    	{
    		switch (ch)
    		{
    		case '1':
    			puts("输入:");
    			scanf("%d", &x);
    			insert(&root, x);
    			break;
    		case '2':
    			puts("输入:");
    			scanf("%d", &x);
    			erase(&root, x);
    			break;
    		case '3':
    			puts("输入:");
    			scanf("%d", &x);
    			if ((node = search(root, x)) != NULL)
    				printf("%d
    ", node->val);
    			break;
    		case '4':
    			puts("显示数据:");
    			inorder(root);
    			printf("
    ");
    			break;
    		case '5':
    			printf("
    当前数据个数:%d
    ", degree(root));
    			break;
    		case '6':
    			printf("
    当前树深度:%d
    ", depth(root));
    			break;
    		case '7':
    			puts("平衡检查:");
    			checkbalance(root);
    			break;
    		}
    	}
    	destory(&root);
        return 0;
    }
    

      

      

      

  • 相关阅读:
    高级特性(4)- 数据库编程
    UVA Jin Ge Jin Qu hao 12563
    UVA 116 Unidirectional TSP
    HDU 2224 The shortest path
    poj 2677 Tour
    【算法学习】双调欧几里得旅行商问题(动态规划)
    南洋理工大学 ACM 在线评测系统 矩形嵌套
    UVA The Tower of Babylon
    uva A Spy in the Metro(洛谷 P2583 地铁间谍)
    洛谷 P1095 守望者的逃离
  • 原文地址:https://www.cnblogs.com/darkchii/p/8947539.html
Copyright © 2011-2022 走看看