ADT - AVL-Tree (平衡二叉树)

Posted darkchii

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ADT - AVL-Tree (平衡二叉树)相关的知识,希望对你有一定的参考价值。

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

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

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

  code:

#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\n", 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\n", node->val);
			break;
		case ‘4‘:
			puts("显示数据:");
			inorder(root);
			printf("\n");
			break;
		case ‘5‘:
			printf("\n当前数据个数:%d\n", degree(root));
			break;
		case ‘6‘:
			printf("\n当前树深度:%d\n", depth(root));
			break;
		case ‘7‘:
			puts("平衡检查:");
			checkbalance(root);
			break;
		}
	}
	destory(&root);
    return 0;
}

  

  

  

以上是关于ADT - AVL-Tree (平衡二叉树)的主要内容,如果未能解决你的问题,请参考以下文章

二叉查找树ADT

[数据结构4.8]平衡二叉树

求数据结构算法平衡二叉树实现代码

平衡二叉树详解——PHP代码实现

PHP代码实现平衡二叉树详解

判断一颗二叉树是否为二叉平衡树 python 代码