引言
数组是一个数据元素的集合,元素之间具有线性关系,但是,元素可以参与多个线性关系(前面讲的都是参与一个);
广义表是一个数据元素的集合,元素之间具有线性关系,但其前驱后继可以是一般元素,也可以是一个表。即广义表中放松对表元素的原子限制,容许它们具有其自身结构。
也可以说广义表(Lists,又称列表)是一种非线性的数据结构,是线性表的一种推广。但如果广义表的每个元素都是原子,它就变成了线性表。
一、广义表的定义
广义表一般记作 LS = (a1, a2, ···, an),
- n是广义表的_ 长度 _。ai可以是单个元素(原子),也可以是广义表(子表),
- LS是广义表的名字,通常广义表的_ 名字 _ 用大写字母表示。_ 单元素_一般用小写字母表示.
- 当广义表非空时,称第一个元素a1为LS的 _ 表头 ,称其余元素组成的表为LS的 表尾 _。注意:表头是元素(可以是原子,也可以是广表),表尾一定是广义表。
例:
((a),a)的表头是(a),表尾是(a),
((a))的表头是(a),表尾是( )。
- _ 深度 _:简单说就是表的嵌套层次,定义为:
1 2 3 4 5
| LS = ( dl , d2 ,... ,dn ) depth ( LS ) =max{depth(dl), depth(d2),... ,depth(dn) } + l 0 di 是单元素 depth ( di ) = { l di 是空表
|
5.举例说明:(长度、单元素、子表、表头、深度)
A = ( ) ; A空表,表长为0,深度1;
B = (e) ; B中只有一个元素e,表长为1,表头:e ,表尾 ( ),深度1;
C = (a,(b,c,d)); C的表长为2,两个元素分别为 a 和子表,表头:a, 表尾 ((b,c,d)),深度2;
D = (A,B,C) ; D 的表长为3,它的三个元素 A,B,C 广义表;表头:A 表尾 (B,C),深度3;
depth(D)=max{1,1,2}+1
E=(a, E); E是一个递归的表。
F=(( ),(e),(a,(b,c,d))); F是多层次的广义表,长度为3,深度为3。


二、广义表的数据结构定义
- gen_list.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| #ifndef _GEN_LIST_H_ #define _GEN_LIST_H
#define MATCH (0) #define NOT_MATCH (1)
#include "tools.h"
typedef enum { HEAD = 0, INT, CHARACTER, LIST }Node_type;
typedef struct Gen_node { Node_type n_type; union { int int_value; char char_value; int head_flag; struct Gen_node *head; }value; struct Gen_node *next; }Gen_node;
typedef struct Gen_node *Gen_list;
Gen_list init_genlist(char *input_str);
void destroy_genlist(Gen_list *gen_list);
int get_genlist_count(Gen_list gen_list);
int get_genlist_depth(Gen_list gen_list);
Gen_list copy_genlist(Gen_list gen_list);
void show_genlist(Gen_list gen_list);
#endif
|
三、广义表的接口实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400
| #include <stdio.h> #include <strings.h> #include <ctype.h>
#include "gen_list.h" #include "tools.h"
Boolean is_input_empty(char *string); Boolean is_braket_match(char *string);
char *delete_blank(char *string); void delete_braket(char *src_str, char *des_str, int strlen); void get_item(char *sub_str, char *item_str);
Gen_node *create_node(void); Gen_node *create_head_node(int head_flag); Gen_node *create_int_node(int head_flag); Gen_node *create_char_node(const char character); Gen_node *create_list_node(Gen_node *p_list); Gen_list create_genlist(char *string);
void show_genlist_value(Gen_list gen_list);
Boolean is_input_empty(char *string) { return strlen(string) == ZERO || strcmp(string, "()") == ZERO; }
Boolean is_braket_match(char *string) { int flag = MATCH; int i = 1;
if(string[0] != '(') { return NOT_MATCH; } flag ++;
while(string[i] != '\0') { if(string[i] == '(') { flag ++; } else if(string[i] == ')') { flag --; } if(flag == MATCH && string[i+1] != '\0') { return NOT_MATCH; } i ++; } return flag == MATCH ? MATCH : NOT_MATCH ; }
char *delete_blank(char *string) { int i = 0; int j = 0;
if(string == NULL) { return string; } while(string[j] = string[i]) { if(isblank(string[i])) { i++; continue; } i++; j++; } return string; }
void delete_braket(char *src_str, char *des_str, int strlen) { strncpy(des_str, src_str + 1, strlen -2 ); des_str[strlen -2 ] = '\0'; }
void get_item(char *sub_str, char *item_str) { int i = 0; int flag = 0; int sub_len = strlen(sub_str);
while(i < sub_len) { if(sub_str[i] == '(') { flag++; } if(sub_str[i] == ')') { flag--; } if(flag == 0 && sub_str[i] == ',') { break; } i ++; }
if(i == sub_len) { strcpy(item_str, sub_str); sub_str[0]= '\0'; } else { strncpy(item_str, sub_str, i); item_str[i] = '\0'; strcpy(sub_str, sub_str + i +1); } }
Gen_node *create_node(void) { Gen_node *result = (Gen_node *)Malloc(sizeof(Gen_node)); bzero(result, sizeof(Gen_node));
return result; }
Gen_node *create_head_node(int head_flag) { Gen_node *node = create_node(); node->n_type = HEAD; node->value.head_flag = head_flag;
return node; }
Gen_node *create_int_node(int int_value) { Gen_node *node = create_node(); node->n_type = INT; node->value.int_value = int_value;
return node; }
Gen_node *create_char_node(const char character) { Gen_node *node = create_node(); node->n_type = CHARACTER; node->value.char_value = character;
return node; }
Gen_node *create_list_node(Gen_node *p_list) { Gen_node *node = create_node(); node->n_type = LIST; node->value.head = p_list;
return node; }
Gen_list create_genlist(char *string) { char *sub_str = NULL; char *item_str = NULL; int str_len = strlen(string); Gen_node *p_node = NULL;
if(is_input_empty(string) == TRUE) { fprintf(stderr, "input illegal!\n"); return NULL; } Gen_list start = create_head_node(1); p_node = start;
sub_str = (char *)Malloc(sizeof(char) * str_len); item_str = (char *)Malloc(sizeof(char) * str_len);
delete_braket(string, sub_str, str_len); while(strlen(sub_str)) { get_item(sub_str, item_str); if(item_str[0] != '(' && item_str[0] != '\'') { p_node->next = create_int_node(atoi(item_str)); } else if(item_str[0] != '(' && item_str[0] == '\'') { p_node->next = create_char_node(item_str[1]); } else { p_node->next = create_list_node(create_genlist(item_str)); } p_node = p_node->next; }
free(sub_str); free(item_str);
return start; }
void show_genlist_value(Gen_list gen_list) { Gen_node *p_node = NULL;
if(gen_list == NULL) { return ; } printf("("); p_node = gen_list->next;
while(p_node != NULL) { if(p_node->n_type == INT) { printf("%d", p_node->value.int_value); } else if(p_node->n_type == CHARACTER) { printf("'%c'", p_node->value.char_value); } else { show_genlist_value(p_node->value.head); } if(p_node->next != NULL) { printf(","); } p_node = p_node->next; } printf(")"); }
Gen_list init_genlist(char *input_str) { if(input_str == NULL || is_input_empty(input_str) == TRUE || is_braket_match(input_str) == NOT_MATCH) { return NULL; } delete_blank(input_str); return create_genlist(input_str); }
void destroy_genlist(Gen_list *gen_list) { Gen_node *p_node = NULL; if(gen_list == NULL || *gen_list == NULL) { return ; }
p_node = *gen_list; while(p_node != NULL) { *gen_list = p_node->next; if(p_node->n_type == LIST) { destroy_genlist(&(p_node->value.head)); } free(p_node); p_node = *gen_list; } }
int get_genlist_count(Gen_list gen_list) { int count = 0; Gen_node *p_node = NULL;
if(gen_list == NULL) { return -1; } p_node = gen_list->next;
while(p_node != NULL) { if(p_node->n_type == INT) { count ++; } else if(p_node->n_type == CHARACTER) { count ++; } else { count += get_genlist_count(p_node->value.head); } p_node = p_node->next; } return count; }
int get_genlist_depth(Gen_list gen_list) { int count = 0; Gen_node *p_node = NULL;
if(gen_list == NULL) { return -1; } p_node = gen_list->next;
while(p_node != NULL) { if(p_node->n_type == LIST) { count += get_genlist_depth(p_node->value.head); } p_node = p_node->next; } count++; return count; }
Gen_list copy_genlist(Gen_list gen_list) { Gen_node *p_node = NULL; Gen_node *q_node = NULL; Gen_list new_list = (Gen_list)Malloc(sizeof(gen_list)); bzero(new_list, sizeof(gen_list));
if(gen_list == NULL) { printf("NULL\n"); return NULL; } p_node = gen_list->next; q_node = new_list;
while(p_node != NULL) { if(p_node->n_type == INT) { q_node->next = create_int_node(p_node->value.int_value); } else if(p_node->n_type == CHARACTER) { q_node->next = create_char_node(p_node->value.char_value); } else { q_node->next = create_list_node(p_node->value.head); } p_node = p_node->next; q_node = q_node->next; } q_node = NULL;
return new_list; }
void show_genlist(Gen_list gen_list) { show_genlist_value(gen_list); printf("\n"); }
|
四、代码功能测试
目录结构:
1 2 3 4 5 6 7 8 9
| . ├── gen_list ├── gen_list.c ├── gen_list.h ├── main.c ├── tools.c └── tools.h
0 directories, 7 files
|
测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| #include <stdio.h> #include <stdlib.h> #include "gen_list.h"
int main(int argc, char **argv) { Gen_list list = NULL; Gen_list new_list = NULL;
char str[] = "(15, 'c', (20, 'd', (30, 'f')), ('g', 'i'), 60)";
list = init_genlist(str); show_genlist(list);
printf("%d\n",get_genlist_count(list)); printf("%d\n",get_genlist_depth(list));
new_list = copy_genlist(list); show_genlist(new_list); destroy_genlist(&list); return 0; }
|
测试结果:
1 2 3 4 5 6 7 8 9 10 11
| root@aemonair:~# cc.sh *.c Compiling ... -e CC gen_list.c main.c tools.c -g -lpthread -e Completed . -e Sat Jun 25 00:55:16 CST 2016
root@aemonair:~# ./gen_list (15,'c',(20,'d',(30,'f')),('g','i'),60) 9 4 (15,'c',(20,'d',(30,'f')),('g','i'),60)
|
总结
至此,我们学习到了一种叫做广义表的数据结构,并且进行了操作接口的实现。
1.广义表是数据元素的有限序列,可以是单个元素,也可以是广义表。
2.一对表头和表尾可唯一确定广义表。
3.我们采用了链式存储结构,而且我们的节点可以是多种类型,或者是广义表节点。