數據結構題集(C語言版 清華大學出版社)


數據結構 第六章 樹

清華大學出版社數據結構習題集 第六章 樹 整理

這里寫圖片描述

輸入數據
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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM