首页 > 代码库 > 广义表
广义表
结点类型定义:
1 /* 2 * 结点类型 3 */ 4 enum NodeType { head, atom, sublist }; 5 6 /* 7 * 定义广义表的结点结构(注意union的使用) 8 */ 9 struct Node10 {11 Boolean flag; // 结点标志,附加表头结点->flag=0;原子结点->flag=1;子表结点->flag=212 union13 {14 ElementType data; // 原子结点数据域15 struct Node *sublist; // 指示全表或子表第一个结点的指针域16 } value;17 struct Node *next; // 指示后件结点的指针域18 };19 20 /* 21 * 类似于用单链表表示线性表那样,也可以对表示广义表的链表定义一个结构类型,类型中只包含链表的头指针,其定义如下:22 */23 struct GeneralizedList24 {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 = http://www.mamicode.com/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 =http://www.mamicode.com/ 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哒!
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。