• 广义表


    结点类型定义:

     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!
    ");
      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!
    ");
     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哒!

  • 相关阅读:
    04-老马jQuery教程-DOM节点操作及位置和大小
    03-老马jQuery教程-DOM操作
    02-老马jQuery教程-jQuery事件处理
    01-老马jQuery教程-jQuery入口函数及选择器
    08Vue.js快速入门-Vue综合实战项目
    09Vue.js快速入门-Vue入门之Vuex实战
    07Vue.js快速入门-Vue路由详解
    06Vue.js快速入门-Vue组件化开发
    整套高质量前端基础到高级视频教程免费发布
    05-Vue入门系列之Vue实例详解与生命周期
  • 原文地址:https://www.cnblogs.com/gotodsp/p/3854322.html
Copyright © 2020-2023  润新知