广义表

结点类型定义:

 1 /* 

 2  * 结点类型

 3  */

 4 enum NodeType { head, atom, sublist };

 5 

 6 /*

 7  * 定义广义表的结点结构(注意union的使用)

 8  */

 9 struct Node

10 {

11     Boolean flag;               // 结点标志,附加表头结点->flag=0;原子结点->flag=1;子表结点->flag=2

12     union

13     {

14         ElementType data;       // 原子结点数据域

15         struct Node *sublist;   // 指示全表或子表第一个结点的指针域

16     } value;

17     struct Node *next;          // 指示后件结点的指针域

18 };

19 

20 /* 

21  * 类似于用单链表表示线性表那样,也可以对表示广义表的链表定义一个结构类型,类型中只包含链表的头指针,其定义如下:

22  */

23 struct GeneralizedList

24 {

25     struct Node *first;         // 链表存储的广义表的头指针

26 };

基本操作:

  1 /*

  2  * 创建一个空广义表

  3  */

  4 void initGeneralizedList(struct Node *first)

  5 {

  6     first = (struct Node *)malloc(sizeof(Node));    // 分配一个新结点作为附加表头结点

  7     if(first == NULL) {                             // 申请内存失败,则退出

  8         printf("Memory allocation failure!\n");

  9         exit(-1);

 10     }

 11     first->flag = 0;                          // 置附加表头结点标志

 12     first->value.sublist = NULL;              // 置子表指针域为空

 13     first->next = NULL;                       // 置后件结点域为空

 14 }

 15 

 16 /*

 17  * 求广义表的长度

 18  */

 19 int getGLLength(struct Node *first)

 20 {

 21     struct Node *current = first;                   // fist是广义表的头指针,指向附加表头结点

 22     if(current->flag == NodeType.head) {        

 23         current = current->value.sublist;           // 使current指针指向第一个元素结点

 24     }

 25 

 26     if(current == NULL) {                           // 表为空,长度为0

 27         return 0;

 28     } else {                                        // 表不为空

 29         int length = getGLLength(current->next);    // current指针指向的表长度

 30         return length + 1;                          // current->next指针指向的表的长度 + current当前指针所指结点1

 31     }

 32 }

 33 

 34 /*

 35  * 求广义表的长度,非递归实现

 36  */

 37 int getGLLength(struct Node *first)

 38 {

 39     struct Node *current = first;

 40     if(current->flag == NodeType.head) {

 41         current = current->value.sublist;

 42     }

 43 

 44     int length = 0;

 45     while(current != NULL) {

 46         ++length;

 47         current = current->next;

 48     }

 49 

 50     return length;

 51 }

 52 

 53 /*

 54  * 求广义表深度:递归实现

 55  * 思路:

 56  * 广义表的深度等于它的各子表的最大深度加1

 57  */

 58 int getGLDeepth(struct Node *first)

 59 {

 60     struct Node *current = first;

 61     if(currento->flag == NodeType.head)

 62         current = current->value.sublist;                       // 确保current指向第一个元素结点

 63 

 64     /*****揣度*****/

 65     int maxDeepth = 0;                                          // maxDeepth记录子表最大深度,初值为0

 66     while(current != NULL) {

 67         if(current->flag == NodeType.sublist) {

 68             int deepth = getGLDeepth(current->value.sublist);   // 求子表深度

 69             if(deepth > maxDeepth)

 70                 maxDeepth = deepth;                    // 记录当前所搜索子树的最大深度

 71         }

 72         current = current->next;                       // 指向下一结点

 73     }

 74 

 75     return maxDeepth + 1;                              // 返回当前层次的深度

 76 }

 77 

 78 /*

 79  * 复制广义表:递归实现

 80  * 思路:

 81  * 对广义表每个结点的三个域分别进行复制即可

 82  */

 83 struct Node* copyDeeply(struct Node *first)

 84 {

 85    if(first == NULL) {

 86         return NULL;

 87    } else {

 88         struct Node *temp = (struct Node *)malloc(sizeof(struct Node));         // 建立一个用于复制数据的结点

 89         if(temp == NULL) {

 90             printf("Memory allocation failure!\n");

 91             exit(-1);

 92         }

 93         temp->flag = first->flag;                                               // 复制结点标志域

 94         if(first->flag == NodeType.head || first->flag == NodeType.sublist)

 95             temp->value.sublist = copyDeeply(first->value.sublist);             // 复制结点的值:此时为指针

 96         else 

 97             temp->value.data = first->value.data;                               // 复制结点的值:此时为具体数据类型对应的数据

 98 

 99         temp->next = copyDeeply(first->next);                       // 复制广义表的表尾部分

100         return temp;

101    }

102 }

