1. 程式人生 > >第五章 樹與二叉樹

第五章 樹與二叉樹

需要 輸入 版本 ecc 在定義函數時 體會 ret 完成 spa

這周學習了樹和二叉樹。

主要就是遞歸,之前一直不明白遞歸是什麽,通過這幾次課我了解的更詳細,也體會到了遞歸的神奇之處。

來記錄一些我從課堂上學到了知識吧

技術分享圖片
二叉樹的課堂筆記
1,    返回值,先看函數要幹嘛,如果是對內容進行操作類,無需結果回傳
2,原型聲明,直接copy函數定義那裏,只不過形參括號內不用類型定義
Typedef struct Node{//結構體定義,鏈表的結點定義
ElemType data;
Struct node *lchild;
Struct node *rchild;
}Node,*Bitree;//都是代表二叉樹的結點名稱,區別就是Node *t之某個結點的指針,Bitree指頭指針(或是說根節點)
Void PreOrder(Node*/Bitree t)//t是一個根節點 (註意!在定義函數時,括號裏的形參要有類型定義) { If(t==NULL) return;(return用法?返回上層? cout << t->data << “ “;(輸出根的數據,為什麽記錄的是用雙引號 PreOrder(t->lchild); PreOrder(t->rchild);//用遞歸造樹,(只對本層寫正確邏輯,不考慮下層) } //函數說明:左孩子為空時,return退出當前函數,返回上層(遞歸),進行PreOrder(t->rchild)
void create (Bitree &t)//建立一棵空樹,t指向根結點 //發現該樹傳不回去,說明是形參問題,但是t是指針,為什麽會傳不回去呢?但對t進行操作時,如果改變的是其直接空間,如操作(a),,只改變地址,不改變t的內容,如改變其間接空間,如(a[1],a[2])是不需要&) {//每建立一棵樹,先讀入,再判斷是否#(為空樹) ElemType x;//以X作為根結點的樹 cin >> x; if (x == ‘#’){//建立一顆空樹 t = NULL;//有指針就要賦初值
return ;//強行中止函數執行 } t == new Node;//為t分配像Node結構的空間 //操作的是間接空間 //形參不用再在函數內進行定義!!直接用 t->data = x;//輸入根結點x create(t->lchild); create(t->rchild); //一般操作先寫主函數架構思路,再不斷補充函數的操作 Int main() { Bitree t ==NULL;//結構體Bitree直接用,形參在主函數中定義就夠了! create( t );//創造讀入樹 註意在主函數中引用函數直接寫函數名(形參)即可 PreOrder( t );//讀出樹 return 0; }
課堂小筆記1

以及老師帶我們打的深入虎穴的思路

技術分享圖片
1.      對樹進行層次遍歷
2.    門的編號1-N
3.    由編號得出可用數組
4.      二維數組表現樹的存儲關系,符合行號列號置一
5.    第二種
6.    10的5次*10 的5次,考慮稀疏矩
7.    可看為1維數組
8.    存儲指針(單鏈表)
9.    先定義一個結構體(整數加指針)
10.    第二種,指針P後面帶了一個數組P【0】,P【111.    P指針後面用new申請一個新數組空間
思路

再然後是作業啦,

