演算法與資料結構實驗題 6.32 我不會 AVL
阿新 • • 發佈:2020-11-12
★實驗任務
歡迎來到暴走資料結構,我是洪尼瑪。今天,我們來玩 AVL樹,怎麼玩呢?很簡單:給 你n個數字,你需要按順序插入一棵AVL樹中,然後輸出每個數所在節點的深度(從1開始)。 因為我不會AVL樹,所以希望聰明的你們來幫我完成這個任務
★資料輸入
輸入第一個數為n(n≤100000)表示數字的個數
接下來一行輸入n個數,範圍在 1 到 n 之間,每個數只出現一次
★資料輸出
按輸入的順序依次輸出每個數所在節點的深度
輸入示例 |
---|
6 1 2 3 4 5 6 |
輸出示例 |
---|
3 2 3 1 2 3 |
★提示
注意:輸出行末不能有空格
對於50%的資料,1<=n<=100
對於100%的資料,1<=n<=100000
#include<stdio.h> #include<stdlib.h> typedef struct TNode *Position; typedef Position BinTree; typedef int ElementType; int maxsize=100005; struct TNode{ ElementType Data; BinTree Left; BinTree Right; int Height; }a[100005]; Position FindMin( BinTree BST ){if(!BST || !BST->Left)return BST; return FindMin(BST->Left); } Position FindMax( BinTree BST ){ if(!BST || !BST->Right)return BST; return FindMax(BST->Right); } BinTree Delete(BinTree BST,ElementType X) { Position Tmp; if(!BST) printf("要刪除的元素未找到"); else{ if(X < BST->Data) BST->Left = Delete(BST->Left,X);//左子樹遞迴刪除 else if(X > BST->Data) BST->Right = Delete(BST->Right,X);//右子樹遞迴刪除 else{//BST就是要刪除的點 //如果被刪除的結點有左右兩個子結點 if(BST->Left&&BST->Right) { Tmp = FindMin(BST->Right); BST->Data = Tmp->Data; BST->Right = Delete(BST->Right,BST->Data); } else{//被刪除的結點只有一個或無子節點 Tmp = BST; if(!BST->Left) BST = BST->Right; else BST = BST->Left; free(Tmp); } } } return BST; } int Max( int a,int b) { return a > b ? a : b; } int Height(BinTree t) { int hl,hr; if(!t)return -1; hl=Height(t->Left); hr=Height(t->Right); if(hl>hr) return ++hl; else return ++hr; } int GetHeight(BinTree T){ if(!T)return 0; return T->Height; } BinTree SingleLeftRotation(BinTree A) { //注意 A必須有一個左子結點B //將A和B做左單旋,更新A和B的高度,返回新的結點B BinTree B = A->Left; A->Left = B->Right ; B->Right = A; A->Height = Max( GetHeight(A->Left),GetHeight(A->Right))+1; B->Height = Max( GetHeight(B->Left),A->Height)+1; return B; } BinTree SingleRightRotation(BinTree A) { BinTree B = A->Right ; A->Right = B->Left; B->Left = A; A->Height = Max( GetHeight(A->Left),GetHeight(A->Right))+1; B->Height = Max( GetHeight(B->Right),A->Height)+1; return B; } BinTree DoubleLeftRightRotation(BinTree A) { /* 注意:A必須有一個左子結點B,且B必須有一個右子結點C */ /* 將A、B與C做兩次單旋,返回新的根結點C */ /* 將B與C做右單旋,C被返回 */ A->Left = SingleRightRotation(A->Left); /* 將A與C做左單旋,C被返回 */ return SingleLeftRotation(A); } BinTree DoubleRightLeftRotation(BinTree A) { A->Right = SingleLeftRotation(A->Right); return SingleRightRotation(A); } BinTree Insert(BinTree BST,struct TNode &X) { if(!BST) {//若原樹為空,生成並返回一個結點的二叉搜尋樹 BST = &X; BST->Left = BST->Right =NULL; } else //開始查詢要插入的的元素的位置 { if( X.Data < BST->Data ) { BST->Left = Insert(BST->Left,X);//遞迴插入左子樹 if(GetHeight(BST->Left) - GetHeight(BST->Right) == 2) { if( X.Data < BST->Left->Data ) BST = SingleLeftRotation(BST); else BST = DoubleLeftRightRotation(BST); } } else if(X.Data > BST->Data) { BST->Right = Insert(BST->Right,X);//遞迴插入右子樹 if(GetHeight(BST->Left) - GetHeight(BST->Right)== -2) { if(X.Data > BST->Right->Data ) BST = SingleRightRotation(BST); else BST = DoubleRightLeftRotation(BST); } } //else X已經存在,什麼都不做 } BST->Height = Max(GetHeight(BST->Left),GetHeight(BST->Right)) + 1; return BST; } BinTree MakeTree(int N){ BinTree T=NULL; int i,V; for(int i=0;i<N;i++){ scanf("%d",&a[i].Data); T = Insert(T,a[i]); } // for(int i=0;i<N;i++){ // printf("%d ",T->Height+1-a[i].Height); // } return T; } void Find(BinTree T,ElementType X,int *deep){ if(!T||T->Data == X)return ; else{ (*deep)++; return Find(T->Data>X ? T->Left : T->Right ,X,deep); } } void FindDepth(BinTree T,int N) { int deep; for(int i=0;i<N;i++) { deep = 0; Find(T,a[i].Data,&deep); printf("%d ",deep+1); } } int main(){ BinTree T = NULL; int n; scanf("%d",&n); T = MakeTree(n); FindDepth(T,n); return 0; }