【数据结构】树-树的存储(图解、树、森林与二叉树的转换)
URLeisure的树的存储“完美”复习资料。
文章目录
GitHub同步更新(已分类):Data_Structure_And_Algorithm-Review
公众号:URLeisure 的复习仓库
公众号二维码见文末
以下是本篇文章正文内容,下面案例可供参考。
树的存储结构
-
树形结构是一对多的关系,除了树根之外,每一个节点有唯一的直接前驱(双亲),除了叶子之外,每一个节点有一个或多个直接后继(孩子)。
-
采用顺序存储和链式存储两种形式存储。
-
分别用两种方式存储下图树。
顺序存储
-
顺序存储采用一段连续的存储空间,因为树中节点的数据关系是一对多的逻辑关系,不仅要存储数据元素,还要存储他们之间的逻辑关系。
-
顺序存储分为: 双亲表示法、孩子表示法和双亲孩子表示法。
1.双亲表示法
- 除了存储数据元素之外,还存储其双亲节点的存储位置下标,其中 “-1” 表示不存在。每一个节点有两个域,即数据域 date 和双亲域 parent。
如图。
2.孩子表示法
- 除了存储数据元素之外,还存储其所有孩子的存储位置下标。
如图。
3.双亲孩子表示法
- 双亲孩子表示法是指除了存储数据元素之外,还存储其双亲和所有孩子的存储位置下标。
如图。
-
此方法其实就是在孩子表示法的基础上增加了一个双亲域。
-
是双亲表示法和孩子表示法的结合体。
三种表示法的优缺点
- 双亲表示法:只记录了每个节点的双亲,无法直接得到该节点的孩子。
- 孩子表示法:可以得到该节点的孩子,但是无法直接得到该节点的双亲,而且由于不知道每个节点到底有多少个孩子,因此只能按照树的度(树中节点的最大度)分配孩子空间,这样做可能会浪费很多空间。
- 双亲孩子表示法:在孩子表示法的基础上,增加了一个双亲域,可以快速得到节点的双亲和孩子,其缺点和孩子表示法一样,可能浪费很多空间。
链式存储
-
由于树中每个节点的孩子数量无法确定,因此在使用链式存储时,孩子指针域不确定分配多少个合适。
-
如果采用“异构型”数据结构,每个节点的指针域个数按照节点的孩子数分配,则数据结构描述困难;
-
如果采用每个节点都分配固定个数(如树的度)的指针域,则浪费很多空间。
可以考虑两种方法存储:
- 采用邻接表的思路,将节点的所有孩子存储在一个单链表中,称为孩子链表表示法。
- 采用二叉链表的思路,左指针存储第一个孩子,右指针存储右兄弟,称为孩子兄弟表示法。
1.孩子链表表示法
-
孩子链表表示法类似于邻接表,表头含数据元素并指向第一个孩子指针,将所有孩子放入一个单链表中。
-
在表头中,data 存储数据元素,first 为指向第 1 个孩子的指针。单链表中的节点记录该节点的下标和下一个节点的地址。
如图。
- 孩子链表表示法中,如果在表头中再增加一个双亲域 parent,则为双亲孩子链表表示法。
2.孩子兄弟表示法
-
节点除了存储数据元素之外,还有两个指针域 lchild 和 rchild ,被称为二叉链表。
-
lchild 存储“长子”地址,rchild 存储右兄弟地址。
- 孩子兄弟表示法秘诀:长子在左,兄弟向右。
存储方式如图。
树、森林与二叉树的转换
-
根据树的孩子兄弟表示法,任何一棵树都可以根据秘诀转换成二叉链表来存储。
-
二叉链表存储法中,每个节点都有两个指针域,也成为二叉树表示法。这样,任何树和森林都可以转换为二叉树,其存储方式简单多了。
-
这样就完美地解决了树中孩子数量无法确定,难以分配空间的问题。
-
树转换为二叉树的秘诀:长子当作左孩子,兄弟关系向右斜。
树和二叉树的转换
- 还原时,找准右兄弟。
森林和二叉树的转换
-
森林是由 m(0)棵不相交的树组成的集合。
-
可以把森林中的每棵树的树根看作兄弟关系。
- 还原时,把第一个节点的兄弟砍掉。
总结
-
由于普通的树每个节点的子树个数不同,存储和运算都比较困难,因此在实际应用中,可以将树或森林转换为二叉树,然后进行存储和运算。
-
二者存在唯一的对应关系,因此不影响其结果。
关注公众号,感受不同的阅读体验
下期预告:二叉树的性质

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐
所有评论(0)