PASCAL实现平衡有序树AVL树

来源:互联网 发布:修改电话号码软件 编辑:程序博客网 时间:2024/05/22 01:33
{/*
  Name: PASCAL实现平衡有序树AVL树
  Copyright: 始发于goal00001111的专栏;允许自由转载,但必须注明作者和出处
  Author: goal00001111
  Date: 04-12-08 21:37
  Description:
在排序二叉树的基础上分析了AVL树,AVL树比普通二杈有序树多了一个高度信息,
在进行结点的插入和删除后能保证二叉树的深度不会增加,这样在插入和查找结点时能
保证时间复杂度不超过O(logN)。 AVL树的遍历和查找等操作与二叉排序树是一样的,
只是在创建AVL树,插入和删除结点操作有些不同,特别是插入结点,为了保证左右子树
不失去平衡,引入了“单旋转”或“双旋转”的算法。
本文较为全面的介绍了二叉排序树的基本算法,并提供了一样演示程序。
*/
}
{
也许二杈树是很好用的,在插入和查找的时候时间复杂度一般为O(logN),但如果左右
子树失去平衡,也可能达到O(N)。为了防止这种现象发生,一种解决办法是是左右子树尽量
保持平衡,即建立一种平衡有序树AVL树。   
一棵AVL树是其每个结点的左子树和右子树的高度最多相差1的二杈有序树。空树的高度定义为-1。
AVL树的结点声明;
}
PROGRAM AverageTree (input, output);
CONST
    MAX = 1000; {最大结点数量}
TYPE
    element = char;
    AvlTree = ^node;
    node = record
               data : element;
               height : integer; {比普通二杈有序树多了一个高度信息}
               lc, rc : AvlTree;
           end; {record}
    Ary = array[1..MAX] of element;
CONST
    WIDTH = 2; {输出元素值宽度}
    ENDTAG = '#';
VAR
    a : Ary;
    root: AvlTree;
    length : integer;
    data : element;

{AVL树基本操作}
FUNCTION FindMin_1(t : AvlTree): AvlTree; FORWARD;
FUNCTION FindMin_2(t : AvlTree): AvlTree; FORWARD;
FUNCTION FindMax_1(t : AvlTree): AvlTree; FORWARD;
FUNCTION FindMax_2(t : AvlTree): AvlTree; FORWARD;
FUNCTION Height(p : AvlTree): integer; FORWARD;
FUNCTION InsertNode(var t : AvlTree; s : AvlTree) : boolean; FORWARD;
PROCEDURE CreateTree(var t : AvlTree); FORWARD;
PROCEDURE InsertData(var t : AvlTree; data : element); FORWARD;
FUNCTION DelNode(p : AvlTree) : AvlTree;   FORWARD;
PROCEDURE DeleteData(var t : AvlTree; data : element); FORWARD;
PROCEDURE DestroyTree(var t : AvlTree); FORWARD;
FUNCTION GetMax(n1, n2 : integer): integer; FORWARD;

{寻找结点的最大值和最小值}
{递归算法: }
FUNCTION FindMin_1(t : AvlTree): AvlTree;
    begin
        if t = nil then
            FindMin_1 := nil
        else if t^.lc = nil then
            FindMin_1 := t
        else
            FindMin_1 := FindMin_1(t^.lc);
    end; {FindMin_1}

FUNCTION FindMax_1(t : AvlTree): AvlTree;
    begin
        if t = nil then
            FindMax_1 := nil
        else if t^.rc = nil then
            FindMax_1 := t
        else
            FindMax_1 := FindMax_1(t^.rc);
    end; {FindMax}

{非递归算法:}
FUNCTION FindMin_2(t : AvlTree): AvlTree;
    begin
        if t <> nil then
            while t^.lc <> nil do
                t := t^.lc;
        FindMin_2 := t;
    end; {FindMin_2}

FUNCTION FindMax_2(t : AvlTree): AvlTree;
    begin
        if t <> nil then
            while t^.rc <> nil do
                t := t^.rc;
        FindMax_2 := t;
    end; {FindMax_2}

