37-树的存储结构

  树的存储结构大致分为三种:双亲存储结构,孩子链存储结构,孩子兄弟链存储结构,接下来,我们主要讲围绕这几种存储结构来详解介绍。

1. 双亲存储结构

  双亲存储结构采用了一种顺序存储结构,也就是用一组连续空间(数组)存储树的所有节点。同时在每个节点中增加一个伪指针指示其双亲节点的位置。

这里写图片描述
图1-双亲存储结构

  比如:对于A节点来说,它是整棵树结构中的根节点,因此A节点的双亲节点的位置就是-1了,即跟节点A不存在双亲节点。

  对于B,C,D节点来说,它们的双亲节点是A节点,而A节点的下标为0,因此我们可以把B,C,D节点的双亲节点位置设置为0。同理,E,F,G节点的双亲节点是C节点,而C节点的下标为2,那么E,F,G节点的双亲节点位置设置为2。


  现在我们根据这样的树的存储结构,用计算机程序设计语言来定义树的存储结构,如下所示:

#define MAXSIZE 100

typedef struct
{

    ElemType data;  //存储当前节点数据,ElemType指向具体的数据类型
    int parent;   //记录双亲节点位置

} PTree [MAXSIZE];

2. 孩子链存储结构

  孩子链存储结构是存储每个节点的值,并且把每一个节点的所有孩子的链接都存储下来。

  有同学可能会问,要是每个节点的孩子节点个数不一样,那么我们应该怎么去设计每个节点的所有孩子链接数呢?如果孩子链接个数少了,会导致在存储孩子链接时不够用,如果过多又会造成存储空间的浪费,因此我们必须解决这个问题。

  对于设计每个节点的所有孩子链接个数的问题,通常采用的解决办法是:当我们在设计每个节点的所有孩子的链接个数时,应该按照树的度(即树中所有节点度的最大值)设计节点的孩子节点指针域个数。

这里写图片描述
图2-孩子链存储结构

  在图2中最左边的树结构中的度最大是3,那么在设计树的存储结构时,每个节点的孩子链接的个数就是3了。对于这样的存储结构来说,如果每个节点的孩子节点不足3个的话,那么存储空间就不能充分利用,这将会造成一些浪费。

  比如对于A节点来说,虽然A节点有三个空间可以存储孩子链接,但是A节点只有两个孩子节点,因此只用son1和son2保存这两个孩子节点的链接,剩下的son3将会浪费。而B节点则恰好有3个孩子节点,因此B节点用son1,son2,son3保存这些孩子节点的链接,可以充分利用存储空间。



  当确定好了这种存储结构时,我们就可以使用程序设计语言定义存储结构,如下所示:

//MAXSONS表示最多的孩子节点个数
#define MAXSONS 3

typedef struct node
{
    ElemType data;              //存储当前节点的数据
    struct node *sons[MAXSONS];     //存储当前节点的孩子节点的链接个数
} TSonNode;

3. 孩子兄弟链存储结构

孩子兄弟链存储结构是为每个节点设计三个域:
  1.当前节点的数据域
  2.当前节点的第一个孩子节点指针域
  3.当前节点的下一个兄弟节点指针域

这里写图片描述
图3-孩子兄弟链存储结构

  孩子兄弟链存储结构如上图所示,每一个节点都有三个域用于存储当前节点,第一个孩子节点,兄弟节点,而vp域表示指向第一个孩子节点,hp域表示指向兄弟节点,data域表示当前节点。

  对于根节点A来说,A节点有B和C两个孩子节点,但是A的第一个孩子节点是B,因此在A节点中的vp就会指向B节点,由于A节点没有兄弟节点,因此A节点中的hp就会指向NULL 。

  对于B节点来说,B节点有三个孩子节点(D,E,F)和一个兄弟C节点,那么B节点的hp域会指向C节点,由于D节点是B节点的第一个孩子节点,那么B节点中的vp域会指向D节点。其他节点同理,并以此类推……



  当我们非常确定孩子兄弟链存储结构的时候,就可以用C语言定义存储结构,如下所示:

typedef struct tnode
{

    ElemType data;    //存储当前节点的数据
    struct tnode *hp;     //指向兄弟节点
    struct tnode *vp;     //指向第一个孩子节点

} TSBNode;

猜你喜欢

转载自blog.csdn.net/qq_35733751/article/details/80876175