數據結構 第六章 樹
清華大學出版社數據結構習題集 第六章 樹 整理
輸入數據
13
1 2 3 0 0 1 0 0 0 0 0 0 1
6
1 // 35 順序存儲結構 2 const int MAXSIZE = 20; 3 typedef struct 4 { 5 Elemtype data[MAXSIZE+1]; // data[0]不存儲元素,因為順序存儲結構二叉樹的根節點從1開始層次遍歷+1 6 int length; 7 }SqBiTree; 8 void createSqBiTree(SqBiTree &st) 9 { 10 Elemtype x; 11 int n; 12 cout << "n:"; 13 cin >> n; 14 for (int i = 0;i<n;i++) 15 { 16 cin>>x; 17 st.data[i+1] = x; 18 } 19 st.length = n; 20 } 21 void print(SqBiTree &st) 22 { 23 for (int i=1;i<=st.length;i++) 24 cout << st.data[i]<<' '; 25 } 26 // 求出下標志為I的結點對應的十進制整數 27 // 思路:parent = i/2,如果為偶數則為0,奇數則為1 28 int thirty_five(SqBiTree &st,int i) 29 { 30 int sum =0; 31 int j = 0; 32 while (i) 33 { 34 if (i%2!=0) 35 { 36 sum += pow(2,j); 37 } 38 j++; 39 i = i/2; 40 } 41 return sum; 42 } 43 int main() 44 { 45 SqBiTree st ; 46 createSqBiTree(st); 47 cout << "i:"; 48 int i;cin>>i; 49 cout << "十進制整數:"<<thirty_five(st,i)<<endl; 50 return 0; 51 }