{返回P点的高度}
FUNCTION Height(p : AvlTree): integer;
    begin
        if p = nil then
            Height := -1
        else
            Height := p^.height;
    end; {Height}

{在对一棵AVL树进行插入操作后,可能会破坏它的平衡条件,因此必须对新的AVL树进行调整,
这里用到了“单旋转”或“双旋转”的算法,分别适用于:
单左旋转(SingleRotateWithLeft);对结点p的左孩子的左子树进行一次插入
单右旋转(SingleRotateWithRight);对结点p的右孩子的右子树进行一次插入
双左旋转(DoubleRotateWithLeft);对结点p的左孩子的右子树进行一次插入
双右旋转(DoubleRotateWithRight);对结点p的右孩子的左子树进行一次插入
}
FUNCTION SingleRotateWithLeft(k2 : AvlTree): AvlTree; FORWARD;
FUNCTION SingleRotateWithRight(k2 : AvlTree): AvlTree; FORWARD;
FUNCTION DoubleRotateWithLeft(k : AvlTree): AvlTree; FORWARD;
FUNCTION DoubleRotateWithRight(k : AvlTree): AvlTree; FORWARD;

FUNCTION SingleRotateWithLeft(k2 : AvlTree): AvlTree;
    var
        k1 : AvlTree;
    begin
        k1 := k2^.lc;
        k2^.lc := k1^.rc;
        k1^.rc := k2;

        k1^.height := GetMax(Height(k1^.lc), Height(k1^.rc)) + 1;
        k2^.height := GetMax(Height(k2^.lc), Height(k2^.rc)) + 1;

        SingleRotateWithLeft := k1;
    end; {SingleRotateWithLeft}

FUNCTION SingleRotateWithRight(k2 : AvlTree): AvlTree;
    var
        k1 : AvlTree;
    begin
        k1 := k2^.rc;
        k2^.rc := k1^.lc;
        k1^.lc := k2;

        k1^.height := GetMax(Height(k1^.lc), Height(k1^.rc)) + 1;
        k2^.height := GetMax(Height(k2^.lc), Height(k2^.rc)) + 1;

        SingleRotateWithRight := k1;
    end; {SingleRotateWithRight}

FUNCTION DoubleRotateWithLeft(k : AvlTree): AvlTree;
    begin
        k^.lc := SingleRotateWithRight(k^.lc); {对k^.lc进行一次单右旋转}
        DoubleRotateWithLeft := SingleRotateWithLeft(k);{对k进行一次单左旋转}
    end; {DoubleRotateWithLeft}

FUNCTION DoubleRotateWithRight(k : AvlTree): AvlTree;
    begin
        k^.rc := SingleRotateWithLeft(k^.rc); {对k^.rc进行一次单左旋转}
        DoubleRotateWithRight := SingleRotateWithRight(k);{对k进行一次单右旋转}
    end; {DoubleRotateWithRight}

{向AVL树插入结点的操作}
FUNCTION InsertNode(var t : AvlTree; s : AvlTree) : boolean;
    begin {若s->data等于b的根结点的数据域之值,则什么也不做}
        if t = nil then
        begin
            t := s;
            InsertNode := true;
        end {if}
        else if (t^.data > s^.data) and (InsertNode(t^.lc, s) = true) then {成功地把s所指结点插入到左子树中}
        begin
            if (Height(t^.lc) - Height(t^.rc)) > 1 then {若平衡被破坏}
                if t^.lc^.data > s^.data then {若s比T的左孩子小,对T单左旋转}
                    t := SingleRotateWithLeft(t)
                else                          {否则,对T双左旋转}
                    t := DoubleRotateWithLeft(t);
            InsertNode := true;
        end  {else if}
        else if (t^.data < s^.data) and (InsertNode(t^.rc, s) = true) then {成功地把s所指结点插入到右子树中}
        begin
            if (Height(t^.rc) - Height(t^.lc)) > 1 then {若平衡被破坏}
                if t^.rc^.data < s^.data then {若s比T的右孩子大,对T单右旋转}
                    t := SingleRotateWithRight(t)
                else                          {否则,对T双右旋转}
                    t := DoubleRotateWithRight(t);
            InsertNode := true;
        end {else if}
        else {没有成功插入,即s->data等于b的根结点的数据域之值}
            InsertNode := false;

        t^.height := GetMax(Height(t^.lc), Height(t^.rc)) + 1;
    end; {InsertNode}


