Avl平衡樹--C語言實現(xiàn)

Avl 平衡樹 實現(xiàn)記錄

Avl平衡二叉樹和搜索二叉樹基本實現(xiàn)原理相同苍柏,在搜索二叉樹的基礎(chǔ)上添加樹平衡的操作--單旋和雙旋(這也是AvlTree的重難點)洁奈。插入數(shù)據(jù)和刪除數(shù)據(jù)的時候?qū)溥M(jìn)行平衡調(diào)整。

需要注意:在刪除樹節(jié)點的操作中络断,要注意更新調(diào)整各節(jié)點中高度(Height)的值毡琉。Google搜索結(jié)果中看了前幾個實現(xiàn)AvlTree的文章蕾久,基本都沒考慮節(jié)點Height屬性的更新婉宰。

實現(xiàn)代碼

#include <stdio.h>
#include <stdlib.h>
#define FatalError(str) fprintf(stderr, "%s\n", str), exit(1);
#define Error(str) FatalError(str);

struct AvlNode;
typedef struct AvlNode *Position;
typedef struct AvlNode *AvlTree;
typedef int ElementType;

struct AvlNode
{
    ElementType Element;
    AvlTree Left;
    AvlTree Right;
    int Height;
};

AvlTree
MakeEmpty(AvlTree T);
Position Find(ElementType X, AvlTree T);
Position FindMin(AvlTree T);
Position FindMax(AvlTree T);
AvlTree Insert(ElementType X, AvlTree T);
ElementType Retrieve(Position P);
static int Height(Position P);
static int Max(int, int);
static Position SingleRotateWithLeft(Position P);
static Position SingleRotateWithRight(Position P);
static Position DoubleRotateWithLeft(Position P);
static Position DoubleRotateWithRight(Position P);
AvlTree Delete(Position P, AvlTree T);
void printTree(AvlTree T);
void test();

AvlTree MakeEmpty(AvlTree T)
{
    if (T != NULL)
    {
        MakeEmpty(T->Left);
        MakeEmpty(T->Right);
        free(T);
    }
    return T;
}

ElementType Retrieve(Position P)
{
        return P->Element;
}

Position Find(ElementType X, AvlTree T)
{
    if (T == NULL)
    {
        return NULL;
    }
    else if (X < T->Element)
    {
        return Find(X, T->Left);
    }
    else if (X > T->Element)
    {
        return Find(X, T->Right);
    }
    else
    {
        return T;
    }
}

Position FindMin(AvlTree T)
{
    if (T == NULL)
    {
        return NULL;
    }
    else if (T->Left == NULL)
    {
        return T;
    }
    else
    {
        return FindMin(T->Left);
    }
}

Position FindMax(AvlTree T)
{
    if (T != NULL)
    {
        while (T->Right != NULL)
        {
            T = T->Right;
        }
    }

    return T;
}

static int Height(Position P)
{
    if (P == NULL)
    {
        return -1;
    }

    return P->Height;
}

static int Max(int height1, int height2)
{
    if (height1 > height2)
    {
        return height1;
    }
    return height2;
}

AvlTree Insert(ElementType X, AvlTree T)
{
    if (T == NULL)
    {
        T = malloc(sizeof(struct AvlNode));
        if (T == NULL)
        {
            Error("Error: out of space!!!");
        }
        else
        {
            T->Element = X;
            T->Left = T->Right = NULL;
            T->Height = 0;
        }
    }
    else if (X < T->Element)
    {
        T->Left = Insert(X, T->Left);
        if (Height(T->Left) - Height(T->Right) == 2)
        {
            if (X < T->Left->Element)
            {
                T = SingleRotateWithLeft(T);
            }
            else
            {
                T = DoubleRotateWithLeft(T);
            }
        }
    }
    else
    {
        T->Right = Insert(X, T->Right);
        if (Height(T->Right) - Height(T->Left) == 2)
        {
            if (X > T->Right->Element)
            {
                T = SingleRotateWithRight(T);
            }
            else
            {
                T = DoubleRotateWithRight(T);
            }
        }
    }

    T->Height = Max(Height(T->Left), Height(T->Right)) + 1;
    return T;
}

// 左單旋
static Position SingleRotateWithLeft(Position P)
{
    Position K1;
    K1 = P->Left;
    P->Left = K1->Right;
    K1->Right = P;

    P->Height = Max(Height(P->Left), Height(P->Right)) + 1;
    K1->Height = Max(Height(K1->Left), P->Height) + 1;

    return K1;
}

// 右單旋
static Position SingleRotateWithRight(Position P)
{
    Position K1;
    K1 = P->Right;
    P->Right = K1->Left;
    K1->Left = P;

    P->Height = Max(Height(P->Left), Height(P->Right)) + 1;
    K1->Height = Max(Height(K1->Left), P->Height) + 1;

    return K1;
}

