第五章學習小結
阿新 • • 發佈:2019-05-04
color 是我 左右 出隊 style 並且 下標 pre bre
第五章學習小結
一、學習心得
這是第五章的思維導圖,本章的重點內容在於二叉樹的性質、存儲結構、遍歷二叉樹以及哈夫曼樹,我覺得這些內容比較好理解,但是對於哈夫曼樹的構造算法的掌握還是不夠熟練,應當進一步加強。
二、題目
(1)List Leaves
這道題的目的是求葉子結點,我的方法是采用隊列的方法實現層次遍歷。
1 #include<iostream> 2 #include<queue> 3 4 using namespace std; 5 6 typedef int Tree; 7 struct TreeNode8 { 9 Tree Left; 10 Tree Right; 11 }T[10]; 12 int N,check[10]={0},count=0; 13 queue<int> q; 14 15 Tree BuildTree(struct TreeNode T[]) 16 { 17 Tree Root=-1; 18 int i; 19 char lch,rch; 20 cin>>N; 21 if(N) 22 { 23 for(i=0;i<N;i++) 24 {25 cin>>lch>>rch; 26 if(lch!=‘-‘) 27 { 28 T[i].Left=lch-‘0‘; 29 check[T[i].Left]=1; 30 } 31 else T[i].Left=-1; 32 if(rch!=‘-‘) 33 { 34 T[i].Right=rch-‘0‘; 35 check[T[i].Right]=1; 36 } 37 else T[i].Right=-1; 38 } 39 for(i=0;i<N;i++) 40 if(check[i]==0) break; 41 Root=i; 42 } 43 return Root; 44 } 45 46 void countleaves(Tree Root)//每碰到一個節點將它的左右孩子入隊(若有的話),然後依次從隊頭取出判斷是否為葉子節點 47 { 48 Tree temp; 49 if(Root==-1) return; 50 q.push(Root); 51 while(!q.empty()) 52 { 53 temp=q.front(); 54 q.pop(); 55 if(T[temp].Left==-1&&T[temp].Right==-1)//如果沒有左右孩子即為葉子節點,則輸出 56 { 57 if(count++!=0)//不是第一個葉子節點的話前面輸出空格 58 { 59 cout<<‘ ‘; 60 } 61 cout<<temp; 62 } 63 if(T[temp].Left!=-1) q.push(T[temp].Left); 64 if(T[temp].Right!=-1) q.push(T[temp].Right); 65 } 66 } 67 int main() 68 { 69 Tree R; 70 R=BuildTree(T); 71 countleaves(R); 72 return 0; 73 }
(2)深入虎穴
這道題是運用到了構造動態數組的方法
1 #include<iostream> 2 #include<queue> 3 using namespace std; 4 typedef struct 5 { 6 int doors;//門的數量 7 int *p;//p指向具體門的編號,把p看作一個整型數組 8 }node; 9 10 int input(node *&a); 11 int find(node *a,int); 12 13 int main() 14 { 15 node *a;//定義一個動態的整型數組 16 int i,j,root; 17 root=input(a);//輸入 18 cout<<find(a,root)<<endl;//輸出 19 return 0; 20 } 21 22 int input(node *&a) 23 { 24 int n,x,i,j; 25 bool *vi;//用於判斷根 26 cin>>n; 27 a=new node[n+1];//為a數組申請空間 28 vi=new bool[n+1];//為vi數組申請空間 29 for(i=1;i<=n;i++)//將vi數組初始化為false 30 vi[i]=false; 31 for(i=1;i<=n;++i) 32 { 33 cin>>x; 34 a[i].doors=x; 35 a[i].p=new int [x];//有效下標是0~x-1 36 for(j=0;j<x;++j) 37 { 38 cin>>a[i].p[j]; 39 vi[a[i].p[j]]=true; 40 } 41 } 42 for(i=1;i<=n;++i) 43 if(!vi[i])break; 44 return i; //找出根在a數組的下標 45 } 46 int find(node *a,int root)//從a數組的root下標開始往下搜索 47 { 48 int x,i; 49 queue<int>q;//定義用於存放帶訪問的門的編號的隊列 50 q.push(root);//根編號入隊 51 while(!q.empty()) 52 { 53 x=q.front(); 54 q.pop(); 55 for(i=0;i<a[x].doors;++i) 56 q.push(a[x].p[i]); 57 }//當隊列不為空,x=出隊,x後面的門的號碼入隊,答案就是x 58 return x; 59 }
(3)樹的同構
這道題是我做了很久的一道題,思路是用數組存儲樹,通過下標訪問數組的方式得到它的左右子樹。最難的地方在於如何判斷兩棵樹是否同構,首先要找到它的根節點才能進行比較,從輸入的數據題目的圖可以發現根節點是沒有結點指向它的,即輸入的數據中不會出現根結點,所以我們用check數組保存所有結點的指向(下標)置為0,每次從輸入中獲取到指向後,將指向的數組位置置為1,最後沒有被指到的位置的節點即為根結點。
1 #include<iostream> 2 using namespace std; 3 typedef char ElementType; 4 typedef int Tree; 5 struct TreeNode 6 { 7 ElementType Data; 8 Tree Left; 9 Tree Right; 10 }T1[10],T2[10]; 11 int N,check[10];//check數組用於尋找樹的根節點 12 13 Tree BuildTree(struct TreeNode T[]) 14 { 15 int Root=-1,i;//剛開始將節點置為空,若為空樹的時候可返回-1 16 char cl,cr; 17 cin>>N; 18 if(N)//如果不為空樹的話 19 { 20 for(i=0;i<N;i++) check[i]=0;//將check數組置為0 21 for(i=0;i<N;i++) 22 { 23 cin>>T[i].Data>>cl>>cr; 24 if(cl!=‘-‘) 25 { 26 T[i].Left=cl-‘0‘; 27 check[T[i].Left]=1; 28 } 29 else 30 T[i].Left=-1; 31 32 if(cr!=‘-‘) 33 { 34 T[i].Right=cr-‘0‘; 35 check[T[i].Right]=1; 36 } 37 else 38 T[i].Right=-1; 39 40 } 41 for(i=0;i<N;i++) 42 if(!check[i]) break; 43 Root=i; 44 } 45 return Root; 46 } 47 int compare(Tree R1,Tree R2) 48 { 49 if((R1==-1)&&(R2==-1))//如果為空樹則是同構的 50 return 1; 51 if(((R1==-1)&&(R2!=-1))||((R1!=-1)&&(R2==-1)))//如果一個為空一個不為空則不是同構的 52 return 0; 53 if((T1[R1].Data)!=(T2[R2].Data))//如果數據不同則不是同構的 54 return 0; 55 if((T1[R1].Left==-1)&&(T2[R2].Left==-1))//如果左兒子都為空判斷右兒子是否同構:主要看以上三個方面(1)右兒子是否都為空(2)是否一個有右兒子一個沒有(3)右兒子數據是否相同 56 return compare(T1[R1].Right,T2[R2].Right);//如果兩棵樹左兒子都不為空並且數據還是一樣的,對左兒子進行遞歸 57 if ( ((T1[R1].Left!=-1)&&(T2[R2].Left!=-1))&&((T1[T1[R1].Left].Data)==(T2[T2[R2].Left].Data)) ) 58 return ( compare( T1[R1].Left, T2[R2].Left )&&compare( T1[R1].Right, T2[R2].Right ) );// 如果兩棵樹左兒子(一個空一個不空或者都不空)並且數據不一樣,那麽判斷第一棵樹的左(右)兒子是否跟第二棵樹的右(左)兒子同構 59 else 60 return ( compare( T1[R1].Left, T2[R2].Right)&&compare( T1[R1].Right, T2[R2].Left ) ); 61 62 } 63 int main() 64 { 65 Tree R1,R2; 66 R1=BuildTree(T1); 67 R2=BuildTree(T2); 68 if(compare(R1,R2)) //compare函數判斷是否同構 69 cout<<"Yes"; 70 else cout<<"No"; 71 return 0; 72 }
三、目標達成
上次定下的目標是多多鞏固所學知識,多多實踐。這一段時間我雖然比較忙,但是依然抽出時間進行了反思,每一次的反思都會有不同的收獲,每一次重新回顧之前學過的知識,都會有新的進步。本次的目標是多多鞏固樹的相關知識,特別是二叉樹和哈夫曼樹。
第五章學習小結