{向AVL树插入数据的操作}
PROCEDURE InsertData(var t : AvlTree; data : element);
    var
        s : AvlTree;
    begin {创建一个值域为data的新结点s,并将s插入AVL树}
        new(s);
        s^.data := data;
        s^.height := 0;
        s^.lc := nil;
        s^.rc := nil;
        if not(InsertNode(t, s)) then {插入一个结点s,插入失败则收回s的空间}
            dispose(s);
    end; {InsertData}

{生成一棵AVL树(以ENDTAG为结束标志)}
PROCEDURE CreateTree(var t : AvlTree);
    var
        data : element;
        s : AvlTree;
    begin
        t := nil;
        read(data);
        while data <> ENDTAG do
        begin
            new(s);
            s^.data := data;
            s^.height := 0;
            s^.lc := nil;
            s^.rc := nil;
            if not(InsertNode(t, s)) then  {插入一个结点s,插入失败则收回s的空间}
                dispose(s);
            read(data);
        end; {while}
    end; {CreateTree}

{删除结点p}
FUNCTION DelNode(p : AvlTree) : AvlTree;
    var
        r, q : AvlTree;
    begin
        if p^.lc <> nil then
        begin
            r := p^.lc; {r指向其左子树}
            q := p^.lc; {q指向其左子树}
            while r^.rc <> nil do {搜索左子树的最右边的叶子结点r,q作为r的父亲}
            begin
                q := r;
                r := r^.rc;
            end;
            p^.data := r^.data; {本算法关键:用r的值取代p的值}
            if q <> r then {若r不是p的左孩子,即p^.lc有右孩子}
                q^.rc := r^.lc{把r的左孩子作为r的父亲的右孩子}
            else {否则直接删除r结点}
                p^.lc := r^.lc;
            q^.height := GetMax(Height(q^.lc), Height(q^.rc)) + 1;
        end {if}
        else
        begin
            r := p;
            p := p^.rc; {用p的右孩子取代它}
        end; {else}

        dispose(r); {删除r结点}
        if p <> nil then {p非空结点}
            p^.height := GetMax(Height(p^.lc), Height(p^.rc)) + 1;
        DelNode := p;
    end; {DelNode}

{删除值域为data的结点}
PROCEDURE DeleteData(var t : AvlTree; data : element);
    begin
        if t <> nil then
        begin
            if t^.data = data then
                t := DelNode(t)
            else if t^.data > data then
                DeleteData(t^.lc, data)
            else
                DeleteData(t^.rc, data);
        end; {else}
    end; {DeleteData}

{销毁一棵AVL树}
PROCEDURE DestroyTree(var t : AvlTree);
    begin
        if t <> nil then
        begin
            DestroyTree(t^.lc);
            DestroyTree(t^.rc);
            dispose(t);
            t := nil;
        end; {if}
    end; {DestroyTree}

FUNCTION GetMax(n1, n2 : integer): integer;
    begin
        if n1 > n2 then
            GetMax := n1
        else
            GetMax := n2;
    end; {GetMax}

{AVL树应用示例:
输入一组数,存储到AVL树中,并进行输出
}
FUNCTION Input(var a : Ary): integer; FORWARD; {输入数据到数组,未排序}
PROCEDURE PrintArray(a : Ary; len : integer); FORWARD;{输出数组}
PROCEDURE Sort(var t : AvlTree; a : Ary; len : integer);  FORWARD;{对数组排序,存储到AVL树}
PROCEDURE Inorder(t : AvlTree); FORWARD; {中序遍历AVL树}
PROCEDURE LevelPrint(t : AvlTree); FORWARD; {层序遍历AVL树}

{输入数据到数组,未排序}
FUNCTION Input(var a : Ary): integer;
    var
        data : element;
        i : integer;
    begin
        i := 1;
        read(data);
        while data <> ENDTAG do
        begin
            a[i] := data;
            inc(i);
            read(data);
        end; {while}

        Input := i - 1;
    end; {Input}

