树结构:由N个结点组成的有限集,在各个结点间具备树状的逻辑结构关系;

               当N=0时,该树是空树;

               当N>0时,该树是非空树,而树中有且只有一个根节点,其余结点组成M个有限集亦是树结构,称为根的子树;

树结构名词解释: (参考如下的示例树状逻辑结构图)

根结点:树状逻辑结构中唯一的,没有双亲结点的结点;

内部结点:树状逻辑结构中具有双亲结点也包含子结点的结点;

叶结点或终端节点:树状逻辑结构中具有双亲结点但是不具有子结点或子树的结点;

树的度:树状结构中拥有子结点或子树的最大值;

树的深度:从根节点开始,往下一个子结点为一层,依次到底,树能伸展的最大深度;

 

java 树状结构存储 java树的存储结构_结点

树存储结构:数据结构是由多个数据元素以及元素之间的逻辑结构组成,而逻辑结构是根据计算机处理数据的便利性,可行性以及时间复杂度等因素,设计得来,因而数据结构的存储结构的设计需要体现该数据结构的逻辑结构并满足实际的计算机存储要求,高级语言中有些封装好的树状结构,例如Java中的HashMap是基于红黑树实现的,这里不做赘述;

树存储结构主要方式有三种:双亲表示法,孩子表示法,兄弟表示法;

实际在高级语言中封装数据类型可能会有自己不同的实现方式,这里只是了解这几种方式的思想;

双亲表示法:  因为对于树中的单个结点来说,除了根节点外,都有唯一的双亲结点,所以可以将单个结点设计为包含双亲结点的下标地址(基于数组实现方式),如下图所示,该方式可以很方便的得出双亲结点位置,但是无法直接获取子结点,需要遍历整个数组获取,增加了时间复杂度;

                                   

java 树状结构存储 java树的存储结构_数组_02

Java 实现单个结点存储的代码:

/** * 双亲表示法的结点结构 * * */ class ParentsTreeEntry { Object data; int parentsIndex; }

 

 孩子表示法:和双亲表示法的思路相反,除了叶子结点以外,所有的结点都会有一个或者多个子结点,因为结点的个数不唯一,所以不能够直接采用双亲表示的实现方式,在每一个结点中保存所有子结点的信息,因为在实现结点Entry的时候,如果子结点不唯一,则必须按照树的度进行初始化该结点,会造成不必要的空间浪费以及结构不统一。故综合考虑结点结构以及空间节约,采用数组和链表结合的方式进行,数组中依旧保存树状结构中的所有结点,使用链表保存结点的孩子引用,从而产生两种结构,一种是表头的结点结构,由数据和孩子结点引用组成,另一种是孩子结点结构,由孩子结点及孩子的兄弟结点组成;该方式可以很方便的得出子结点位置,但是无法直接获取双亲结点,需要遍历整个数组获取,也可以在结点中添加双亲结点的引用,这边不做赘述;

java 树状结构存储 java树的存储结构_数组_03

Java 实现单个结点存储的代码:

/** * 孩子表示法的表头结点结构 * * */ class ChildTreeTableHeadEntry { Object data; int firstChildINdex; int parentsIndex; //这边可以添加双亲结点索引 } /** * 孩子表示法的孩子结点结构 * * */ class ChildTreeChildEntry { Object data; int nextChildINdex; int parentsIndex; //这边可以添加双亲结点索引 }

 

兄弟表示法: 转换另一种思路,通过孩子结点和兄弟结点是否能够唯一确定一个结点的位置和结点间的关系,答案是可以的,每一个结点的第一个孩子结点存在亦唯一,而该结点的第一个右兄弟结点存在亦唯一,以此类推,这种实现方式的好处是可以直接获取到结点的第一个孩子和兄弟结点的信息,但是对于双亲及所有孩子结点的获取存在弊端;

                                   

java 树状结构存储 java树的存储结构_java 树状结构存储_04

Java 实现单个结点存储的代码:

/** * 孩子兄弟表示法的结点结构 * * */ class ChildBrotherTreeEntry { Object data; int nextChildINdex; int pbrotherIndex; }

上述实现是都是基于数组,为了能够以下标的形式加深理解,也可以使用链表进行实现,另外本博客只为理解这种逻辑结构的思想,暂时不对算法进行深究;