广义表是非线性结构,其定义是递归的。

以下给出几种简单的广义表模型:

由上图我们可以看到,广义表的节点类型无非head、value、sub三种,这里设置枚举类型,利用枚举变量来记录每个节点的类型:

  1. enum Type
  2. {
  3. HEAD, //头节点
  4. VALUE, //值节点
  5. SUB, //子表节点
  6. };

  

每个节点都有自己的类型以及next指针,除此之外,如果该节点是VALUE类型还要分配空间存储该节点的有效值;但是若该节点是SUB类型,就需定义一个指针指向子表的头。

这里我们可以用联合来解决这个问题。

(联合(或共同体)是一种不同数据类型成员之间共享存储空间的方法,并且联合体对象在同一时间只能存储一个成员值)

构造节点

  1. struct GeneralizedNode
  2. {
  3. Type _type; // 1.类型
  4. GeneralizedNode* _next; //2.指向同层的下一个节点
  5. union
  6. {
  7. char _value; // 3.有效值
  8. GeneralizedNode* _subLink; // 3.指向子表的指针
  9. };
  10.  
  11. GeneralizedNode(Type type = HEAD, char value = '0')
  12. :_value(value)
  13. ,_type(type)
  14. , _next(NULL)
  15. {
  16. if (_type == SUB)
  17. {
  18. _subLink = NULL;
  19. }
  20. }
  21. };

 

广义表的定义及基本操作

  1. class Generalized
  2. {
  3. public:
  4. //无参的构造函数,建立空的广义表
  5. Generalized();
  6. //建造广义表,有参数的构造函数
  7. Generalized(const char* str);
  8. //打印广义表
  9. void Print();
  10. //获取值节点的个数
  11. size_t Amount();
  12. //获取广义表的深度
  13. size_t Depth();
  14. //拷贝构造
  15. Generalized(const Generalized& g);
  16. ////赋值运算符的重载
  17. Generalized& operator=(const Generalized& g);
  18. ////析构函数
  19. ~Generalized();
  20.  
  21. protected:
  22. void _Print(GeneralizedNode* head);
  23. GeneralizedNode* _CreatList(const char*& str);
  24. size_t _Amount(GeneralizedNode* head);
  25. GeneralizedNode* _Copy(GeneralizedNode* head);
  26. void _Destory(GeneralizedNode* head);
  27. protected:
  28. GeneralizedNode* _head; //记录广义表头指针
  29. };

 

 初始化建立广义表进行循环递归。遍历字符串时遇到字符就建立值节点,遇到'('就进行递归并建立子表;遇到')'就结束当前子表的建立,并返回当前子表的头指针。

  1. GeneralizedNode* _CreatList(const char*& str)
  2. {
  3. assert(*str == '(');
  4. GeneralizedNode* head = new GeneralizedNode(HEAD,'0');
  5. GeneralizedNode* cur = head;
  6. str++;
  7. while (str != '\0')
  8. {
  9. if ((*str >= '0'&&*str <= '9') || (*str >= 'a'&&*str <= 'z') || (*str >= 'A'&&*str <= 'Z'))
  10. {
  11. cur->_next = new GeneralizedNode(VALUE, *str);
  12. cur = cur->_next;
  13. }
  14. else if (*str == '(')
  15. {
  16. cur->_next = new GeneralizedNode(SUB);
  17. cur = cur->_next;
  18. cur->_subLink = _CreatList(str);
  19. }
  20. else if (*str == ')')
  21. {
  22. return head;
  23. }
  24. str++;
  25. }
  26. return head;
  27. }

 

 打印广义表:当节点的类型为SUB时进行递归,最后不要忘了每打印完一层要打印一个后括号。

  1. void _Print(GeneralizedNode* head)
  2. {
  3. if (head == NULL)
  4. {
  5. cout << "Generalized table is NULL" << endl;
  6. return;
  7. }
  8. GeneralizedNode* cur = head;
  9. while (cur)
  10. {
  11. if (cur->_type == HEAD)
  12. {
  13. cout << '(';
  14. }
  15. else if (cur->_type == VALUE)
  16. {
  17. cout << cur->_value;
  18. if (cur->_next)
  19. {
  20. cout << ',';
  21. }
  22. }
  23. else if (cur->_type == SUB)
  24. {
  25. _Print(cur->_subLink);
  26. if (cur->_next)
  27. {
  28. cout << ',';
  29. }
  30. }
  31. cur = cur->_next;
  32. }
  33. cout << ')';
  34. }

  

