平衡二叉树
2010-05-11 17:19 snowkylin 阅读(656) 评论(0) 编辑 收藏 举报AVL树插入算法的基本步骤如下:
①在寻找新结点的插入位置的过程中,记下离该位置最近、且平衡因子不等于零的结点a(此结点即为可能出现的最小失衡子树的根);
②修改自该结点至插入位置路径上所有结点的平衡因子(注意:树上其它结点的平衡因子均不受插入的影响);
③判断实施插入操作之后,结点a的平衡因子的绝对值是否大于1(即判断是否失衡)。若是,进一步判断失衡类型并做相应调整;否则插入过程结束。
AVL树的基本操作一般涉及运做同在不平衡的二叉查找树所运做的同样的算法。但是要进行预先或随后做一次或多次所谓的"AVL 旋转"。
假设由于在二叉排序树上插入结点而失去平衡的最小子树根结点的指针为a(即a是离插入点最近,且平衡因子绝对值超过1的祖先结点),则失去平衡后进行进行的规律可归纳为下列四种情况:
- 单向右旋平衡处理RR:由于在*a的左子树根结点的左子树上插入结点,*a的平衡因子由1增至2,致使以*a为根的子树失去平衡,则需进行一次右旋转操作;
- 单向左旋平衡处理LL:由于在*a的右子树根结点的右子树上插入结点,*a的平衡因子由-1变为-2,致使以*a为根的子树失去平衡,则需进行一次左旋转操作;
- 双向旋转(先左后右)平衡处理LR:由于在*a的左子树根结点的右子树上插入结点,*a的平衡因子由1增至2,致使以*a为根的子树失去平衡,则需进行两次旋转(先左旋后右旋)操作。
- 双向旋转(先右后左)平衡处理RL:由于在*a的右子树根结点的左子树上插入结点,*a的平衡因子由-1变为-2,致使以*a为根的子树失去平衡,则需进行两次旋转(先右旋后左旋)操作。
例如,处理RR使用右旋:
代码
program balance;
type link=^node;
node=record
data,b:longint;
lch,rch,parent:link;
end;
var root,temp:link;
x,t:longint;
procedure LL_rolation(var p:link);
var q:link;
begin
q:=p^.lch;
p^.lch:=q^.rch;
q^.rch:=p;
p:=q;
p^.b:=0;
p^.rch^.b:=0;
end;
procedure RR_rolation(var p:link);
var q:link;
begin
q:=p^.rch;
p^.rch:=q^.lch;
q^.lch:=p;
p:=q;
p^.b:=0;
p^.lch^.b:=0;
end;
procedure LR_rolation(var p:link);
var q:link;
x:longint;
begin
x:=p^.lch^.rch^.b;
q:=p^.lch;
RR_rolation(q);
p^.lch:=q;
LL_rolation(p);
p^.b:=0;
if x=1 then begin p^.lch^.b:=-1;p^.rch^.b:=0; end
else begin p^.lch^.b:=0;p^.rch^.b:=-1; end;
end;
procedure RL_rolation(var p:link);
var q:link;
x:longint;
begin
x:=p^.rch^.lch^.b;
q:=p^.rch;
LL_rolation(q);
p^.rch:=q;
RR_rolation(p);
p^.b:=0;
if x=1 then begin p^.lch^.b:=-1;p^.rch^.b:=0; end
else begin p^.lch^.b:=0;p^.rch^.b:=-1; end;
end;
procedure insert(var root:link; x:longint);
var p,q,r,t,b,f,k:link;
d:longint;
begin
new(p);
p^.data:=x;
p^.lch:=nil;
p^.rch:=nil;
p^.b:=0;
q:=root;
t:=nil;
r:=root;
while q<>nil do
begin
if q^.b<>0 then begin r:=q;f:=t; end;
if x<q^.data then
if q^.lch=nil then begin q^.lch:=p;break; end else begin t:=q;q:=q^.lch; end
else
if q^.rch=nil then begin q^.rch:=p;break; end else begin t:=q;q:=q^.rch; end;
end;
q:=r;
if x<q^.data then
begin d:=-1;q:=q^.lch;b:=q; end
else begin d:=1;q:=q^.rch;b:=q; end;
while q<>p do
begin
if x<q^.data then
begin
dec(q^.b);
q:=q^.lch;
end
else
begin
inc(q^.b);
q:=q^.rch;
end;
end;
if r^.b=0 then r^.b:=d
else if r^.b+d=0 then r^.b:=0
else
begin
k:=r;
if d=-1 then
case r^.lch^.b of
-1:LL_rolation(k);
1:LR_rolation(k);
end
else
if d=1 then
case r^.rch^.b of
-1:RL_rolation(k);
1:RR_rolation(k);
end;
if f=nil then root:=k
else
if f^.lch=r then f^.lch:=k
else if f^.rch=r then f^.rch:=k;
end;
end;
procedure print(p:link);
begin
if p^.lch<>nil then print(p^.lch);
write(p^.data,' ');
if p^.rch<>nil then print(p^.rch);
end;
begin
while not eof do
begin
new(root);
read(x);
root^.data:=x;
root^.lch:=nil;
root^.rch:=nil;
root^.b:=0;
while not eoln do
begin
read(x);
insert(root,x);
end;
readln;
print(root);
writeln;
end;
end.