1 // 36 判定兩棵二叉樹是否相似 2 int similar(BiTree &t1,BiTree &t2) 3 { 4 if (t1==NULL && t2==NULL) 5 return 1; 6 if (t1!=NULL && t2!=NULL) 7 { 8 int l = similar(t1->lchild,t2->lchild); 9 int r = similar(t1->rchild,t2->rchild); 10 return l&r; 11 }else 12 return 0; 13 } 14 int main() 15 { 16 BiTree t1,t2; 17 createBiTree(t1); 18 createBiTree(t2); 19 if (similar(t1,t2)) 20 cout <<"similar!"<<endl; 21 else 22 cout <<"not similar!"<<endl; 23 return 0; 24 }
1 // 39 增設雙親域和標志域時不用棧進行后序遍歷的遞推形式 2 typedef struct NBiNode 3 { 4 Elemtype data; 5 struct NBiNode *lchild,*rchild,*parent; 6 int mark;// 0 1 2 7 }NBiNode,*NBiTree; 8 void createNBiTree(NBiTree &nt,NBiTree &parent) 9 { 10 Elemtype x; 11 cin >> x; 12 if (x!='#') 13 { 14 nt = (NBiTree)malloc(sizeof(NBiTree)); 15 nt->data = x; 16 nt->mark = 0; 17 nt->parent = parent; 18 createNBiTree(nt->lchild,nt); 19 createNBiTree(nt->rchild,nt); 20 } 21 else 22 { 23 nt = NULL; 24 } 25 } 26 /* 27 思路: 28 1. 從parent走到當前子樹根節點,Mark為0,轉為1 29 2. Mark為1時:轉到左子樹,設Mark為2 30 3. Mark為2時轉到右子樹,設Mark為0哦,訪問結點 31 */ 32 void postOrderUnWithPM(NBiTree &t) 33 { 34 NBiTree p = t; 35 while (p){ 36 switch(p->mark) 37 { 38 case 0: 39 // 第一次訪問P結點 40 p->mark =1; 41 if (p->lchild) 42 p = p->lchild; 43 break; 44 case 1: 45 // 第二次訪問P結點 46 p->mark = 2; 47 if (p->rchild) 48 p = p->rchild; 49 break; 50 case 2: 51 // 訪問右結點結束后需要打印根節點 52 cout << p->data << ' '; 53 p->mark = 0; 54 p = p-> parent; 55 break; 56 } 57 } 58 59 } 60 int main() 61 { 62 NBiTree nt; 63 NBiTree p; 64 p =NULL; 65 createNBiTree(nt,p); 66 postOrderUnWithPM(nt); 67 68 return 0; 69 }
1 // 40 只設雙親域不用棧如何中序遍歷 2 typedef struct NBiNode 3 { 4 Elemtype data; 5 struct NBiNode *lchild,*rchild,*parent; 6 }NBiNode,*NBiTree; 7 void createNBiTree(NBiTree &nt,NBiTree &parent) 8 { 9 Elemtype x; 10 cin >> x; 11 if (x!='#') 12 { 13 nt = (NBiTree)malloc(sizeof(NBiTree)); 14 nt->data = x; 15 nt->parent = parent; 16 createNBiTree(nt->lchild,nt); 17 createNBiTree(nt->rchild,nt); 18 } 19 else 20 { 21 nt = NULL; 22 } 23 } 24 25 26 void midOrder(NBiTree &nt) 27 { 28 NBiTree p = nt; 29 while (p) 30 { 31 if (p->lchild) 32 { 33 p = p->lchild; 34 } 35 else 36 { 37 cout << p->data <<' '; // 從左子樹回到根節點,打印根節點;此時根據右子樹是否為空進行判斷 38 while (!p->rchild) 39 {//右子樹為空,兩種情況,1. 雙親的左子樹:往上走,打印結點;2 雙親的右子樹,不必打印 40 while (p->parent && p->parent->rchild == p) 41 { 42 p = p->parent; 43 } 44 if (p->parent) 45 { 46 if (p->parent->lchild == p) 47 { 48 p = p->parent; 49 cout << p->data << ' '; // 走到根節點又要判斷右子樹是否為空 50 } 51 }else 52 { 53 return ;// 右子樹的雙親為空,那就是中序遍歷完啦! 54 } 55 } 56 // 右子樹不為空,往右走 57 p = p->rchild; 58 59 } 60 } 61 } 62 63 int main() 64 { 65 NBiTree nt; 66 NBiTree p; 67 p =NULL; 68 createNBiTree(nt,p); 69 midOrder(nt); 70 return 0; 71 }
1 // 45 2 // 遞歸,對於二叉樹中的每一個元素值為X的結點,刪去以他為根的子樹,並釋放相應空間 3 // 遞歸清空子樹 4 void delete2(BiTree &t) 5 { 6 if (!t) return ; 7 if (t->lchild) 8 delete2(t->lchild); 9 if (t->rchild) 10 delete2(t->rchild); 11 delete t; 12 t = NULL; // 13 } 14 void deleteBiTree(BiTree &t,Elemtype x) 15 { 16 if (t) 17 { 18 if (t->data == x ) // string.h 和 string 這真的是兩個頭文件! 19 delete2(t); 20 else { // 如果刪除了左右孩子就都沒有了!★ 21 deleteBiTree(t->lchild,x); 22 deleteBiTree(t->rchild,x); 23 } 24 } 25 } 26 27 int main() 28 { 29 BiTree t; 30 createBiTree(t); 31 Elemtype x; 32 cout << "x:"; 33 cin >> x; 34 deleteBiTree(t,x); 35 preOrder(t); 36 return 0; 37 }
1 // 48 求兩節點的共同祖先 2 // 找到root到P的路徑存到數組中 3 // 思路:比較根節點和P指針是否相同,若相同返回1已找到;否則壓入根節點,判斷左右子樹能否找到該結點並返回1 4 // 如果左右子樹均沒有找到也就意味着該路徑上沒有P結點(走錯路啦!)彈棧出根節點 5 int findPath(BiTree &root,Elemtype &p,BiTree a[],int &top) 6 { 7 if (root->data == p ) 8 return 1; // 先比較根節點:相等則返回1,說明找到p,但此時路徑數組為空,說明沒有祖先 9 a[++top] = root; // 根節點入棧 10 int has = 0; 11 if (root->lchild) 12 has = findPath(root->lchild,p,a,top); 13 if (has == 0 && root->rchild) 14 has = findPath(root->rchild,p,a,top); 15 if (has == 0) 16 { 17 top -- ; 18 } 19 return has; 20 } 21 22 BiTree findGrandpa(BiTree &root,Elemtype p,Elemtype q) 23 { 24 int top1 = -1,top2 = -1; // TOP 指向a,b的頂層 25 // 存儲兩節點的路徑到數組中,尋找相同的最靠右的部分 26 BiTree a[20]={}; 27 BiTree b[20]={}; 28 if (findPath(root,p,a,top1)!=0 && findPath(root,q,b,top2)!=0) 29 { 30 for (int i = top1;i>-1;i--) 31 for (int j = top2;j>-1;j--) 32 if (a[i]== b[j]) 33 return a[i]; 34 } 35 } 36 int main() 37 { 38 BiTree t; 39 createBiTree(t); 40 Elemtype p,q; 41 cout <<"p,q:"; 42 cin >> p >> q; 43 BiTree grand = findGrandpa(t,p,q); 44 cout << "grandpa : " << grand->data <<endl; 45 return 0; 46 }
判斷一棵二叉樹是否是完全二叉樹
我們要如何判斷一棵二叉樹是否是完全二叉樹???
1)如果一個結點有右孩子而沒有左孩子,那么這棵樹一定不是完全二叉樹。
2)如果一個結點有左孩子,而沒有右孩子,那么按照層序遍歷的結果,這個結點之后的所有結點都是葉子結點這棵樹才是完全二叉樹。
3)如果一個結點是葉子結點,那么按照層序遍歷的結果,這個結點之后的所有結點都必須是葉子結點這棵樹才是完全二叉樹。
求一棵二叉樹的層序遍歷,我們借助的是數據結構—-隊列。如果一個結點不是葉子結點,我們將當前結點出隊,將其孩子入隊;如果一個結點是葉子結點,我們直接將其出隊即可。這是之前求一棵樹層序遍歷的結果的思路,我們可以借助這個思路,來完成此題。
根據上邊分析的2)和3),我們知道,如果一個結點沒有左右孩子或者僅有左孩子,它之后的結點必須全部是葉子結點,這棵樹才可能是完全二叉樹。所以,我們必須定義一個bool變量,來記錄是否到了滿足2)或者3)的結點,如果滿足,我們只需要判斷它之后的結點是否是葉子結點即可。
1 // 49 編寫算法判定給定二叉樹是否為完全二叉樹 2 /* 3 1. 層次搜索 4 2. 設一個布爾數組記錄訪問過的結點,檢查數組中是否有false 5 3. 遞歸算法:給出完全二叉樹與原定義等價的遞歸定義,設計一個判別給定的二叉樹是滿二叉樹、不滿二叉樹還是非完全二叉樹的遞歸函數 6 7 */ 8 const int Maxsize = 20; 9 // 2. 檢查數據中是否有false 10 bool isFull(BiTree &t) 11 { 12 BiTree que[Maxsize]; 13 int front = 0,rear = 0; 14 BiTree p; 15 Elemtype data[Maxsize] = {}; 16 int i = 0; 17 if (t) 18 { 19 rear = (rear + 1)%Maxsize; 20 que[rear] = t; 21 data[i] = t->data; 22 while (front != rear) 23 { 24 front = (front+1)%Maxsize; 25 p = que[front]; 26 if (p->lchild) 27 { 28 rear = (rear+1)%Maxsize; 29 que[rear]=p->lchild; 30 data[++i] = p->lchild->data; 31 } // 有左子樹則放入數據否則放入零 32 else 33 data[++i] = 0; 34 if (p->rchild) 35 { 36 rear = (rear+1)%Maxsize; 37 que[rear]=p->rchild; 38 data[++i] = p->rchild->data; 39 } 40 else 41 data[++i] = 0; 42 43 } 44 for (int j = 1;j<i;j++) 45 { // 檢查是否有字母夾着單個0的情況,因為最后也都是0 46 if (data[j-1]!=0 && data[j+1]!=0 && data[j] == 0) 47 return false; 48 } 49 } 50 return true; 51 } 52 53 // 用一個數組記錄遍歷過得結點序號,看是否連續 54 bool isFull2(BiTree &t) 55 { 56 int i=0,j=0; 57 BiTree que[Maxsize] = {}; // front 58 int order[Maxsize] = {}; // j i 59 BiTree p; 60 int front = 0,rear = 0; 61 if (t) 62 { 63 que[++rear] = t; 64 order[++i] = ++j; // order[1] = 1 根節點序號 65 while (front != rear) 66 { 67 p = que[++front]; 68 if (order[i]!= order[i-1]+1) // 結點序號不連續 69 return false; 70 if (p->lchild) 71 { 72 que[++rear] = p->lchild; 73 order[++i] = 2*p->data; 74 } 75 if (p->rchild) 76 { 77 que[++rear] = p->rchild; 78 order[++i] = 2*p->data+1; 79 } 80 } 81 return 1 ; 82 } 83 } 84 int main() 85 { 86 BiTree t; 87 createBiTree(t); 88 cout << isFull2(t)<< endl; 89 return 0; 90 }
1 // 50 2 /* 3 1. 三元組序列 (F, C, L/R) 4 2. ^代表根節點的雙親 5 3. ^^代表輸入終點 6 4. 層次表示輸入 7 */ 8 BiTree three() 9 { 10 Elemtype thr[3]; 11 BiTree que[Maxsize]; 12 int front = 0,rear =0; 13 BiTree t,p,q; 14 cin >> thr[0] >>thr[1] >> thr[2]; 15 while (thr[0]!='^' || thr[1]!='^') 16 { 17 if (thr[0] == '^' ) 18 { 19 t = (BiTree )malloc(sizeof(BiTree)); 20 t->data = thr[1]; 21 t->lchild = NULL; 22 t->rchild = NULL; 23 que[++rear] = t; // 根節點入隊 24 p = t; 25 front = 1; 26 } 27 else 28 { 29 if (thr[2] == 'L') 30 { 31 p->lchild = q; 32 } 33 if (thr[2]=='R') 34 { 35 p->rchild = q; 36 } 37 } 38 39 cin >> thr[0] >> thr[1] >> thr[2]; 40 q = (BiTree)malloc(sizeof(BiTree)); 41 q->data = thr[1]; 42 q->lchild = NULL; 43 q->rchild = NULL; 44 que[++rear] = q; 45 // 每輸入一組,便把數據入隊 46 if (thr[0] != p->data) 47 { 48 // 出隊 49 p = que[++front]; 50 } 51 52 } 53 return t; 54 } 55 int main() 56 { 57 BiTree t; 58 t = three(); 59 preOrder(t); 60 61 return 0; 62 } 63 //51 輸出以二叉樹表示的算數表達式,如果右括號在輸出時應添上 64 bool isOperator(Elemtype c) 65 { 66 if (c=='+' || c=='-' || c=='*' || c=='/') 67 return true; 68 else 69 return false; 70 } 71 bool lowPrior(Elemtype a,Elemtype b) 72 { 73 if ((a == '+' || a == '-')&&(b=='*' || b == '/')) 74 return true; 75 else 76 return false; 77 } 78 void biao(BiTree &t) 79 { 80 if (t) 81 { 82 if (t->lchild) 83 { 84 if (isOperator(t->lchild->data) && lowPrior(t->lchild->data,t->data)) 85 { 86 // 如果左孩子是操作符並且優先級低於根節點 87 cout << '(' << ' '; 88 biao(t->lchild); 89 cout <<')' << ' '; 90 } 91 else 92 biao(t->lchild); 93 } 94 95 cout << t->data << ' '; 96 97 if (t->rchild) 98 { 99 if (isOperator(t->rchild->data) && lowPrior(t->rchild->data,t->data)) 100 { 101 // 如果左孩子是操作符並且優先級低於根節點 102 cout << '(' << ' '; 103 biao(t->rchild); 104 cout <<')' << ' '; 105 } 106 else 107 biao(t->rchild); 108 } 109 } 110 } 111 112 int main() 113 { 114 BiTree t; 115 createBiTree(t); 116 preOrder(t); 117 // biao(t); 118 119 return 0; 120 } 121 // 52 一棵二叉樹的繁茂度定義為各層節點數的最大值與樹的高度的乘積 122 123 int fanmao(BiTree &t) 124 { 125 int level,v,i,j; 126 float f; 127 int maxrow,maxcol ; // 最大行和最大列 128 BiTree que[Maxsize] = {}; // 隊列 129 int order[Maxsize] = {};// 存放各節點序號 130 int count[Maxsize] ={};//下標代表層,數組內容為各層結點個數 131 v = 0;i = 0;j = 0;maxcol = 0;maxrow = 0; 132 if (t) 133 { 134 que[j] = t; 135 order[j] = 1; 136 j ++ ; 137 while (i<j) 138 { 139 f = log(order[i])/log(2) ; 140 // 將 x 的自然對數值除以 n 的自然對數值,就可以對任意底 n 來計算數值 x 的對數值:Logn(x) = Log(x) / Log(n) 141 level = (int)f +1 ;// 當前i節點的層數 142 if (maxrow < level) 143 maxrow = level; 144 count[level] ++; 145 // 求出每個節點當前層數,使當前層數的數據++ 146 if (maxcol <count[level]) 147 maxcol = count[level]; 148 149 if (que[i]->lchild) 150 { 151 que[j] = que[i]->lchild; 152 order[j] = 2*order[i] ;// i是雙親節點,j是子節點 153 j++; 154 } 155 if (que[i]->rchild) 156 { 157 que[j] = que[i]->rchild; 158 order[j] = 2*order[i]+1; 159 j++; 160 } 161 i++; 162 } 163 } 164 v = maxcol * maxrow; 165 return v; 166 } 167 int main() 168 { 169 BiTree t; 170 createBiTree(t); 171 cout << fanmao(t); 172 173 174 return 0; 175 }