一,广义表的基本概念:

广义表(Lists,又称列表)是一种非线性的数据结构,是线性表的一种推广。即广义表中放松对表元素的原子限制,容许它们具有其自身结构(即可以有子表)。它被广泛的应用于人工智能等领域的表处理语言LISP语言中。在LISP语言中,广义表是一种最基本的数据结构,就连LISP 语言的程序也表示为一系列的广义表。(更好的阅读体验,请移步我的个人博客)

二,广义表的基本表示:

1,  概念角度分析:

广义表是n个元素a1,a2,a3…. an组成的有限序列,通常记为:LS = (a1,a2,a3…. an);

其中,LS代表表名,ai 代表表中元素即为表元素,其既可以为单个原子元素又可以是一个广义表,当ai为为广义表是成为LS的一个子表(此处体现出来了递归思想)。

★特别提醒:

a,  n为表的长度,当n = 0时,LS为空表;n >0时,表的第一个表元素称为广义表的表头(head),除此之外,其它表元素组成的表称为广义表的表尾(tail)。即当a1为表 头元素时,(a2,a3 ……an)为表尾元素。

b,   因为元素可以为子表,所以就体现出来层次结构(关于分层,请看下图)。

2,举例说明:

A=( );    //A是一个空表

B=(e);   //表B有一个原子

C=(a, (b,c,d) );  //两个元素为原子a和子表(b,c,d)

D=(A,B,C);  //有三个元素均为列表

E=(a,E);  //递归的列表,包含两个元素,一个是单元素a,另一个是子表,但该子表是其自身.所以,E相当于一个无限的广义表( a,(a,(a,…))).

3,几个常见术语:

a,表的深度:表展开后所含括号的层数;

b,表的长度:长度为第一层的元素个数(原子和子表都只算一个);

c,表头、表尾。

4,图形化理解表:

5,表头表尾的求法:

以C表为例:GetHead(C) = a;  GetTail(c) = ( (b,c,d) );

算法实现(存储结构采用头尾链表存储表示,详见下图):

 PGNode GetHead(PGNode p){if( !p || p->tag==0 ){printf("表头子表元素不存在\n");return NULL;}return p->ptr.sublist ;}PGNode GetTail(PGNode p){if( !p || p->tag==0 ){printf("空表或者为单个原子元素\n");return NULL;}return p->ptr.next ;}

三、广义表的存储结构:

由于表元素的特殊性,通常采用链式存储,而不采用顺序存储,由于可能会有两种表元素,所以需要采用两种结构的节点,分别为原子节点和表结点。

按照其节点结构的不同,可以设计两种不同的存储结构:

a,广义表的头尾链表存储表示:

typedef int NodeType; //节点类型,1为表结点,0为原子节点;

typedef char ElemType;//元素类型是字符型

//广义表的存储结构

struct GNode{

NodeType  NodeTag;      //标志域

union{           //值域或子表的表头指针域

ElemType data;

struct { GNode *sublist,*next }ptr;

};  //ptr表节点的指针域,sublist , next表头表尾指针;

}*PGNode;

b, 广义表的扩展线性链表表示:

typedef int NodeType; //节点类型,1为表结点,0为原子节点;

typedefchar ElemType;//元素类型是字符型

//广义表的存储结构

struct GNode

{

NodeType NodeTag;      //标志域

union{           //值域或子表的表头指针域

ElemType data;

struct GNode *sublist;

};

struct GNode *next;  //指向后继结点的指针域

}*PGNode;

四、广义表基本操作(创建,遍历,求深度,查找某一元素)的代码实现:

由于广义表的形成缘由有递归的思想(子表),所以, 广义表的操作可采用递归与非递归算法实现;在其存储结构上,可采用上述两种的任何一种。

下面将采用两种算法来实现广义表的基本操作:

1,  递归算法,存储结构采用扩展线性链表

节点定义:

 typedef int NodeType;
typedef char ElemType;//元素类型是字符型
typedef struct GNode
{NodeType NodeTag;      //标志域union{           //值域或子表的表头指针域ElemType data;struct GNode *sublist;};struct GNode *next;  //指向后继结点的指针域
}*PGNode;

建立广义表:

