数据结构题集(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 }

 

posted @ 2018-08-21 09:29  暴走的二萌  阅读(3033)  评论(0编辑  收藏  举报