103 

104 /*

105  * 建立广义表的存储结构

106  * 假设:广义表以字符形式存放于字符数组str[]中。

107  * 广义表中的元素由一堆圆括号所包含,元素之间用逗号分隔,且每一层子表都由一重圆括号来表示,空表用空格表示,以分号作为整个广义表的结束符

108  * 思路:

109  * 从左到右依次读入str[]中的各字符,并根据其所表示的不同结点类型建立相应的存储结构:

110  *  1、对空表结点,置标志、其子表指针置空

111  *  2、对原子结点,置标志、存入数据元素

112  *  3、对子表结点,通过递归调用建立起子表存储结点

113  *  4、若结点有后继结点,通过递归调用建立其后继存储结点

114  *  e.g.    (g, ,(a,(e,f)));

115  */

116 void createGL(struct Node *head, char str[])

117 {

118     char currentChar;                                           // 存放当前读入的字符

119     static int index = -1;                                      // index指示当前读入位置

120     currentChar = str[++index];                                 // 读入一个字符    

121     if(currentChar == ' ')                                      // 若读入字符为空格,指示新结点的指针为空

122         head = NULL;

123     else if(currentChar == '(') {                               // 若读入字符为左括号,则建立一个新的表结点

124         head = (struct Node *)malloc(sizeof(struct Node));

125         if(index == 0)

126             first->flag = NodeType.head;                  // 建立附加表头结点

127         else 

128             first->flag = NodeType.sublist;               // 建立子表结点

129         createGL(head->value.sublist, str[]);             // 递归创建子表

130     } else {                                                    // 若读入的是原子结点,则建立原子结点

131         head = (struct Node *)malloc(sizeof(struct Node));

132         head->flag = NodeType.atom;

133         head->value.data = currentChar;

134     }

135     if(head == NULL)

136         return ;

137 

138     currentChar = str[++index];                               // 读入下一字符

139     if(currentChar == ',')                                    // 若读入逗号,则递归创建表尾部分

140         createGL(head->next, str[]);

141     else if(currentChar == ')' || currentChar == ';')         // 扫描到表元素结束符或全表结束符,后件指针域为空

142         head->next = NULL;

143 }

144 

145 /*

146  * 遍历并输出广义表

147  * 思路:

148  * 逐一遍历广义表中的每个元素结点;

149  *  1、若是原子结点,则输出元素值

150  *  2、若是子表结点,则通过递归调用遍历子表中的元素结点

151  *  3、若有后继结点,则通过递归调用遍历后件元素结点

152  */

153 void outGL(struct Node *head)

154 {

155     if(head->flag == NodeType.head || head->flag == NodeType.sublist) {     // 扫描到附加表头结点或子表表头结点

156         printf("(");                        // 输出全表或子表的起始符“(”;注意:括号是必须匹配的

157         if(head->value.sublist == NULL)     // 若结点的子表指针域为空

158             printf(" ");

159         else 

160             outGL(head->value.sublist);     // 递归遍历子表

161     } else {

162         printf("%d", head->value.data);

163     }

164     if(head->flag == NodeType.head || head->flag == NodeType.sublist)// 若一个表遍历结束,输出表结束符“)”,匹配之前的左括号

165         printf(")");

166 

167     if(head->next != NULL) {        // 若当前结点有后继结点

168         printf(",");

169         outGL(head->next);          // 遍历后继表

170     }

171 }

 

OK哒!

你可能感兴趣的:(表)