{输出数组}
PROCEDURE PrintArray(a : Ary; len : integer);
    var
        i : integer;
    begin
        for i:=1 to len do
            write(a[i]:WIDTH);
        writeln;
    end; {PrintArray}

{对数组排序,存储到AVL树}
PROCEDURE Sort(var t : AvlTree; a : Ary; len : integer);
    var
        i : integer;
    begin
        for i:=1 to len do
            InsertData(t, a[i]);
    end; {Sort}

{中序遍历}
PROCEDURE Inorder(t : AvlTree);
    begin
        if t <> nil then
        begin
            Inorder(t^.lc); {遍历左子树}
            write(t^.data:WIDTH); {输出该结点(根结点)}
            Inorder(t^.rc); {遍历右子树}
        end;
    end; {Inorder}

{层序遍历:
使用循环队列记录结点的层次,设levelUp为上次打印结点层号,level为本层打印结点层号
}
PROCEDURE LevelPrint(t : AvlTree);
    type
        levelNode = record
                        level : integer;
                        pointer : AvlTree;
                    end;
    var
        p : AvlTree;  {p表示当前结点}
        queue : array [0..MAX] of levelNode; {循环队列queue[]用来存储levelNode结点}
        front, rear, levelUp, level : integer;
    begin
        front := -1;
        rear := -1;
        levelUp := 0;
        if t <> nil then {先判断是否为空树}
        begin
            rear := 0;
            queue[rear].level := 1; {结点层号入队}
            queue[rear].pointer := t; {结点内容入队}
        end; {if}

        while front <> rear do {队列非空}
        begin
            front := (front + 1) mod MAX;{出队列,并输出结点}
            level := queue[front].level; {记录当前结点的层号}
            p := queue[front].pointer; {记录当前结点的内容}
            if level = levelUp then {和上次输出的结点在同一层,只输出结点}
                write(p^.data:WIDTH)
            else {和上次输出的结点不在同一层,换行后输出结点并修改levelUp的值}
            begin
                writeln;
                write(p^.data:WIDTH);
                levelUp := level;
            end; {else}
            if p^.lc <> nil then {左孩子非空则入列}
            begin
                rear := (rear + 1) mod MAX;
                queue[rear].level := level + 1; {左孩子层号入列}
                queue[rear].pointer := p^.lc;  {左孩子结点入列}
            end; {if}
            if p^.rc <> nil then {右孩子非空则入列}
            begin
                rear := (rear + 1) mod MAX;
                queue[rear].level := level + 1; {右孩子层号入列}
                queue[rear].pointer := p^.rc;  {右孩子结点入列}
            end; {if}
        end; {while}
    end; {LevelPrint}

BEGIN {main}
    length := Input(a);
    PrintArray(a, length);
    writeln;
    Sort(root, a, length);
    Inorder(root);
    writeln;
    LevelPrint(root);
    writeln;
    write('MAX : ');
    writeln(FindMax_1(root)^.data);
    write('MIN : ');
    writeln(FindMin_1(root)^.data);
    write('MAX : ');
    writeln(FindMax_2(root)^.data);
    write('MIN : ');
    writeln(FindMin_2(root)^.data);
    writeln;
    READLN;
    write('input delete data:');
    read(data);
    readln;
    DeleteData(root, data);
    writeln;
    LevelPrint(root);
    writeln;
    writeln('DestroyTree : ');
    DestroyTree(root);
    if root <> nil then
        LevelPrint(root)
    else
        writeln('DestroyTree!');
    writeln;

    write('CreateTree:');
    CreateTree(root);
    readln;  writeln;
    Inorder(root);
    writeln;  writeln;
    LevelPrint(root);
    writeln;
    write('input delete data:');
    read(data);
    while (root <> nil) and (data <> ENDTAG) do
    begin
        DeleteData(root, data);
        writeln;  writeln;
        Inorder(root);
        writeln;  writeln;
        LevelPrint(root);
        writeln;
        write('input delete data:');
        readln;
        read(data);
        writeln;
    end; {while}

    READLN;  READLN;
END.