You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AVL树插入出现无必要旋转,求代码错误排查与修复

AVL树插入功能的错误排查与修复

问题现象

插入1、2、3时,前序遍历显示右旋操作执行正确;但插入4后,树本应处于平衡状态,前序遍历却显示又执行了一次右旋操作,树结构异常。

错误定位

1. 内存分配错误

创建新节点时,malloc的大小计算错误:

t = (struct node*)malloc(sizeof(struct node*));

这里用sizeof(struct node*)分配的是指针大小的内存,远小于struct node结构体的实际大小,导致节点的height等成员内存越界,高度值被随机覆盖,引发后续平衡判断错误。

2. 节点高度更新逻辑错误

insert函数末尾无条件执行高度更新:

t->height = max(height(t->left), height(t->right)) + 1;
  • 当插入元素与当前节点值相等时,树结构未发生变化,无需更新高度,但这段代码强制更新,破坏了原有高度值。
  • 旋转操作已经正确更新了相关节点的高度,末尾的统一更新会覆盖正确的高度计算结果,导致平衡因子判断错误。

修复方法

  1. 修正内存分配大小:将malloc的参数改为sizeof(struct node),确保分配足够内存存储完整节点。
  2. 调整高度更新逻辑:
    • 仅在树结构发生变化时(创建新节点、插入左/右子树后)更新高度。
    • 移除末尾的统一高度更新,将高度更新嵌入到对应的分支中。
    • 当插入元素与当前节点值相等时,直接返回原节点,不做任何修改。

修复后的完整代码

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

typedef struct node *treenode;

struct node
{
    int data;
    int height;
    treenode left;
    treenode right;
};

int height(treenode t)
{
    if(t == NULL)
        return -1;
    else 
        return t->height;
}

int max(int a, int b)
{
    return (a > b)? a : b;
}

treenode singlerotatewithleft(treenode t)
{
    treenode p;
    p = t->left;
    t->left = p->right;
    p->right = t;
    t->height = max(height(t->left), height(t->right)) + 1;
    p->height = max(height(p->left), t->height) + 1;
    return p;
}

treenode singlerotatewithright(treenode t)
{
    treenode p;
    p = t->right;
    t->right = p->left;
    p->left = t;
    t->height = max(height(t->left), height(t->right)) + 1;
    p->height = max(height(p->left), t->height) + 1;
    return p;
}

treenode doublerotatewithleft(treenode t)
{
    t->left = singlerotatewithright(t->left);
    return singlerotatewithleft(t);
}

treenode doublerotatewithright(treenode t)
{
    t->right = singlerotatewithleft(t->right);
    return singlerotatewithright(t);
}

treenode insert(treenode t, int x)
{
    if(t==NULL)
    {
        t = (struct node*)malloc(sizeof(struct node));
        if(t == NULL)
        {
            printf("Out of space");
        }
        else
        {
            t->data = x;
            t->height = 0;
            t->left = t->right = NULL;
        }
        return t;
    }

    if(x < t->data)
    {
        t->left = insert(t->left,x);
        if(height(t->left) - height(t->right) == 2)
        {
            if(x < t->left->data)
                t = singlerotatewithleft(t);
            else
                t = doublerotatewithleft(t);
        }
        t->height = max(height(t->left), height(t->right)) + 1;
    }
    else if(x > t->data)
    {
        t->right = insert(t->right,x);
        if(height(t->right) - height(t->left) == 2)
        {
            if(x > t->right->data)
                t = singlerotatewithright(t);
            else
                t = doublerotatewithright(t);
        }
        t->height = max(height(t->left), height(t->right)) + 1;
    }
    // x等于当前节点值,直接返回原节点,不修改
    return t;
}

void preorder(treenode t)
{
    if(t != NULL)
    {
        printf("%d  ",t->data);
        preorder(t->left);
        preorder(t->right);
    }
}

int main()
{
    int choice;
    treenode root;
    root = NULL;
    do
    {
        printf("\n1.Insert\n2.Preorder traversal\n3.Exit");
        printf("\nEnter choice: ");
        scanf("%d",&choice);

        int x;

        switch(choice)
        {
            case 1:
                printf("\nEnter element to insert: ");
                scanf("%d",&x);
                root = insert(root,x);
                break;
            case 2:
                printf("\nThe preorder traversal is:\n");
                preorder(root);
                printf("\n");
                break;
        }

    }while(choice != 3);
    return 0;
}

内容的提问来源于stack exchange,提问作者RUFINA

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 15:40:21