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

前言

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

一、广义表的概念

1.广义表的概念

(1)广义表:也称列表,是n(n>=0)个元素的有限序列
记作:LS=(a1,a2,…,an)ai(1<=i<=n)是数据元素或广义表
其中:
LS:广义表名
n:LS的长度

通常,大写字母表示广义表的名称,小写字母表示数据元素

(2)原子:当广义表LS的元素是一个数据元素时,称为原子
(3)广义表的子表:当广义表LS的元素不是一个数据元素时,称为广义表的子表
(4)LS的表头(head):广义表非空时,第一个元素a1称为LS的表头
(5)LS的表尾(tail):其余部分(a2,…,an)称为表尾

举例:
(1)A=(): A是一个空表,长度n=0
(2)B=(e),Head(B)=e ,Tail(B)=():表尾为空的广义表,长度为1
(3)C=(a,(b,c)) ,Head©=a为原子 ,Tail©=((b,c))为广义表,表尾长度为1
(4)D=((a,b),c) ,Head(D)=(a,b)为广义表 ,Tail(D)=©
(5)E=((a,b),c,(d,e)), Head(E)=(a,b)为E的子表 ,Tail(E)=(c,(d,e)) ,Head(Tail(E))=c , Tail(Tail(E))=((d,e))

结论1:广义表允许共享子表
结论2:广义表也允许d递归的定义
例:G=(a,G) 这里G是一个长度为2的广义表,第一个元素是原子a,第二个元素是广义表G自己

2.广义表的图型表示

在这里插入图片描述

二、广义表的存储结构

1.广义表的存储结构

(1)由于广义表中的元素既可以是原子,也可以是广义表,所以会有原子结点和链表结点
(2)每个元素元素所需的空间大小无法统一,所以很难用顺序存储结构表示,通常采用链式结构表示

原子结点:tag=0 atom(元素),只有2个域,标志域和值域
列表结点: tag=1 hp(表头) tp(表尾),有3个域,标志域、表头指针域与表尾指针域

注:这种链式存储结构中,为了统一管理这2类结点,采用了共同体(联合)来定义广义表的结点类型。
//相关定义 
typedef struct GLNode
{
    
    
	ElemTag tag;//标志域,用以区分原子结点和表结点
	union 
	{
    
    
		AtomType atom;//原子结点 
		struct 
		{
    
    
			struct GLNode *hp,*tp;
		}ptr;//表结点 
	} 
}*GList; 

2.广义表的基本操作(递归算法)

(1)求广义表的长度 :int GLisitLength(Glist L)
递归定义:
若L==NULL,长度0
若L!=NULL,长度:1 + GLisitLength(L->ptr.tp)

//求广义表的长度
int GLisitLength (Glist L)
{
    
    
	if (!L)
		return 0;
	return 1+GLisitLength(L->ptr.tp);
}

(2)求广义表的深度:int GLisitDepth(Glist L)
广义表:LS=(a1,a2,…,an)
递归定义:

若L= =NULL,深度1
若L!=NULL,深度:1 + Max(ai)
L->tag==0,原子结点:深度0

//求广义表的深度 
int GLisitDepth (Glist L)
{
    
    
	if (!L)
		return 1;
	if (L->tag==0)
		return 0;
	for (max=0,p=L;p;p=p->ptr.tp)
	{
    
    
		dep = GLisitDepth(p->ptr.hp);
		if (dep>max)
			max = dep;
	}
	return max+1;
}

总结

以上简要介绍了一下广义表。广义表还有很多其他的基本操作,在此不一 一赘述。感兴趣的话可以再去看看其他的代码实现。
下一篇将开始介绍非线性结构——树。篇幅较长,将分为上下两篇。
ps:代码非原创。
如有错误,欢迎指正。

猜你喜欢

转载自blog.csdn.net/qq_51308373/article/details/115351066