数据结构(C语言)-广义表

广义表

  • 一、广义表的定义和运算
    • 1、广义表的定义
    • 2、广义表的性质
  • 二、广义表的存储
    • 1、头尾表示法
    • 2、孩子兄弟表示法

广义表是线性表的推广,也称为列表(Lists)。线性表中的元素仅限于单个数据元素(原子),即不可以再分割;而广义表中的元素即可以是原子,也可以是子表。

一、广义表的定义和运算

1、广义表的定义

广义表是n(n>=0)个数据元素a1,a2,a3…an的有序序列,一般记做:
LS=(a1,a2,a3…an)
其中LS是广义表的名称,n是广义表的长度。每个a3(1<=3<=n)是LS非空时,称第一个元素a1为LS的表头(head),称其余元素组成的表(a2,…,ai…,an)为LS的表尾(tail)。显然,广义表的定义是递归的。
广义表通常用圆括号起来,并用逗号分隔开来,通常用大写字母表示广义表,用小写字母表示单个数据元素。下面是广义表的例子:
A=()——A是一个空表,它的长度为零
B=(e)——列表B只有一个原子e,它的长度是1
C=(a,(b,c,d))——列表C的长度为2,两个元素分别为a和子表(b,c,d)
D=(A,B,C)——列表D的长度为3,三个元素都是列表,将A,B,C带入后得D=((),(e),(a,(b,c,d))
E=(a,E)——这是一个递归表,它的长度为2,正相当于一个无限的列表。
广义表的长度指该广义表中所包含的元素(原子和子表)的个数。广义表的深度指该广义表所包含扩号的层数

2、广义表的性质

(1)广义表是一种多层次的数据结构,其中的元素可以是单元素,也可以是子表
(2)广义表可以是递归的表,即广义表也可以是其自身的子表。
(3)广义表可以为其他表所共享。
广义表结构相当灵活,可以兼容线性表、数组、树和有向图等各种常用的数据结构。

二、广义表的存储

广义表中的数据元素可以是具有不同的结构,因此难以用顺序的存储结构来表示,而链式存储结构分配灵活,易于解决广义表的共享与递归问题,所以通常都采用链式的存储结构存储广义表。
广义表的元素可以是数据元素,也可以是表,因此结点的结构也需要两种:一种表结点,用以表示表;另一种是原子结点,用以表示原子。按结点形式的不同,广义表的链式存储结构又可以分为不同的两种存储方式。

1、头尾表示法

由于广义表中的数据元素即可能是表示也可能是单元素,相应地在头尾表示法中结点的结构形式有两种:一种是表结点,用以表示法;另一种是元素结点,用以表示原子。表结点由三个域:标志域(tag=1)、表头指针域(hp)、表尾指针域(tp)组成;而原子结点由两个域;标志域(tag=0)和值域(data)组成。广义表的存储结点可定义:

typedef enum{ATOM,LIST}ElemTag;
typedef struct GLNode{
      ElemTag tag;
      union
      {
         DataType atom;
         Struct
         {
         struct GLNod *hp, *tp;
          }ptr;
      } 
}*GList;

在这种存储结构中有几种情况:
(1)除空表的表头指针为空外,对任何非空列表,其表头指针均指向一个表结点,且该结点中的hp域指示列表表头(或为原子结点,或为表结点),tp域指向列表表尾(除非表尾为空,则指针为空,否则必为表结点)
(2)容易分请列表中原子和子表所在层次,如在列表D中,原子a和e在同一层次上,而b、c和d在同一层次且比a和e低一层,B和C是同一层的子表。
(3)最高层的表结点个数即为列表的长度。

2、孩子兄弟表示法

广义表的另一种表示法称为孩子兄弟表示法。在孩子兄弟表示法中,也有两种结点形式:一种是有孩子结点,用以表示子表;另一种是无孩子结点,用以表示原子。在有孩子结点中包括一个指向第一个孩子的指针和一个指向兄弟的指针;而在无孩子结点中包括一个指向兄弟的指针和该原子的元素值,为了能区分这两类结点,在结点中设置一个标志域。如果标志为1,表示该结点为有孩子结点;如果标志为0,则表示结点为无孩子结点

typedef enum {ATOM ,LIST}ElemTag;
typedef struct GLNode{
     ElemTag tag;
     union{
         DataType atom;
         struct GLNode *hp;
         
     };
     struct GLNode *tp;
}*GList;

你可能感兴趣的:(学习分享,列表,指针,数据结构,链表,程序设计)