CreateGList(PGNode *GL)
{char ch;scanf("%c", &ch);//读入一个字符,此处只可能读入空格#、左括号或英文字母if(ch=='#')//若输入为空格,则置表头指针为空{*GL = NULL;
}else if(ch=='(')//若输入为左括号则建立由*GL所指向的子表结点并递归构造子表{*GL = (PGNode GL)malloc(sizeof(struct GNode));(*GL)->NodeTag = 1;CreateGList(&((*GL)->sublist));}else{       //若输入为字符则建立由*GL所指向的单元素结点*GL =  (PGNode GL) malloc(sizeof(struct GNode));(*GL)->NodeTag = 0;(*GL)->data = ch;}scanf("%c", &ch);//此处读入的字符必为逗号、右括号或分号if(*GL==NULL);       //若*GL为空,则什么都不做
{
return ;
}else if(ch==',')//若输入逗号则递归构造后继表{
CreateGList(&((*GL)->next));
}else if((ch==')') || (ch==';'))//若输入为右括号或分号则置*GL的后继指针域为空{
(*GL)->next = NULL;
}
}

求广义表的深度

int DepthGList(PGNode GL)
{int max=0;//给max赋初值//遍历表中每一个结点,求出所有子表的最大深度while(GL!=NULL){if(GL->NodeTag==1){int dep = DepthGList(GL->sublist);//递归调用求出一个子表的深度if(dep > max)max = dep;//让max始终为同一层所求过的子表中深度的最大值}GL = GL->next;//使GL指向同一层的下一个结点}return(max + 1);//返回表的深度
}

求广义表的长度

int LengthGList(PGNode GL)
{if(GL!=NULL)return(1 + LengthGList(GL->next));elsereturn(0);
}

打印输出广义表

void PrintGList(PGNode GL)
{//对于表结点的处理情况if(GL->NodeTag==1){    //存在子表,则输出左括号,作为开始符号printf("(");if(GL->sublist==NULL)//若子表为空则输出'#'字符{
printf("#");}else//若子表非空,则递归输出子表{PrintGList(GL->sublist);
}
printf(")");//当一个子表输出结束后,应输出一个右括号终止符}else//对于单元素结点,则输出该结点的值{printf("%c", GL->data);}
if(GL->next!=NULL)//输出结点的后继表{printf(",");//先输出逗号分隔符PrintGList(GL->next);//再递归输出后继表}
}

构建总体代码如下:

#include<stdio.h>
#include<stdlib.h>typedef int NodeType;
typedef char  ElemType;
typedef struct GNode
{NodeType NodeTag; union{          ElemType data;struct GNode *sublist;};struct GNode *next;
}*PGNode;
void CreateGList(PGNode *GL)
{
char ch ;
scanf("%c",&ch);
if( ch== '#')
{
*GL = NULL;
}
else if( ch=='(' )
{
*GL = (PGNode) malloc ( sizeof(struct GNode) );
(*GL)->NodeTag = 1;
CreateGList( &(*GL)->sublist );
}
else
{
*GL = (PGNode) malloc ( sizeof(struct GNode) );
(*GL)->NodeTag = 0;
(*GL)->data = ch ;
}
scanf("%c",&ch);
if(*GL== NULL)
{
return ;
}
else if( ch==',' )
{
CreateGList( &(*GL)->next );
}
else if( (ch==')') || (ch==';') )
{
(*GL) ->next = NULL;
}
}void PrintGList(PGNode GL)
{
if( GL->NodeTag == 1 )
{
printf( "(" );if( GL->sublist==NULL )
{
printf( "#" );
}
else
{
PrintGList( GL->sublist );
printf( ")" );
}
}
else
{
printf("%c",GL->data);
}
if( GL->next != NULL )
{
printf( ",");
PrintGList(GL->next );
}
}int Depth( PGNode GL )
{
int max = 0;
while(GL != NULL )
{
if(GL->NodeTag == 1){
int dep = Depth( GL->sublist );
if( dep>max )
{
max = dep;
}
}
GL = GL->next ;
}
return (max+1);
}int LengthGList( PGNode GL )
{
if( GL !=NULL )
{
return (1+LengthGList(GL->next) );
}
else
{
return 0;
}
}int main()
{
PGNode GL;
int depth,length;
printf("******采用递归方法进行广义表的基本操作******\n");
printf("请输入一个广义表,以分号结束 :  ");
CreateGList(&GL);printf("\n此方法输出的输出广义表->  :");PrintGList(GL);printf("\n\n");
depth =  Depth( GL->sublist );
printf("广义表的深度depth为-> %d \n",depth);
length = LengthGList( GL->sublist );
printf("广义表的长度width为-> %d \n",length);
return 0;
}

程序截图:

五、学习心得:

广义表作为对线性表的一种推广,秉承了线性表的基本思想,也采取了和线性表相似的存储结构,但是,要比线性表复杂好多,从CRUD操作就可以看出来,我的掌握也不是很透彻,只会一些基本的CRUD操作,以后用到,还得要继续深入理解,欢迎交流。

