美文网首页
数据结构-树的定义和存储

数据结构-树的定义和存储

作者: lionsom_lin | 来源:发表于2019-01-11 18:02 被阅读15次

一、基本概念

树的定义

树(Tree)是 n(n >= 0)个结点的有限集。

  • n = 0 时,称为空树;
  • n > 0 时,为非空树,在非空树中:
    • (1) 有且只有一个特定的称为根(Root)的结点;
    • (2) n > 1 时,其余结点可分为 m(m>0)个互不相交的有限集,其中每一个集合本身又是一棵树,并且称为根的子树(SubTree);

注意:
1、n > 0 时根结点是唯一的,不可能存在多个根结点。
2、m > 0 时,子树的个数没有限制,但它们一定是互不相交的。

两个结构就不符合树的定义,因为它们都有相交的子树。

相关术语

  • 结点的度:结点拥有子树数,称为结点的度;
  • 叶结点:度为0的结点,称为叶结点(Leaf)或终端结点;
  • 分支结点:度不为0的结点,称为分支结点;
  • 树的度:树内部各结点的度的最大值;
  • 结点的子树的根称为该结点的孩子,结点称为孩子的双亲;
  • 结点为根的子树中所有结点都是该结点的子孙,该结点称为子孙的祖先;
  • 同一个双亲的孩子之间称为兄弟;
  • 双亲在同一层的结点称为堂兄弟;
结点关系
  • 结点的层次从根开始,根结点为第1层,根结点的孩子为第2层,依次类推。
  • 树中结点的最大层次称为树的深度或高度
结点的层次
  • 若将树中每个结点的各子树看成是从左到右有次序的(即不能互换),则称该树为有序树(Ordered Tree);
    否则称为无序树(UnorderedTree)。
    注意:若不特别指明,一般讨论的树都是有序树。
举例
  • 森林(Forest)是 m(m>=0)颗不相交的树的集合。
森林

二、树的存储结构

对于存储结构,可能会联想到前面的 顺序存储链式存储结构。但是对于树这种可能会有很多孩子的特殊数据结构,只用顺序存储结构或者链式存储结构很难实现,
不过充分利用顺序存储和链式存储结构的特点,完全可以实现对树的存储结构的表示。产生主要的三种存储结构表示法:双亲表示法、孩子表示法、孩子兄弟表示法。

2.1、双亲表示法

我们假设 以一组连续空间存储树的结点,同时在每个结点中,附设一个指示器指示其双亲结点到链表中的位置。
也就是数组中存放一个结构体,结构体大致如下:

struct
/* 树的双亲表法结点结构定义*/
#define MAX_TREE_SIZE 100
typedef int  ElemeType;

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

typedef struct { // 树结构
    PTNode nodes[MAX_TREE_SIZE];   // 结点数组
    int r; // 根的位置
    int n; // 结点数
}PTree;
双亲表示法

双亲表示法的特点

  • 由于根结点是没有双亲的,约定根结点的位置位置域为-1.
  • 根据结点的parent指针很容易找到它的双亲结点。所用时间复杂度为O(1),直到parent为-1时,表示找到了树结点的根。
  • 缺点:如果要找到孩子结点,需要遍历整个结构才行。

对结构体拓展,对其进行改进

可如果我们要知道结点的孩子是什么,对不起,请遍历整个结构才行。
这真是麻烦,能不能改进一下呢?
当然可以。我们增加一个结点最左边孩子的域,不妨叫它长子域,这样就可以很容易得到结点的孩子。如果没有孩子的结点,这个长子域就设置为-1,如下图:

对struct进行拓展

2.2、双亲表示法

初始

树的度是3,所以我们的指针域的个数是3,这种方法实现如图

多重链表表示法

这种方法对于树中各结点的度相差很大时,显然是很浪费空间的,因为有很多的结点,它的指针域都是空的。不过如果树的各结点度相差很小时,那就意味着开辟的空间被充分利用了,这时存储结构的缺点反而变成了优点。

改进

改进方案每个结点指针域的个数等于该结点的度,我们专门取一个位置来存储结点指针域的个数,如下图:

改进,节省空间

这种方法克服了浪费空间的缺点,对空间利用率是很高了,但是由于各个结点的链表是不相同的结构,加上要维护结点的度的数值,在运算上就会带来时间上的损耗。

再次改进

我们为了要遍历整棵树,把每个结点放到一个顺序存储结构的数组中是合理的,但每个结点的孩子有多少是不确定的,所以我们再对每个结点的孩子建立一个单链表体现它们的关系 。

结构体 再次改进

这样的结构对于我们要查找某个结点的某个孩子,或者找某个结点的兄弟,只需要查找这个结点的孩子单链表即可。对于遍历整棵树也是很方便的,对头结点的数组循环即可。
但是,这也存在着问题,我如何知道某个结点的双亲是谁呢?比较麻烦,需要整棵树遍历才行,难道就不可以把双亲表示法和孩子表示法综合一下吗?当然是可以。

最终 - 双亲孩子表示法
双亲孩子表示法

2.3、孩子兄弟表示法 - 将复杂树变为二叉树

结构体 image.png

其实这个表示法的最大好处是它把一棵复杂的树变成了一棵二叉树。我们把上图变形就成了下图这个样子:

image.png

最后,如果真的有必要,完全可以再增加一个parent指针域来解决快速查找双亲的问题。

相关文档参考

引用《大话数据结构》作者:程杰
数据结构(十三)——树
树的三种存储结构
【数据结构】树的定义和树的三种存储结构

相关文章

  • 数据结构-树的定义和存储

    一、基本概念 树的定义 树(Tree)是 n(n >= 0)个结点的有限集。n = 0 时,称为空树;n > 0 ...

  • 二叉树的创建和删除子节点

    树的定义 树是计算机科学中经常用到的一种数据结构。树是一种非线性的数据结构,以分层的方式 存储数据。树被用来存储具...

  • HashMap类简介

    1 基本定义 数据结构 数据结构数组链表红黑树用途存储键值对。数组下标为键的哈希值解决哈希冲突解决哈希冲突 定义参...

  • 数据结构之二叉树

    为什么要定义树这种数据结构? 线性表 和 链表 常见的两种数据结构。但是各有所长。线性表顺序存储,通过下标随机访问...

  • 【数据结构】二叉树及其各种遍历

    关于树的定义和存储结构可以查看上一篇文章树的定义和树的三种存储结构 一、二叉树的定义 二叉树的定义 二叉树(Bin...

  • 这是一篇算法研习指导:数据结构的存储方式,基本操作和遍历方式

    数据结构的存储方式 数据结构的存储方式只有两种:数组: 顺序存储链表: 链式存储散列表, 栈, 队列, 堆, 树,...

  • MySQL中的索引(二)InnoDB中的索引

    相关的数据结构 在InnoDB存储引擎中,建立索引所使用的数据结构是B+树。这里我们看看和B+树相关的数据结构。 ...

  • 01-基本概念

    定义 数据结构: 数据之前的关系 算法定义: 解决问题的程序 数据结构分类 物理结构: 数据在存储设备上的存储方式...

  • 数据结构

    一.数据结构的基本概念 数据结构定义:数据结构是一种存储和组织数据的方式,以便于访问和修改。数据结构包括数据的逻辑...

  • 树(Tree)

    本文主要是对数据结构中非线性结构 树 的学习和总结。 树的定义 专业定义: 通俗的定义: 专业术语: 树的分类 一...

网友评论

      本文标题:数据结构-树的定义和存储

      本文链接:https://www.haomeiwen.com/subject/xmuorqtx.html