1. 程式人生 > >AVL樹的基本操作之插入(遞迴與非遞迴編碼)(2)

AVL樹的基本操作之插入(遞迴與非遞迴編碼)(2)

摘要:(1)插入的基本思路;首先遞迴的插入,插入完成之後,逐個返回,對於返回的每一個節點都要檢查,是否該次插入是使得這個節點不平衡。為了簡化程式碼,定義一個Height()函式,用來處理該節點為NULL的情況。當該節點不平衡時,就要進行旋轉。根據插入元素與該節點元素兒子的大小關係可以確定旋轉型別。
(2)非遞迴程式設計有一點麻煩:基本思路還是用一個棧來保留經過的節點。

int Height(Position T)//獲得高度
{
    if (T==NULL)
        return -1;
    else
        return T->Height;
}
int Max
(int x,int y)//返回一個較大值 { if (x == y) return x; else return x>y?x:y; } Position InsertAvl(Position T,int X)//遞迴演算法 { if (T == NULL) { T = (Position)malloc(sizeof(AvlTreeRecord)); T->Element = X; T->Height = 0; T->Left = NULL; T->
Right = NULL; } else // { if (X >T->Element) { T->Right = InsertAvl(T->Right,X); if (Height(T->Right)-Height(T->Left) == 2){//需要調整 if (X > T->Right->Element) T = SingleRotateRight(T); else
T = DoubleRotateRight(T); } } else if (X< T->Element) { T->Left = InsertAvl(T->Left,X); if(Height(T->Left)-Height(T->Right) == 2){//需要調整 if (X < T->Left->Element) T = SingleRotateLeft(T); else T = DoubleRotateLeft(T); } } T->Height = Max(Height(T->Left),Height(T->Right))+1; return T; } } Position Insert_noninduction(int X,Position T) { int mark1,mark2; Position Temp = T; List L,P; L = (List)malloc(sizeof(ListRecord)); L->mark = -1; P = L->Next; if (T == NULL) { //直接插入 T = Create(X); return T; } while(1) { if (X > T->Element)//進入右子樹 { //連結串列記錄 L->Next = CreateList(T); L->Next->Previous = L; L = L->Next; L->mark = Rtree; if (T->Right == NULL) { T->Right = Create(X); break; } else T = T->Right; } else //進入左子樹 { //連結串列記錄 L->Next = CreateList(T); L->Next->Previous = L; L = L->Next; L->mark = Ltree; if (T->Left == NULL) { T->Left = Create(X); break; } else T = T->Left; } }//while P = L;//儲存最後的節點,方便確定旋轉 while(L->mark!=-1) { //從葉子向上計算插入路徑上節點的高度 L->Pointer->Height = Max(Height(L->Pointer->Left),Height(L->Pointer->Right))+1; L = L->Previous; } L = P;//將L恢復到插入節點的父節點 //進行判斷是否旋轉以及進行節點連線 do { if (abs(Height(L->Pointer->Left) - Height(L->Pointer->Right)) == 2) { T = L->Pointer; mark1 = L->mark; mark2 = L->Next->mark; switch (mark1) { //確定進行哪種調整 case Rtree: if (mark2 == Rtree) T = SingleRotateRight(T); else T = DoubleRotateRight(T); break; case Ltree: if (mark2 == Ltree) T = SingleRotateLeft(T); else T = DoubleRotateLeft(T); break; } //用來確定旋轉後與父節點的連結方式 if (L->Previous->mark != -1) { switch(L->Previous->mark) { case Rtree: L->Previous->Pointer->Right = T; break; case Ltree: L->Previous->Pointer->Left = T; } } else //root 是調整點,無需與父節點連結. Temp = T; } L = L->Previous; } while(L->mark != -1); return Temp; }