获取值节点的个数:设置count变量,遇到值节点就加1,遇到SUB节点进行递归并将返回值加给count

  1. size_t _Amount(GeneralizedNode* head)
  2. {
  3. GeneralizedNode* begin = head;
  4. size_t count = 0;
  5. while (begin)
  6. {
  7. if (begin->_type == VALUE)
  8. {
  9. count++;
  10. }
  11. if (begin->_type == SUB)
  12. {
  13. count += _Amount(begin->_subLink);
  14. }
  15. begin = begin->_next;
  16. }
  17. return count;
  18. }

  

广义表的深度:设置变量dp和max分别用来记录当前子表即当前SUB节点指向的子表深度,以及本层所有的SUB节点中深度最大的子表的深度。

  1. size_t _Depth(GeneralizedNode* head)
  2. {
  3. if (_head == NULL)
  4. {
  5. return 0;
  6. }
  7. size_t dp=0;
  8. GeneralizedNode* cur = head;
  9. size_t max = 0;
  10. while (cur)
  11. {
  12. if (cur->_type == SUB)
  13. {
  14. dp=_Depth(cur->_subLink);
  15. if (max < dp)
  16. {
  17. max = dp;
  18. }
  19. }
  20. cur = cur->_next;
  21. }
  22. return max+1;
  23. }

 

销毁广义表:依次遍历节点,遇到子表递归,将子表的节点delete完成后,再回到当前层继续遍历。

  1. void _Destory(GeneralizedNode* head)
  2. {
  3. if (head == NULL)
  4. {
  5. return;
  6. }
  7. while (head)
  8. {
  9. GeneralizedNode* begin = head->_next;
  10. if (head->_type == SUB)
  11. {
  12. _Destory(head->_subLink);
  13. }
  14. delete head;
  15. head = begin;
  16. }
  17. }

  广义表的拷贝构造及赋值运算符重载与构造函数的递归方式类似,这里就不再阐述冗余信息。

 

