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

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

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

enum  Type
{
HEAD, //头节点
VALUE, //值节点
SUB, //子表节点
};

  

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

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

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

构造节点

struct GeneralizedNode
{
Type _type; // 1.类型
GeneralizedNode* _next; //2.指向同层的下一个节点
union
{
char _value; // 3.有效值
GeneralizedNode* _subLink; // 3.指向子表的指针
}; GeneralizedNode(Type type = HEAD, char value = '0')
:_value(value)
,_type(type)
, _next(NULL)
{
if (_type == SUB)
{
_subLink = NULL;
}
}
};

 

广义表的定义及基本操作

class Generalized
{
public:
//无参的构造函数,建立空的广义表
Generalized();
//建造广义表,有参数的构造函数
Generalized(const char* str);
//打印广义表
void Print();
//获取值节点的个数
size_t Amount();
//获取广义表的深度
size_t Depth();
//拷贝构造
Generalized(const Generalized& g);
////赋值运算符的重载
Generalized& operator=(const Generalized& g);
////析构函数
~Generalized(); protected:
void _Print(GeneralizedNode* head);
GeneralizedNode* _CreatList(const char*& str);
size_t _Amount(GeneralizedNode* head);
GeneralizedNode* _Copy(GeneralizedNode* head);
void _Destory(GeneralizedNode* head);
protected:
GeneralizedNode* _head; //记录广义表头指针
};

 

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

    GeneralizedNode* _CreatList(const char*& str)
{
assert(*str == '(');
GeneralizedNode* head = new GeneralizedNode(HEAD,'0');
GeneralizedNode* cur = head;
str++;
while (str != '\0')
{
if ((*str >= '0'&&*str <= '9') || (*str >= 'a'&&*str <= 'z') || (*str >= 'A'&&*str <= 'Z'))
{
cur->_next = new GeneralizedNode(VALUE, *str);
cur = cur->_next;
}
else if (*str == '(')
{
cur->_next = new GeneralizedNode(SUB);
cur = cur->_next;
cur->_subLink = _CreatList(str);
}
else if (*str == ')')
{
return head;
}
str++;
}
return head;
}

 

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

    void _Print(GeneralizedNode* head)
{
if (head == NULL)
{
cout << "Generalized table is NULL" << endl;
return;
}
GeneralizedNode* cur = head;
while (cur)
{
if (cur->_type == HEAD)
{
cout << '(';
}
else if (cur->_type == VALUE)
{
cout << cur->_value;
if (cur->_next)
{
cout << ',';
}
}
else if (cur->_type == SUB)
{
_Print(cur->_subLink);
if (cur->_next)
{
cout << ',';
}
}
cur = cur->_next;
}
cout << ')';
}

  

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

    size_t _Amount(GeneralizedNode* head)
{
GeneralizedNode* begin = head;
size_t count = 0;
while (begin)
{
if (begin->_type == VALUE)
{
count++;
}
if (begin->_type == SUB)
{
count += _Amount(begin->_subLink);
}
begin = begin->_next;
}
return count;
}

  

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

    size_t _Depth(GeneralizedNode* head)
{
if (_head == NULL)
{
return 0;
}
size_t dp=0;
GeneralizedNode* cur = head;
size_t max = 0;
while (cur)
{
if (cur->_type == SUB)
{
dp=_Depth(cur->_subLink);
if (max < dp)
{
max = dp;
}
}
cur = cur->_next;
}
return max+1;
}

 

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

    void _Destory(GeneralizedNode* head)
{
if (head == NULL)
{
return;
}
while (head)
{
GeneralizedNode* begin = head->_next;
if (head->_type == SUB)
{
_Destory(head->_subLink);
}
delete head;
head = begin;
}
}

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

 

广义表(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. OSX: 命令行制作U盘Recovery HD

    使用命令行操作,非常easy,可是操作不当非常危急! 免责声明:假设操作不当造成的数据丢失,本人概不负责. 为什么? 不是有OSX恢复磁盘助理嘛?是的.假设仅仅想使用GUI的软件.能够去苹果官方站点: ...

  2. 【已解决】iView-admin Editor 组件 绑定默认值问题

    iView-admin Editor 组件 绑定默认值问题 发现 editor 组件,设置v-model 后, 修改 v-model 数据, editor组件没有自动渲染,需要手动设置渲染  this ...

  3. C# SqlBulkCopy类批量导入数据

    特别注意  sqlbulkcopy.ColumnMappings.Add(dt.Columns[i].ColumnName, dt.Columns[i].ColumnName); 插入的时候列的顺序可 ...

  4. 挑战--asp.net 文件夹上传

    今天遇到一个有趣的问题,公司让平安做一个上传文件夹的功能,这个任务具有一定的挑战性哦.上传文件夹,我第一次看到有人这样做,以前都是上传压缩文件,从来就没有见人上传过文件夹,我也从来就没有尝试过.先不讨 ...

  5. centos6下手工编译vitess

    vitess是youtub开源的一款mysql代理,在ubuntu下编译非常方便.可是在centos下且不能訪问google的情况下坑比較多.近期依据其bootstrap.sh脚本手工编译成功.把过程 ...

  6. Android Studio SDK Manager 解决无法更新问题

    一.首先要保证你可以FQ上google等网站. 这个..如何越过GFW就要靠自己了..网上也有很多教程.. 二.更改android sdk manager的option设置 选择Tools→Opini ...

  7. JSP HTTP 状态码

    JSP HTTP 状态码 HTTP请求与HTTP响应的格式相近,都有着如下结构: 以状态行+CRLF(回车换行)开始 零行或多行头模块+CRLF 一个空行,比如CRLF 可选的消息体比如文件,查询数据 ...

  8. postman 测试API - 获取/调用 token

    1.使用全局变量保存token 2.再调用 参考文章 http://www.jianshu.com/p/13c8017bb5c8 https://testerhome.com/topics/6555

  9. 阿里云服务器---centos编译安装ffmpeg

    环境 系统环境:CentOS release 6.7 (Final) 需求 编译安装ffmpeg 获取依赖 安装依赖包 yum install -y autoconf automake cmake f ...

  10. Office Web Apps Server 2013与PDF(二)

    在上一篇文章(Office Web Apps Server 2013与PDF(一))中,曾经介绍了Office Web Apps Server 2013在更新后,可以直接对PDF文档进行在线的查看.不 ...