// 左雙旋
static Position DoubleRotateWithLeft(Position P)
{
    P->Left = SingleRotateWithRight(P->Left);
    return SingleRotateWithLeft(P);
}

// 右雙旋
static Position DoubleRotateWithRight(Position P)
{
    P->Right = SingleRotateWithLeft(P->Right);
    return SingleRotateWithRight(P);
}

// 刪除
AvlTree Delete(Position P, AvlTree T)
{
    Position PMix;
    Position Tmp;
    if (T != NULL)
    {
        if (T->Element > P->Element)
        {
            // printf("34\n");
            T->Left = Delete(P, T->Left);
            T->Height = Max(Height(T->Right), Height(T->Left)) + 1;
            if (Height(T->Right) - Height(T->Left) == 2)
            {
                if (T->Right->Element < P->Element)
                {
                    return  SingleRotateWithRight(T);
                }
                else
                {
                    return DoubleRotateWithRight(T);
                }
            }
        }
        else if (T->Element < P->Element)
        {
            T->Right = Delete(P, T->Right);
            
            T->Height = Max(Height(T->Right), Height(T->Left)) + 1;
          
            if (Height(T->Left) - Height(T->Right) == 2)
            {
                if (T->Left->Element > P->Element)
                {
                    return SingleRotateWithLeft(T);
                }
                else
                {
                    return  DoubleRotateWithLeft(T);
                }
            }
        }
        else
        {
            if (T->Right != NULL && T->Left != NULL)
            {
                if (Height(T->Right) > Height(T->Left))
                {
                    PMix = FindMin(T->Right);
                    T->Element = PMix->Element;
                    T->Right = Delete(PMix, T->Right);
                }
                else
                {
                    PMix = FindMax(T->Left);
                    T->Element = PMix->Element;
                    T->Left = Delete(PMix, T->Left);
                }
                T->Height = Max(Height(T->Right), Height(T->Left)) + 1;
            }
            else
            {
                Tmp = P;
                T = P->Right ? P->Right : P->Left;
                free(Tmp);
            }
        }
    }
    return T;
}

void printTree(AvlTree T)
{
    if (T != NULL)
    {
        printTree(T->Left);
        printf("%d", T->Element);
        printTree(T->Right);
    }
}

void test()
{
    int i,n;
    AvlTree T;
    Position P;
    n = 20;
    for(i = 0; i < n; i++)
    {
        T = Insert(i, T);
    }

    printTree(T);
    P = Find(4, T);
    T = Delete(P, T);

    P = Find(5, T);
    T = Delete(P, T);

    P = Find(17, T);
    T = Delete(P, T);

    T = Insert(5, T);
    
    printf("\n");
    printTree(T);
    printf("\n");
    printf("根節(jié)點的高度:%d\n", T->Height);
    printf("根節(jié)點的值:%d\n",T->Element);
}

int main()
{
    test();
}

歡迎關(guān)注我的博客O(∩_∩)O哈哈~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末歌豺,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子心包,更是在濱河造成了極大的恐慌类咧,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蟹腾,死亡現(xiàn)場離奇詭異痕惋,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)娃殖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門值戳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人炉爆,你說我怎么就攤上這事堕虹。” “怎么了叶洞?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵鲫凶,是天一觀的道長。 經(jīng)常有香客問我衩辟,道長,這世上最難降的妖魔是什么波附? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任艺晴,我火速辦了婚禮,結(jié)果婚禮上掸屡,老公的妹妹穿的比我還像新娘封寞。我一直安慰自己,他們只是感情好仅财,可當(dāng)我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布狈究。 她就那樣靜靜地躺著,像睡著了一般盏求。 火紅的嫁衣襯著肌膚如雪抖锥。 梳的紋絲不亂的頭發(fā)上亿眠,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天,我揣著相機(jī)與錄音磅废,去河邊找鬼纳像。 笑死,一個胖子當(dāng)著我的面吹牛拯勉,可吹牛的內(nèi)容都是我干的竟趾。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼宫峦,長吁一口氣:“原來是場噩夢啊……” “哼岔帽!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起导绷,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤犀勒,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后诵次,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體账蓉,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年逾一,在試婚紗的時候發(fā)現(xiàn)自己被綠了铸本。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡遵堵,死狀恐怖箱玷,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情陌宿,我是刑警寧澤锡足,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站壳坪,受9級特大地震影響舶得,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜爽蝴,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一沐批、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蝎亚,春花似錦九孩、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春宪拥,著一層夾襖步出監(jiān)牢的瞬間仿野,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工江解, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留设预,地道東北人。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓犁河,卻偏偏與公主長得像鳖枕,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子桨螺,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內(nèi)容