数据结构 - 树和森林表示与遍历

双亲表示法(顺序存储结构)

      用一组连续的存储空间来存储树的结点,同时在每个结点中附加一个指示器(整数域) ,用以指示双亲结点的位置(下标值) 。数组元素及数组的类型定义如下:
#define MAX_SIZE  100
typedef  struct PTNode
{  ElemType  data ;
int  parent ;
}PTNode ;
typedef  struct
{  PTNode  Nodes[MAX_SIZE] ;
int  root;    /*  根结点位置  */
int  num ;   /*  结点数   */
}Ptree ;

所示是一棵树及其双亲表示的存储结构。这种存储结构利用了任一结点的父结点唯一的性质。可以方便地直接找到任一结点的父结点,但求结点的子结点时需要扫描整个数组。

孩子链表表示法

2 孩子链表表示法

树中每个结点有多个指针域,每个指针指向其一棵子树的根结点。有两种结点结构。

⑴ 定长结点结构

指针域的数目就是树的度。

其特点是:链表结构简单,但当树中各结点的度相差很大时,指针域的浪费明显。但如果树的各结点的度相差很小时,那开辟的空间被充分利用了,这种存储结构的缺点就变成了优点。

结点结构

⑵ 不定长结点结构(按需分配)

树中每个结点的指针域数量不同,是该结点的度。没有多余的指针域,但操作不便。

优点:空间利用率提高了

缺点:各个结点的链表结构不相同,实现起来比较困难;

其次要维护结点的度的值,运算上会带来时间的 损耗。

⑶ 复合链表结构

(顺序存储+链式存储)

具体办法是:把所有结点放到一个顺序存储的数组中,然后将每个结点的孩子结点排列起来,用单链表作存储结构(因为每个结点的孩子数不确定) 。

    n个结点的树有n个(孩子)单链表(叶子结点的孩子链表为空);
   n个头结点又组成一个线性表,采用顺序存储结构,存放进一个一维数组中。

设计两种结点结构:

表头数组的表头结点: (firstchild存储该结点的孩子链表的头指针);

孩子链表的表结点:(childno用来存储某个结点在表头数组中的下标,next指向下一个孩子)。

数据结构类型定义

数据结构类型定义如下:

#define  MAX_NODE  100
typedef  struct  listnode
{   int   childno ;    /*  孩子结点编号  */
struct listno  *next ;
}CTNode;    /*  表结点结构  */
typedef  struct
{  ElemType   data ;
CTNode  *firstchild ;
}HNode;    /*  头结点结构  */
typedef  struct
{  HNode   nodes[MAX_NODE] ;
int  root;    /*  根结点位置  */
int  num ;   /*  结点数   */
}CLinkList;    /*  头结点结构  */
复合链表结构点评:
优点:便于查找结点的孩子或结点的兄弟
缺点:查找某结点的双亲需遍历整棵树

孩子兄弟表示法(二叉树表示法)

3 孩子兄弟表示法(二叉树表示法)

  树有以下特点:任意一棵树,它的结点的第一个孩子如果存在就是唯一的,它的兄弟如果存在也是唯一的。因此,设置两个指针,分别指向该结点的第一个孩子和它的右兄弟结点。结点类型定义如下:
typedef  struct   CSnode
{  ElemType   data ;
struct   CSnode *firstchild, *nextsib ;
}CSNode;

孩子兄弟表示法点评:

便于查找某个结点的孩子

通过firstchild找到该结点的长子,然后通过长子结点的nextsib找到次子……直到找到要找的孩子。

难以找到双亲

解决办法:增加一个双亲parent指针域

森林与二叉树的转换

     由于二叉树和树都可用二叉链表作为存储结构,对比各自的结点结构可以看出,以二叉链表作为媒介可以导出树和二叉树之间的一个对应关系。

◆ 从物理结构来看,树和二叉树的二叉链表是相同的,只是对指针的逻辑解释不同而已。

◆ 从树的二叉链表表示的定义可知,任何一棵和树对应的二叉树,其右子树一定为空。

树转换成二叉树

对于一般的树,可以方便地转换成一棵唯一的二叉树与之对应。其详细步骤是:

⑴ 加虚线。在树的每层按从“左至右”的顺序在兄弟结点之间加虚线相连。

⑵ 去连线。除最左的第一个子结点外,父结点与所有其它子结点的连线都去掉。

⑶ 旋转。将树顺时针旋转450,原有的实线左斜。

⑷ 整型。将旋转后树中的所有虚线改为实线,并向右斜

3 森林转换成二叉树

当一般的树转换成二叉树后,二叉树的右子树必为空。若把森林中的第二棵树(转换成二叉树后)的根结点作为第一棵树(二叉树)的根结点的兄弟结点,则可导出森林转换成二叉树的转换步骤如下:

1、把每棵树转换为二叉树

2、按给出的森林中树的次序,第一棵树不动,从第二棵树开始,依次把后一棵树的根结点作为前一棵二叉树的根结点的右孩子,用线连起来,当所有的二叉树连接起来后,就得到了由森林转换来的二叉树。

树和森林的遍历

1 树的遍历

由树结构的定义可知,树的遍历有二种方法。

⑴ 先序遍历:先访问根结点,然后依次先序遍历完每棵子树。如图的树,先序遍历的次序是:

ABCDEFGIJHK

⑵ 后序遍历:先依次后序遍历完每棵子树,然后访问根结点。如图的树,后序遍历的次序是:

CDBFGIJHEKA

说明:

◆ 树的先序遍历实质上与将树转换成二叉树后对二叉树的先序遍历相同。

◆ 树的后序遍历实质上与将树转换成二叉树后对二叉树的中序遍历相同。

