数据结构与算法七:2.1 树的存储结构之双亲表示法

523 阅读4分钟

这是我参与8月更文挑战的第31天,活动详情查看:8月更文挑战

关注我,以下内容持续更新

数据结构与算法(一):时间复杂度和空间复杂度

数据结构与算法(二):桟

数据结构与算法(三):队列

数据结构与算法(四):单链表

数据结构与算法(五):双向链表

数据结构与算法(六):哈希表

数据结构与算法(七):树

数据结构与算法(八):排序算法

数据结构与算法(九):经典算法面试题

数据结构与算法(十):递归

数据结构与算法(十一):图

1. 双亲表示法

1. 普通的树结构

图的存储的结构有双亲表示法、孩子(链表)表示法、双亲孩子表示法、孩子兄弟表示法。本篇主要介绍双亲表示法,如上图所示,把这种普通的树结构用双亲表示法来存储。

双亲表示法的基本思想:树的双亲表示法实质是一种静态链表。用一维数组来存储树的各个结点(一般按层序存储),数组中的一个元素对应树中的一个结点,包括结点的数据信息以及该结点的双亲在数组中的下标。

因为根节点没有父节点(父节点又称为双亲节点),因此根节点记录父节点位置的变量通常置为-1。 采用双亲表示法存储图1中的普通树,其存储状态如图2所示:

2. 双亲表示法

每个结点Node由data和parent构成,如图所示

  • data:存储树中结点的数据信息
  • parent:存储该结点的双亲在数组中的下标
#define tree_size 100  //宏定义树中结点的最大数量
#define TElemType int  //宏定义树结构中数据类型

//结点
typedef struct PTNode{
  TElemType data;  //树中结点的数据类型
  int parent;     //结点的父结点在数组中的位置下标
}PTNode;

//树
typedef struct {
  PTNode nodes[tree_size];  //存放树中所有结点
  int r, n;  //根的位置下标和结点数
}PTree;

这种结构来查找双亲结点非常容易,直接找到这个结点的parent域就是双亲结点;但是查询某个结点的孩子结点需要遍历所有的结点,有点复杂,所以可以把双亲表示法进行改造。

2. 改造后的双亲表示法

改造后,增加了firstChild域和rightSib域来提高查找孩子结点的性能。改造后的每个结点Node由data、parent、firstChild和rightSib构成,其存储状态如图3所示:

3. 完善后的双亲表示法
  • data:存储树中结点的数据信息
  • parent:存储该结点的双亲在数组中的下标
  • firstChild:存储该结点的第一个孩子结点在数组中的下标
  • rightSib:存储该结点的兄弟结点在数组中的下标

如图,查找B的孩子结点的过程如下:

  • 1.查找B结点的firstChild域,值为3。也就是B的第一个孩子结点在数组中的下标为3,也就是D结点;
  • 2.查找D结点的rightSib域,值为4。也就是B的第二个孩子结点在数组中的下标为4,也就是E结点;
  • 3.查找E结点的rightSib域,值为5。也就是B的第三个孩子结点在数组中的下标为5,也就是F结点;
  • 4.查找F结点的rightSib域,值为-1。-1代表F结点没有兄弟结点,所以B结点的孩子结点至此查找完毕;
  • 5.至此找到了B结点的所有孩子结点:D、E、F。

再例如查找结点I的孩子结点:因为I结点的firstChild域值为-1,所以它没有孩子结点。

查找D的孩子结点的过程如下:

  • 1.查找D结点的rightSib域,值为4。也就是D的第一个兄弟结点在数组中的下标为4,也就是E结点;
  • 2.查找E结点的rightSib域,值为5。也就是D的第二个兄弟结点在数组中的下标为5,也就是F结点;
  • 3.查找F结点的rightSib域,值为-1。-1代表F结点没有兄弟结点,所以D结点的兄弟结点至此查找完毕;
  • 4.一共找到了D的所有兄弟结点:E、F。

关注我

如果觉得我写的不错,请点个赞 关注我, 您的支持是我更文最大的动力!