题目来源:严蔚敏《数据结构》C语言版本习题册 6.67

    【题目】6.67
    假设以二元组(F,C)的形式输入一棵树的诸边(其中F表示双亲结点的标识,C表示孩子结点标识),且在输入的二元组序列C中,C是按层次顺序出现的。F='^'时C为根结点标识,若C也为‘^’,则表示输入结束。例如,如下所示树的输入序列为:
    二元组创建树(孩子兄弟链表)(严蔚敏《数据结构》6.67) - 图1
    试编写算法,由输入的二元组序列建立该树的孩子-兄弟链表。

    【答案】

    1. /*---------------------------------
    2. |6.67 二元组(F,C)创建CSTree |
    3. ---------------------------------*/
    4. #define maxSize 50
    5. Status CreateCSTreeByDuplet(CSTree *pT) {
    6. char input[5];
    7. CSNode *queue[maxSize];int front,rear;
    8. CSNode *p, *q;
    9. front=rear=0; //对队列初始化
    10. for (scanf("%s", input); input[1]!='^'; scanf("%s", input)) {
    11. //创建结点
    12. p = (CSNode *)malloc(sizeof(CSNode)); if (!p) exit(OVERFLOW);
    13. p->data=input[1];p->firstchild=p->nextsibling=NULL;
    14. //入队列
    15. queue[rear]=p;rear=(rear+1)%maxSize;
    16. //找爸爸
    17. if (input[0]=='^') { //根结点-->不需要找爸爸
    18. *pT = p; //传出去
    19. } else {
    20. for (q=queue[front]; q->data!=input[0]; front=(front+1)%maxSize,q=queue[front]) ; //找爸爸
    21. //找哥哥
    22. if (!q->firstchild) q->firstchild=p; //它是最大的
    23. else { //它不是最大的
    24. for(q=q->firstchild; q->nextsibling; q=q->nextsibling) ; //找最近的哥哥
    25. q->nextsibling = p; //和哥哥牵手
    26. }
    27. }
    28. }
    29. return OK;
    30. }

    【完整代码】

    1. /*-------------------
    2. |树-孩子兄弟表达法 |
    3. -------------------*/
    4. #include<stdio.h>
    5. #include<stdlib.h>
    6. #include<string.h>
    7. #ifndef BASE
    8. #define BASE
    9. #define TRUE 1
    10. #define FALSE 0
    11. #define OK 1
    12. #define ERROR 0
    13. #define INFEASIBLE -1
    14. #define OVERFLOW -2
    15. typedef int Status;
    16. typedef int bool;
    17. #endif
    18. #define TElemType char
    19. typedef struct CSNode{
    20. TElemType data;
    21. struct CSNode *firstchild, *nextsibling;
    22. }CSNode, *CSTree;
    23. /*-------------------
    24. |6.59 输出T的所有边 |
    25. -------------------*/
    26. void TreePrintEdge(CSTree T) {
    27. CSNode *p;
    28. for (p=T->firstchild; p; p=p->nextsibling) {
    29. printf("(%c,%c)\n", T->data, p->data); //输出T的孩子
    30. TreePrintEdge(p); //输出p的孩子
    31. }
    32. }
    33. /*-------------------------
    34. |6.60 统计叶子结点的个数 |
    35. -------------------------*/
    36. int TreeLeafCnt(CSTree T) {
    37. // 树的叶子结点-->没有孩子
    38. int ret=0;
    39. CSNode *p;
    40. if (!T) return 0;
    41. else if (!T->firstchild) return 1;
    42. else {
    43. for (p=T->firstchild; p; p=p->nextsibling) ret += TreeLeafCnt(p);
    44. return ret;
    45. }
    46. }
    47. /*-------------------------
    48. |6.61 求树的度 |
    49. -------------------------*/
    50. int TreeDegree(CSTree T) {
    51. // 最大的孩子数
    52. int max=-1;
    53. int cnt=0;
    54. CSNode *child;
    55. if (!T) return -1; //空树
    56. else if (!T->firstchild) return 0; //只有一个根结点,度为0
    57. else {
    58. for (cnt=0,child=T->firstchild; child; child=child->nextsibling) cnt++; //求自己的度
    59. max = cnt; //当前的最大值
    60. for (child=T->firstchild; child; child=child->nextsibling) {
    61. cnt = TreeDegree(child);
    62. if (cnt>max) max=cnt;
    63. }
    64. return max;
    65. }
    66. }
    67. /*-------------------------
    68. |6.62 求树的深度 |
    69. -------------------------*/
    70. int TreeDepth(CSTree T) {
    71. int h1,h2;
    72. if (!T) return 0;
    73. else {
    74. h1 = TreeDepth(T->firstchild)+1; //T孩子的深度+1
    75. h2 = TreeDepth(T->nextsibling); //T兄弟的深度
    76. return h1>h2 ? h1 : h2;
    77. }
    78. }
    79. /*---------------------------------
    80. |6.66 双亲表示法-->孩子兄弟表达式|
    81. ---------------------------------*/
    82. #define MAX_TREE_SIZE 50
    83. typedef struct PTNode{
    84. TElemType data;
    85. int parent; //双亲的位置域
    86. }PTNode;
    87. typedef struct{
    88. PTNode nodes[MAX_TREE_SIZE];
    89. int r,n;
    90. }PTree;
    91. CSTree CreateCSTreeByPTree(PTree T) {
    92. CSNode *tmp[MAX_TREE_SIZE]; //创建一个辅助的数组,仿照PTree结点的位置存放
    93. CSNode *p, *q;
    94. int i,parent;
    95. if (T.n<=0) return NULL;
    96. for (i=0; i<T.n; i++) { //双亲表按层序存储
    97. //创建新结点
    98. p = (CSNode *)malloc(sizeof(CSNode)); if(!p) exit(OVERFLOW);
    99. //赋值
    100. p->data = T.nodes[i].data;p->firstchild=p->nextsibling=NULL;
    101. //连接
    102. parent=T.nodes[i].parent; //父亲
    103. if (parent!=-1) { //不是根结点
    104. if (tmp[parent]->firstchild==NULL) tmp[parent]->firstchild=p; //第一个孩子
    105. else { //不是第一个孩子
    106. for (q=tmp[parent]->firstchild; q->nextsibling; q=q->nextsibling) ; //找到最后一个孩子
    107. q->nextsibling = p; //连接
    108. }
    109. }
    110. tmp[i]=p;
    111. }
    112. return tmp[0];
    113. }
    114. /*---------------------------------
    115. |6.67 二元组(F,C)创建CSTree |
    116. ---------------------------------*/
    117. #define maxSize 50
    118. Status CreateCSTreeByDuplet(CSTree *pT) {
    119. char input[5];
    120. CSNode *queue[maxSize];int front,rear;
    121. CSNode *p, *q;
    122. front=rear=0; //对队列初始化
    123. for (scanf("%s", input); input[1]!='^'; scanf("%s", input)) {
    124. //创建结点
    125. p = (CSNode *)malloc(sizeof(CSNode)); if (!p) exit(OVERFLOW);
    126. p->data=input[1];p->firstchild=p->nextsibling=NULL;
    127. //入队列
    128. queue[rear]=p;rear=(rear+1)%maxSize;
    129. //找爸爸
    130. if (input[0]=='^') { //根结点-->不需要找爸爸
    131. *pT = p; //传出去
    132. } else {
    133. for (q=queue[front]; q->data!=input[0]; front=(front+1)%maxSize,q=queue[front]) ; //找爸爸
    134. //找哥哥
    135. if (!q->firstchild) q->firstchild=p; //它是最大的
    136. else { //它不是最大的
    137. for(q=q->firstchild; q->nextsibling; q=q->nextsibling) ; //找最近的哥哥
    138. q->nextsibling = p; //和哥哥牵手
    139. }
    140. }
    141. }
    142. return OK;
    143. }
    144. int main() {
    145. /*6.57
    146. 测试数据一
    147. ^R
    148. RA
    149. RB
    150. RC
    151. AD
    152. AE
    153. CF
    154. FG
    155. FH
    156. FI
    157. ^^
    158. 测试数据二:
    159. ^A
    160. AB
    161. AC
    162. AD
    163. CE
    164. CF
    165. ^^
    166. */
    167. CSTree CST;
    168. int cnt;
    169. CreateCSTreeByDuplet(&CST);
    170. TreePrintEdge(CST);
    171. cnt = TreeLeafCnt(CST); //6.60 叶子结点个数
    172. printf("TreeLeafCnt:%d\n", cnt);
    173. cnt = TreeDegree(CST); //6.61 树的度
    174. printf("TreeDegree:%d\n", cnt);
    175. cnt = TreeDepth(CST); //6.62 树的深度
    176. printf("TreeDepth:%d\n", cnt);
    177. return 0;
    178. }