2 森林的遍历

设F={T1, T2,?,Tn}是森林,对F的遍历有二种方法。

⑴ 先序遍历:按先序遍历树的方式依次遍历F中的每棵树。

⑵ 中序遍历:按中序遍历树的方式依次遍历F中的每棵树。

时间: 2024-10-10 23:46:38

数据结构 - 树和森林表示与遍历的相关文章

javascript实现数据结构: 树和森林

树的3种常用链表结构 1 双亲表示法(顺序存储结构) 优点:parent(tree, x)操作可以在常量时间内实现 缺点:求结点的孩子时需要遍历整个结构 用一组连续的存储空间来存储树的结点,同时在每个结点中附加一个指示器(整数域) ,用以指示双亲结点的位置(下标值) . 图所示是一棵树及其双亲表示的存储结构.这种存储结构利用了任一结点的父结点唯一的性质.可以方便地直接找到任一结点的父结点,但求结点的子结点时需要扫描整个数组. 代码实现: 1 // 1.双亲表示法 2 // 优点:parent(t

javascript实现数据结构: 树和二叉树,二叉树的遍历和基本操作

树型结构是一类非常重要的非线性结构.直观地,树型结构是以分支关系定义的层次结构. 树在计算机领域中也有着广泛的应用,例如在编译程序中,用树来表示源程序的语法结构:在数据库系统中,可用树来组织信息:在分析算法的行为时,可用树来描述其执行过程等等. 下面讲解的内容完整代码在这:https://github.com/LukeLin/data-structure-with-js/blob/master/Binary%20tree/BinaryTree.js 首先看看树的一些概念: 1.树(Tree)是n

数据结构---树、二叉树、森林

1.基本术语: 度:有两种度"结点的度"与"树的度".结点的度指的是一个结点子树的个数:树的度是指树中结点度的最大值. 叶子结点:指的是没有子树的结点. 层:树是有层次的,一般根结点为第0层.规定根结点到某结点的路径长度为该结点的层数. 深度:树中结点的最大层数 兄弟:同一双亲的结点,互为兄弟 堂兄弟:双亲在同一层次的结点,互为堂兄弟 祖先:从根结点到该结点的路径上的所有结点都是该结点的祖先. 子孙:以某一结点为根的子树上的所有结点都是该结点的子孙 森林:n棵互不相

作业 树和森林 遍历(递归/非递归先序,递归/非递归后序,递归层次)

1 #include <iostream> 2 #include"queue.h"//之前写的类 3 #include"stack.h" //之前写的类 4 using namespace std; 5 6 template <class T> 7 class Tree; 8 9 //======================================== 10 // 树节点类声明 11 template <class T>

数据结构:树的BFS,树的层次遍历! 按先序遍历创建一棵树,然后以层次遍历输出。

按先序遍历创建一棵树,以层次遍历输出 样例输入 A B # D # # C E # # F # # 样例输出 LevelOrder: A B C D E F 代码: #include <iostream> #include <queue> using namespace std; struct node { //表示一个树上的节点 char ch; node *left, *right; }; node* creat() { //以递归的方式构造一棵二叉树 node *root =

树与森林的存储、遍历和树与森林的转换

树的存储结构 双亲表示法 孩子表示法: (a)多重链表(链表中每个指针指向一棵子树的根结点); (b)把每个跟结点的孩子结点排列起来,看成一个线性表,且以单链表做存储结构.且N个头指针也组成一个线性表. 孩子兄弟表示法://二叉树表示法或二叉链表表示法 以二叉链表做树的存储结构,链表中结点的两个链域分别指向该结点的第一个孩子结点和下一个兄弟结点(fchild 和nsibling) //孩子兄弟表示法 typedef struct CSNode{ int data; CSNode *fchild

数据结构——第三章树和二叉树:03树和森林

1.树的三种存储结构: (1)双亲表示法: #define MAX_TREE_SIZE 100 结点结构: typedef struct PTNode { Elem data; int parent; //双亲位置域 } PTNode; (2)孩子双亲链表表示法: typedef struct PTNode { Elem data; int parent; //双亲位置域 struct CTNode* nextchild; } *ChildPtr; (3)树的二叉链表(孩子-兄弟)存储表示法:

浅谈数据结构-树

树是一种数据结构,其中一个元素可以有两个或者多个数据元素,具有一对多的特点,用树结构来存储文件. 树的概念 结点的度:子结点的个数.例如结点1中有3个子结点,结点1的度是3. 树的度:树的度等于所有结点度中度最高的值.结点最高的度为3,树的度为3. 叶子结点:度为0的结点,即没有子结点的结点.例如:上图中3,5,6,7,9,10. 分支结点:除了叶子结点以外的结点,即度不为0的结点.例如:上面树的分支结点为1,2,4,8. 内部结点:除了根结点以及叶子结点或在分支结点的基础之上在去掉根结点.例如

41 蛤蟆的数据结构笔记之四十一图的遍历之深度优先

41  蛤蟆的数据结构笔记之四十一图的遍历之深度优先 本篇名言:"对于我来说 , 生命的意义在于设身处地替人着想 , 忧他人之忧 , 乐他人之乐. -- 爱因斯坦" 上篇我们实现了图的邻接多重表表示图,以及深度遍历和广度遍历的代码,这次我们先来看下图的深度遍历. 欢迎转载,转载请标明出处: 1.  原理 图遍历又称图的遍历,属于数据结构中的内容.指的是从图中的任一顶点出发,对图中的所有顶点访问一次且只访问一次.图的遍历操作和树的遍历操作功能相似.图的遍历是图的一种基本操作,图的许多其它