数据结构之广义表的相关知识点相关推荐

  1. C语言——数据结构之广义表(概念及其存储结构)

    前言 本节我们来说说C语言中的广义表.主要介绍广义表的概念定义,并说明其存储结构,算法中将使用到递归思想. 广义表是线性表的一种推广,在数据结构中有广泛应用. 一.广义表的概念 1.广义表的概念 (1 ...

  2. 数据结构之广义表(C语言)

    文章目录 1.广义表的定义 2.广义表的存储结构 3.代码结构描述 5.广义表的各类操作 6.代码测试 7.完整代码 作者建议:为了方便读者能够更加理解代码实现,建议各位读者在看代码的时候可以参考广义 ...

  3. 【数据结构】广义表的存储结构及基本运算(C语言)

    目录 1. 广义表基本概念 2. 广义表的存储结构 2.1 头尾链表存储结构 2.2 同层结点链存储结构 3. 广义表的基本运算 3.1 求表头.表尾 3.2 求长度.深度 3.3 统计原子数目 3. ...

  4. 【数据结构】广义表的介绍

    参考资料:<数据结构(C语言版)严蔚敏著> 版权说明:未经作者允许,禁止转载.如引用本文内容,需标明作者及出处.如本文侵犯了您的权益,请联系我删除并致歉. 文章说明:如文章中出现错误,请联 ...

  5. c++数据结构之广义表

    最近学习了广义表,我们知道广义表也是一种线性表,而顾名思义广义表就是不止一个表,下面来举个栗子: A=( ) B=(1 , 2,3) C=(1 ,2 ,3, ( a , b ,c) ) D=(1, 2 ...

  6. java 广义表_数据结构:广义表的实现(Java)

    Java实现广义表: package 广义表; import java.util.Stack; public class Test { public final int TAG_TABLE = 1; ...

  7. 【数据结构】广义表的默认成员函数、深度、大小、打印

    广义表的定义: 广义表是非线性的结构,是n个元素的有限序列. 举例:A=(a,b,(c,d)) 我们先定义它的结构: (1)它有三种节点,头节点.值节点.子表节点. (2)两种指向下一节点的指针:指向 ...

  8. 【数据结构】广义表的基本概念

    广义表的基本概念 广义表不是考试的重点,只要理解基本概念就行了. 书上介绍的广义表,我觉得简单来理解的话就是狭义的列表,因为书上规定了列表的表头可以是原子或者子表,但是表尾必须是子表,在python中 ...

  9. 数据结构之串、数组和广义表的相关实现(C语言)

    参考:1.网课:数据结构与算法基础(青岛大学-王卓) 2.教材:数据结构(c语言版)第二版,严蔚敏,李冬梅等著 非科班自学,如有错误望不吝赐教. 串 串可以理解成数据对象为字符集的线性表 定长顺序串包 ...

最新文章

  1. 【126】TensorFlow 使用皮尔逊相关系数找出和标签相关性最大的特征值
  2. 国家计算机病毒中心发现“网游大盗”新变种
  3. Cocos2d-x移植WP8时间CCScrollView问题
  4. ExtAspNet应用技巧(三) - 302与Asp.Net Ajax
  5. Qt CMake变量参考
  6. 使用popwindow制作弹出框与获得焦点弹出软键盘
  7. 【AngularJS】—— 2 初识AngularJs(续)
  8. ptyhon【递归练习】
  9. php datediff 函数,dateAdd与DateDiff函数的js代码
  10. UVA 10608-Friends
  11. 【opencv学习】【形态学】【腐蚀与膨胀】【开运算与闭运算】【礼帽和黑帽】
  12. mysql datapump_mysqlpump参数详解
  13. Android在片段之间传递数据
  14. 干净虚拟机(centos 6.4)上从头到尾安装并调试Mdrill(二)
  15. 基于MATLAB的PID控制器设计
  16. 边缘计算网关平台发展现状综述
  17. HTML5 codecademy
  18. word2vec教程
  19. 什么是人工智能技术?
  20. MPB:中科院城环所杨军组-​​基于DNA宏条形码的水体微型真核生物群落测序建库方法...

热门文章

  1. 第三天 LINUX安全
  2. 修改系统时间,TFS会无法登陆
  3. k阶原点距和k阶中心距各是说明什么数字特征
  4. Tpos时间定位表达式
  5. 李航《统计学习方法》第三章课后答案链接
  6. ubuntu装机并设置远程连接
  7. 【Docker】练习-在容器中部署静态网站
  8. eclipse上的maven,添加依赖后无法自动下载相应的jar包
  9. ELK6.0日志从收集到处理完整版教程(二)
  10. 在vSphere Client使用模板部署虚拟机 系统硬盘空间扩展