技術分享圖片
 1 #include<iostream>
 2 #include<queue>
 3 using namespace std;
 4 
 5 typedef char ElemType;
 6 
 7 typedef struct Node{//結構體定義,鏈表的結點定義
 8 ElemType data;
 9 struct Node *lchild;
10 struct Node *rchild;
11 }Node,*Bitree;//都是代表二叉樹的結點名稱,區別就是Node *t之某個結點的指針,Bitree指頭指針(或是說根節點)
12 
13 void levelOrderTraverse(Bitree t, int x)//t是一個根節點  //PreOrder函數用於遍歷輸出 (層次遍歷) 
14 {
15   queue<int> q;
16   int m;
17   if(t==NULL) return;
18   if(t->lchild == NULL && t->rchild == NULL )
19   q.push(t->data);
20   while(!q.empty()){
21       m == q.front();
22       q.pop();
23       if(!q.empty())
24       cout << m <<" ";
25       else cout << m;
26     q.push(t[m].lch);//??t要用數組表示不然表示不出跳到下一個指針的方法 
27     q.push(t[m].rch);
28   }
29   //用遞歸造樹,(只對本層寫正確邏輯,不考慮下層)
30 }
31 //函數說明:左孩子為空時,return退出當前函數,返回上層(遞歸),進行PreOrder(t->rchild)
32 
33 int BulidTree(Bitree t)
34 {
35     
36     
37     bool check[100] = {false};
38     int n;
39     char x, y;
40     
41     cin >> n;
42     
43     for (int i=0; i<n; i++){
44         
45         cin >> x >> y;
46         
47         if(x!=-){
48           t->lchild = x-0;
49           check[t->lchild] = true;
50         }
51         else 
52           t->lchild = -1;
53           
54         if(y!=-){
55           t->rchild = y-0;
56           check[t->rchild] = true;
57         }
58         else
59           t->rchild = -1;
60     }
61     
62     for (int i=0; i<n; i++){
63         if(!check[i]) return i;
64     }
65 }
66 
67 /*void create (Bitree &t)//建立一棵樹,並讀入,t指向根結點
68 {//每建立一棵樹,先讀入,再判斷是否-(為空樹)//在輸入樹時順便找根結點 
69   ElemType x;//以X作為根結點的樹
70   cin >> x;
71   if (x == ‘-‘){//根為空 
72     t = NULL;//有指針就要賦初值
73     return ;//強行中止函數執行
74   }
75   //x!=‘-‘;
76   t == new Node;//為t分配像Node結構的空間
77   t->data = x-‘0‘;//輸入根結點數字x
78   create(t->lchild);
79   create(t->rchild);
80 }
81 */
82 
83 int main()
84 {
85   int x; 
86   Bitree t;//不能Bitree t == NULL 
87   t == NULL;//結構體Bitree直接用,形參在主函數中定義就夠了!
88   //create(t);//創造讀入樹  註意在主函數中引用函數直接寫函數名(形參)即可
89   x == BulidTree(t);//找到根結點 
90   levelOrderTraverse(t, x);//讀出樹
91   return 0;
92 }
版本1

這個因為結點用的是指針,所以在如何把左孩子轉化為下一個指針的時候出現了問題,暫時還沒想到解決的辦法,

於是我換成了用數組表示本結點的名字,這樣就可以通過i來表示。

技術分享圖片
 1 #include<iostream>
 2 #include<queue>
 3  
 4 using namespace std;
 5 
 6 typedef struct{//樹結點的類型定義 
 7     int lch;
 8     int rch;
 9 }node;
10 
11 int BulidTree(node t[]);
12 void levelOrderTraverse(node t[], int x); //層次遍歷 
13 
14 
15 int main()
16 {    
17     node t[100];//??怎麽可以直接node一個數組呢 
18     int x; 
19     
20     x = BulidTree(t);//找出了根節點x 
21     levelOrderTraverse(t, x);      //水平遍歷並輸出葉子結點  
22     return 0; 
23 }
24 
25 int BulidTree(node t[])//輸入並查找根結點 
26 {
27     bool check[100] = {false};//判斷根結點的標誌 
28     int n;
29     char x, y;
30     
31     cin >> n;
32     
33     for (int i=0; i<n; i++){
34         
35         cin >> x >> y;//輸入左孩子和右孩子 
36         
37         if(x!=-){//如果孩子不為空 
38           t[i].lch = x-0;//給孩子賦值 
39           check[t[i].lch] = true;//標誌改為ture 
40         }
41         else 
42           t[i].lch = -1;//否則孩子為-1 
43           
44         if(y!=-){
45           t[i].rch = y-0;
46           check[t[i].rch] = true;
47         }
48         else
49           t[i].rch = -1;
50     }
51     
52     for (int i=0; i<n; i++){
53         if(!check[i]) return i;//返回根結點下標 
54     }
55 }
56     
57 void levelOrderTraverse(node t[], int x)
58 {//層次遍歷t[x]為根結點的樹t
59     int tmp;
60     queue<int> q;
61     q.push(x); //根結點所在下標入棧 
62     int flag = 0;    //用flag做判斷第一個輸出的指標 
63     while(!q.empty()){
64         tmp = q.front(); //記錄隊頭元素 
65         q.pop();
66         flag++;
67         if(t[tmp].lch==-1 && t[tmp].rch==-1)//如果是葉子結點 ,輸出 
68         {
69             if(flag == 0) cout << tmp;
70             else cout << " " << tmp;
71         }
72             q.push(t[tmp].lch);//如何做到層次遍歷 
73             q.push(t[tmp].rch);
74         
75     } 
76 } 
版本2

這個版本也出現了一點問題,不知道哪裏出錯了,排錯排的時間有點久,希望下次能加快發現錯誤的時間。

上周目標達成:因為假期出去玩的有點多,所以作業質量不是很好,但是改錯的能力加強了,這點還是讓人有感到成就感的,慢慢理解到了一些剛開始不懂得東西,比如自定義類型為什麽要這樣寫之類的小問題。

本周目標:做到邊打代碼邊寫註釋,而不是打完之後才寫

繼續認真復習,總結歸納

認真完成作業。

第五章 樹與二叉樹