第五章 樹與二叉樹
阿新 • • 發佈:2019-05-05
需要 輸入 版本 ecc 在定義函數時 體會 ret 完成 spa
這周學習了樹和二叉樹。
主要就是遞歸,之前一直不明白遞歸是什麽,通過這幾次課我了解的更詳細,也體會到了遞歸的神奇之處。
來記錄一些我從課堂上學到了知識吧
二叉樹的課堂筆記 1, 返回值,先看函數要幹嘛,如果是對內容進行操作類,無需結果回傳 2,原型聲明,直接copy函數定義那裏,只不過形參括號內不用類型定義 Typedef struct Node{//結構體定義,鏈表的結點定義 ElemType data; Struct node *lchild; Struct node *rchild; }Node,*Bitree;//都是代表二叉樹的結點名稱,區別就是Node *t之某個結點的指針,Bitree指頭指針(或是說根節點)課堂小筆記1Void 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. 對樹進行層次遍歷 2. 門的編號1-N 3. 由編號得出可用數組 4. 二維數組表現樹的存儲關系,符合行號列號置一 5. 第二種 6. 10的5次*10 的5次,考慮稀疏矩 7. 可看為1維數組 8. 存儲指針(單鏈表) 9. 先定義一個結構體(整數加指針) 10. 第二種,指針P後面帶了一個數組P【0】,P【1】 11. 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
這個版本也出現了一點問題,不知道哪裏出錯了,排錯排的時間有點久,希望下次能加快發現錯誤的時間。
上周目標達成:因為假期出去玩的有點多,所以作業質量不是很好,但是改錯的能力加強了,這點還是讓人有感到成就感的,慢慢理解到了一些剛開始不懂得東西,比如自定義類型為什麽要這樣寫之類的小問題。
本周目標:做到邊打代碼邊寫註釋,而不是打完之後才寫
繼續認真復習,總結歸納
認真完成作業。
第五章 樹與二叉樹