您当前的位置: 首页 >  数据结构
  • 2浏览

    0关注

    880博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

【大话数据结构C语言】24 树的存储结构

CodeAllen嵌入式编程 发布时间:2020-12-09 23:37:03 ,浏览量:2

我的首发平台是公众号【CodeAllen】,学习交流QQ群:736386324

利用顺序存储和链式存储结构的特点,可以实现对树的存储结构的便是

下边主要介绍三种不同的表示法:

双亲表示法:

我们假设一组连续的空间存储树的结点,同时在每个结点中,附设一个指示器指示双亲结点到链表中的位置 在这里插入图片描述

其中date是数据域,存储结点的数据信息,而parent是指针域,存储该结点的双亲在数组中的下标 用代码表示为:

 /* 树的双亲表示法结点结构定义 */
#define MAX_TREE_SIZE 100

typedef int TElemType;              /* 树结点的数据类型,目前暂定为整型 */

typedef struct PTNode               /* 结点结构 */
{
    TElemType data;                 /* 结点数据 */
    int parent;                     /* 双亲位置 */
} PTNode;

typedef struct                      /* 树结构 */
{
    PTNode nodes[MAX_TREE_SIZE];    /* 结点数组 */
    int r,n;                        /* 根的位置和结点数 */
} PTree;

这样的结构定义,就可以实现双亲表示法了,因为根结点是没有双亲,约定根结点的位置域为-1, 在这里插入图片描述

上图树结构中的树双亲表示为 在这里插入图片描述

这样的存储结构,可以根据结点的parent指针很容易找到他的双亲结点,所以时间复杂度为O(1) 直到parent为-1时,表示找到了树结点的根

引出一个问题,上述结构要想知道结点的孩子是什么,需要遍历整个结构 可以增加一个结点最左边孩子的域,可以叫其长子域,如果没有孩子的结点,这个长子域就设置为-1 在这里插入图片描述

存储结构的设计是非常灵活的过程,一个存储结构设计的是否合理,取决于基于该结构的运算是否适合,是否方便,时间复杂度好不好等

孩子表示法:

由于树中每个结点可能有多棵子树,可以考虑用多重链表,即每个结点有多个指针域,其中每个指针指向一棵子树的根结点,这种方法可以叫做多重链表表示法

这种树的每个孩子个数是不同的,所以可以设计两种方案解决

方案一:指针域的个数就是等于树的度 在这里插入图片描述

其中data是数据域,child1到childd是指针域,用来指向该结点的孩子结点

对于下边的树,树的度就是3 在这里插入图片描述

这种方法实现如下图: 在这里插入图片描述

这种方案显然有点浪费空间,既然很多指针域可能为空,为什么不按需分配呢?

于是有了方案二:每个结点指针域的个数等于该结点的度,专门取一个位置存储结点指针域的个数 在这里插入图片描述

其中data为数据域,degree为度域,存储的是该结点的孩子结点的个数,child1到childd是指针域,用来指向该结点的孩子结点

其实现方法是: 在这里插入图片描述

这种方法克服了浪费空间的问题,不过其各个结点的链表是不同的结构,加上要维护结点的度的数值,在运算上会带来时间损耗

所以想一想,有没有更好的方法?

这就引出开始说的孩子表示法 在这里插入图片描述

/* 树的孩子表示法结构定义 */
#define MAX_TREE_SIZE 100

typedef int TElemType;          /* 树结点的数据类型,目前暂定为整型 */

typedef struct CTNode           /* 孩子结点 */
{
    int child;  
    struct CTNode *next;    
} *ChildPtr;

typedef struct                  /* 表头结构 */
{
    TElemType data; 
    ChildPtr firstchild;    
} CTBox;

typedef struct                  /* 树结构 */
{
    CTBox nodes[MAX_TREE_SIZE]; /* 结点数组 */
    int r,n;                    /* 根的位置和结点数 */
} CTree;

但是这也有个问题,想知道某个结点的双亲是谁,还需要遍历才行

那就把上述的双亲表示法和孩子表示法结合一下是不是可行!

当然是可以的,这种方法就叫做

双亲孩子表示法

在这里插入图片描述

上边的三种都是从双亲的角度和从孩子的角度研究树的结构,但是也可以从兄弟的角度分析

孩子兄弟表示法

在这里插入图片描述

其中data是数据域,firstchild是指针域,存储该结点的第一个孩子结点的地址,rightsib是指针域,存储该结点的右兄弟结点的存储地址

其定义代码可以表示为:

/* 树的孩子兄弟表示法结构定义 */
typedef struct CSNode
{
    TElemType data; 
    struct CSNode *firstchild,*rightsib;    
} CSNode,*CSTree;

其实现示意图可以表示为: 在这里插入图片描述

这种表示法,给查找某个结点的某个孩子带来了方便,只要firstchild找到此结点的长子,然后再通过长子结点的rightsib找到他的二弟,一直接下去,知道找到具体的孩子

那找结点的双亲呢?和上边类似,只要增加一个parent指针域就好了

这些都在后边的二叉树特性中体现的淋漓尽致

关注
打赏
1665938897
查看更多评论
立即登录/注册

微信扫码登录

0.0395s