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;
    }
    

      

      

      

  • 相关阅读:
    ABP文档
    SqlServer英文单词全字匹配
    npm不是以管理身份运行遇到的问题
    concurrenthashmap jdk1.8
    HashSet源码分析 jdk1.6
    Iterator设计模式--jdk1.7
    代理模式
    高并发下的HashMap,ConcurrentHashMap
    HashMap源码分析jdk1.6
    Stack&Vector源码分析 jdk1.6
  • 原文地址:https://www.cnblogs.com/darkchii/p/8947539.html
Copyright © 2011-2022 走看看