树的存储:双亲数组法,孩子链表法,孩子兄弟法

 在实际应用中,人们采用多种形式的存储结构来表示树,既有顺序存储结构,又有链式存储结构,但无论采用哪种存储结构,都要求存储结构不但能存储结点本身的信息,还能存储树中各结点之间的逻辑关系。下面介绍几种常用的树的存储方式。
       1、双亲表示法
       从树的定义可知,除根结点外,树中的每个结点都有唯一的一个双亲结点。根据这一特性,可用一组连续的存储空间(一维数组)存储树中的各结点。树中的结点除保存结点本身的信息之外,还要保存其双亲结点在数组中的位置(数组的序号),树的这种表示法称为双亲表示法。
下图1

所示的树的双亲表示法如图1所示。图中 pPos 域的值为-1 表示该结点是根结点,无双亲结点。

struct node

{

char data;

int   pPos;

};

 

struct   head

{

struct node m [10];

int n;

int pPos;

};

 

 


图2树的双亲表示法


       树的双亲表示法对于实现 Parent(t)操作和 Root()操作非常方便。 Parent(t)操作可以在常量时间内实现,反复调用Parent(t)操作, 直到遇到无双亲的结点(其 pPos值为-1)时,便找到了树的根,这就是Root()操作的执行过程。但要实现查找孩子结点和兄弟结点等操作非常困难,因为这需要查询整个数组。要实现这些操作,需要在结点结构中增设存放第1个孩子在数组中的序号的域和存放第1个兄弟在数组中的序号的域。


       2、孩子链表表示法
       孩子链表表示法也是用一维数组来存储树中各结点的信息。但结点的结构与双亲表示法中结点的结构不同,孩子链表表示法中的结点除保存本身的信息外,不是保存其双亲结点在数组中的序号,而是保存一个链表的第一个结点的地址信息。这个链表是由该结点的所有孩子结点组成。每个孩子结点保存有两个信息,一个是每个孩子结点在一维数组中的

序号,另一个是下一个孩子结点的地址信息。 孩子结点的结构如下所示:



       孩子结点类 的定义如下(与前面一样,只列出了成员字段):
struct node  

{

int pPos;

struct node *next;

};
       树的孩子链表表示法的结点的结构如下所示:
       树的孩子链表表示法的结点类 的定义如下:
struct    elem

{

char data;

struct node *firstchild;

};


       树类的定义如下:
struct head

{

struct elem m[10];

int pPos;

int   n;

} ;
图1所示的树的孩子链表表示法如图3所示。



图3树的的孩子链表表示法
       树的孩子链表表示法对于实现查找孩子结点等操作非常方便,但对于实现查找双亲结点、兄弟结点等操作则比较困难。
       3、孩子兄弟表示法
       这是一种常用的数据结构,又称二叉树表示法,或二叉链表表示法,即以二叉链表作为树的存储结构。每个结点除存储本身的信息外,还有两个引用域分别存储该结点第一个孩子的地址信息和下一个兄弟的地址信息。树类 CSTree只有一个成员字段head,表示头引用。 树的孩子兄弟表示法的结点的结构如下所示: 树的孩子兄弟表示法的结点类 CSNode的定义如下(与前面一样,只列出了成员字段):
struct node

{

char data;

struct node *child;

struct node *sibling;

};
图1所示的树的孩子兄弟表示法如图4所示。



图 4 树的孩子兄弟表示法
      

树的孩子兄弟表示法对于实现查找孩子、兄弟等操作非常方便,但对于实现查找双亲结点等操作则非常困难。如果在树的结点中再增加一个域来存储孩子的双亲结点的地址信息,则就可以较方便地实现上述操作了。

你可能感兴趣的:(树的存储:双亲数组法,孩子链表法,孩子兄弟法)