[英]What is wrong with this AVL balancing code?
每次我使用avlRotate函数时,它都会从树中删除一些元素。 z是检测到不平衡的节点,y是其高度较大的子树节点,x是新插入的节点。 单次插入后立即调用此函数。
#define RESTRUCTURE a->left = t0; a->right = t1; c->left = t2; c->right = t3; b->left = a; b->right = c;
avlTree avlRotate(avlTree z,avlTree y,avlTree x)
{
avlTree a,b,c;
avlTree t0,t1,t2,t3;
if(y==z->left && x==y->left) //single rotation
{
a=x;b=y;c=z;
t0=a->left;
t1=a->right;
t2=b->right;
t3=c->right;
RESTRUCTURE
c->height[0] = y->height[1];
}
else if(y==z->right && x==y->right) //single rotation
{
a=z;b=y;c=x;
t0=a->left;
t1=b->left;
t2=c->left;
t3=c->right;
RESTRUCTURE
a->height[1] = y->height[0];
}
else if(y==z->right && x==y->left) //double rotation
{
a=z;b=x;c=y;
t0=a->left;
t1=b->left;
t2=b->right;
t3=c->right;
RESTRUCTURE
a->height[1] = x->height[0];
c->height[0] = x->height[1];
}
else if(y==z->left && x==y->right) //double rotation
{
a=y;b=x;c=z;
t0=a->left;
t1=b->left;
t2=b->right;
t3=c->right;
RESTRUCTURE
a->height[1] = x->height[0];
c->height[0] = x->height[1];
}
printf("\nRem parts:\n");
printf("{%d %d} {%d %d} {%d %d}\n",a->part->range[0],a->part->range[1],b->part->range[0],b->part->range[1],c->part->range[0],c->part->range[1]);
printf("\n\n");
b->height[0] = ( (a->height[0] > a->height[1]) ? (a->height[0])+1 : (a->height[1])+1 );
b->height[1] = ( (c->height[0] > c->height[1]) ? (c->height[0])+1 : (c->height[1])+1 );
a->balFactor = a->height[0] - a->height[1];
b->balFactor = b->height[0] - b->height[1];
c->balFactor = c->height[0] - c->height[1];
return(b);
}
该函数通过以下方式调用:
if(a->balFactor > 1 || a->balFactor < -1)
{
printf("imbalance fside=%d pside=%d\n",*finalSide,*prevSide);
if(*finalSide == 0)
{yLike = a->left;}
else
{yLike = a->right;}
if(*prevSide == 0)
{xLike = yLike->left;}
else
{xLike = yLike->right;}
printf("passing to rotate %u %u %u\n",a,yLike,xLike);
printf("{%d %d} {%d %d} {%d %d}\n",a->part->range[0],a->part->range[1],yLike->part->range[0],yLike->part->range[1],xLike->part->range[0],xLike->part->range[1]);
a = avlRotate(a,yLike,xLike);
avlInOrderTraversal(a,0);
printf("{%d %d} {%d %d} {%d %d}\n",a->left->part->range[0],a->left->part->range[1],a->part->range[0],a->part->range[1],a->right->part->range[0],a->right->part->range[1]);
}
在插入功能。
输出:
a->height[0]=1 a->height[1]=0
BALANCE FACTOR = 1
16 to 18
51 to 53
a->height[0]=0 a->height[1]=1
BALANCE FACTOR = -1
a->height[0]=2 a->height[1]=0
BALANCE FACTOR = 2
imbalance fside=0 pside=1
passing to rotate 147992552 147992584 147992616
{51 53} {16 18} {41 41}
Rem parts:
{16 18} {41 41} {51 53}
51 to 53
a->height[0]=0 a->height[1]=1
BALANCE FACTOR = -1
51 to 53
60 to 61
a->height[0]=1 a->height[1]=1
BALANCE FACTOR = 0
4 to 6
51 to 53
60 to 61
此功能明显不正确吗?
注意:每个节点都存储一个范围,例如。 3 to 5
。
编写一个函数来转储您的树。 对于每个节点,显示其认为其左,右,上和左/右子树深度是什么。
旋转前先倒树,然后倒。
那是我写我的时候所做的。
您-树中将有一些细微的错误-对每个问题求助于SO将使您无处可寻。 当您爬上树时,您还将需要一个转储函数来调试重新平衡-您需要验证许多独特的添加和删除重新平衡情况。 所有这些都需要一个树转储。
网上的AVL树上有很多资源,其中一些是:
进一步继续Blank Xavier的回答 ,我建议将程序的转储输出与动画结果进行比较 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.