广义表(C++实现)的更多相关文章

  1. 数据结构(C语言第2版)-----数组,广义表,树,图

    任何一个算法的设计取决于选定的数据结构,而算法的实现依赖于采用的存储结构. 之前线性表的数据元素都是非结构的原子类型,元素的值是不可再分的.下面学习的这两个线性表是很特殊的,其中数据元素本身也可能是一 ...

  2. 广义表 Head Tail

    head:取非空广义表的第一个元素 tail:取非空广义表除第一个元素外剩余元素构成的广义表 L=((x,y,z),a,(u,t,w)) head(L)为(x,y,z) head(head(L))为x ...

  3. 数据结构算法C语言实现(十九)--- 5.5&5.6&5.7广义表

    一.简述 传说Lisp的基本数据结构就是广义表,广义表也是具有典型递归属性的数据结构,此外,由于建表要处理字符串,用C语言处理起来也是一脸懵逼.....最后自己还想写一个将广义表还原成字符串的函数,一 ...

  4. javascript实现数据结构:广义表

    原文:javascript实现数据结构:广义表  广义表是线性表的推广.广泛用于人工智能的表处理语言Lisp,把广义表作为基本的数据结构. 广义表一般记作: LS = (a1, a2, ..., an ...

  5. c/c++ 广义表

    广义表 列表里面有列表,比如(1,(2,(3,4)),5) 用链表可以实现 结果如图 guangyibiao.h #ifndef __GUANGYIBIAO__ #define __GUANGYIBI ...

  6. 【C/C++】实现数据结构广义表

    1. 广义表的定义     每个元素可以为Atom,原子,也可以为线性表.      线性表的推广.线性表元素有唯一的前驱和后继,为线性表,而广义表是多层次的线性表      表头:第一个元素,可能是 ...

  7. 数据结构(C语言版)-第4章 串、数组和广义表

    补充:C语言中常用的串运算 调用标准库函数 #include<string.h> 串比较,strcmp(char s1,char s2) 串复制,strcpy(char to,char f ...

  8. 广义表操作 (ava实现)——广义表深度、广义表长度、打印广义表信息

    广义表是对线性表的扩展——线性表存储的所有的数据都是原子的(一个数或者不可分割的结构),且所有的数据类型相同.而广义表是允许线性表容纳自身结构的数据结构. 广义表定义: 广义表是由n个元素组成的序列: ...

  9. 数据结构:广义表的实现(Java)

    广义表的简单理解在这篇博文中:https://blog.csdn.net/lishanleilixin/article/details/87364496,在此不做赘述. Java实现广义表: pack ...

  10. 数据结构28:广义表及M元多项式

    广义表,又称为列表.记作: LS = (a1,a2,…,an) ;( LS 为广义表的名称, an 表示广义表中的数据). 广义表可以看作是线性表的推广.两者区别是:线性表中的数据元素只能表示单个数据 ...

随机推荐

  1. 关于javaSocket中 Software caused connection abort: recv failed问题

    在学习Socket中今天突然遇到了以下这种问题 原来是网路连接出了问题,由于我測试的是远程连接所以是在学校的局域网下,结果非常不稳定,開始还以为怎么了一会连上了一会又出现故障然后把IP地址改为本机的1 ...

  2. centos自动安装镜像脚本

    #!/bin/bash ######################################################################################## ...

  3. windows下简单配置squid反向代理服务器

    下载windwosNT版本的squid下载地址: http://squid.acmeconsulting.it/download/squid-2.6.STABLE13-bin.zip 1.把squid ...

  4. performSelector 方法的自己主动俘获特性

    局部变量自己主动俘获 偶然在调试中发现,performSelector 方法具有自己主动俘获变量的特性.试看例如以下代码: CGFloat c = _addViewShowing ? 0 : 80; ...

  5. DDD中的聚合和UML中的聚合以及组合的关系

    UML:聚合关系:成员对象是整体的一部分,但是成员对象可以脱离整体对象独立存在.如汽车(Car)与引擎(Engine).轮胎(Wheel).车灯(Light)之间的关系为聚合关系,引擎.轮胎.车灯可以 ...

  6. Junit使用教程(三)

    四.实例总结 1. 参数化测试 有时一个测试方法,不同的参数值会产生不同的结果,那么我们为了测试全面,会把多个参数值都写出来并一一断言测试,这样有时难免费时费力,这是我们便可以采用参数化测试来解决这个 ...

  7. zendstudio的安装和破解

    参考博客地址:http://www.oxox.work/web/php-basic/zendstudio/ 注明:还未验证

  8. MongoDB可视化工具 Studio 3T

    告别终端使用可视化工具Studio 3T对MongoDB进行数据库的操作. 简单的使用步骤介绍 1.启动MongoDB服务器(方法见MongoDB介绍与安装中的介绍) 2.连接MongoDB服务器  ...

  9. python 基础 9.9 查询数据

      #/usr/bin/python #-*- coding:utf-8 -*- #@Time   :2017/11/24 4:21 #@Auther :liuzhenchuan #@File   : ...

  10. 博弈SG函数

    转自:Sprague-Grundy Function-SG函数--博弈论(3) 公平游戏的Sprague-Grundy定理 公平游戏是一种双人游戏,在游戏中双方都有完整的信息,没有牵涉,任何状态的合法 ...