1. 程式人生 > >第五章學習小結

第五章學習小結

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 TreeNode
8 { 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 }

三、目標達成

上次定下的目標是多多鞏固所學知識,多多實踐。這一段時間我雖然比較忙,但是依然抽出時間進行了反思,每一次的反思都會有不同的收獲,每一次重新回顧之前學過的知識,都會有新的進步。本次的目標是多多鞏固樹的相關知識,特別是二叉樹和哈夫曼樹。

第五章學習小結