第五章——树和森林

1.树的存储结构

1.1双亲表示法

这种方式采用一组连续空间来存储每个结点,同时在每个结点中增设一个伪指针,指示其双亲结点在数组中的位置。根节点下表为0,其伪指针域为-1.

每个结点除了数据域data外,还附设一个parent域用以指示其双亲结点的位置



优点和缺点:
找双亲容易,找孩子难。

双亲表示法存储结构描述:

typedef struc PTNode{//树的结点定义
	TElemType data;//数据元素
	int parent;//双亲位置域
}
#define MAX_TREE_SIZE 100  
typedef struct{   //树的类型定义
	PTNode nodes[MAX_TREE_SIZE]; //双亲表示
	int r,n;    //结点数
}PTree;

1.2孩子表示法

每个结点的孩子结点排列起来,看成是一个线性表,且以单链表做存储结构,则n个结点有n个孩子链表(叶子的孩子链表为空表)。而n个头指针又组成一个线性表,为了便于查找,可采用顺序存储结构。

优点和缺点:
找孩子容易,找双亲难

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

以二叉链表作为树的存储结构,链表中结点的两个链域分别指向该结点的第一个孩子结点和下一个兄弟结点,分别命名为firstchild域和nextsibling域。


该存储法比较灵活
最大的优点:可以方便的实现树转化为二叉树的操作,易于查找结点的孩子;
缺点:从当前节点查找双亲比较麻烦,但如果为每个结点增设一个parent域指向其父结点,则查找结点的父结点也比较方便。

typedef struct CSNode{
	ElemType data;//数据域
	struct CSNode *firstchild,*nextsibling;//第一个孩子和右兄弟指针
}CSNode,*CSTree;

2.树、森林与二叉树的转换

2.1树转化为二叉树

【基本思想】
由于树和二叉树都可以用二叉链表作为存储结构,则已二叉链表作为媒介可以导出树。
给定一棵树,可以找到唯一的一个二叉树与其对应。
【转化步骤】
① 加线:在兄弟之间加一连线;
② 抹线:对每个结点,除了在孩子外,去除其与其余孩子之间的关系;
③ 旋转:以树的根结点为轴心,将整树顺时针转45°;
树变二叉树: 兄弟相连留长子
在这里插入图片描述

2.2二叉树转化为树

【转化步骤】
①加线:若p结点是双亲结点的左孩子,则将p的右孩子,右孩子的右孩子…沿分支找到的所有右孩子,都与p的双亲用线连起来
②抹线:抹掉原二叉树中双亲与右孩子之间的连线
③调整:将结点按层次排列,形成树结构
树变二叉树:左孩右右连双亲,去掉原来右孩线
在这里插入图片描述

2.3森林转化为二叉树(二叉树与多棵树之间的关系)

①将各棵树分别转换成二叉树
②将每棵树的根结点用线相连
③以第一棵树根结点为二叉树的根,再以根结点为轴心,顺时针旋转,构成二叉树型结构
森林变二叉树:树变二叉根相连

在这里插入图片描述

2.4二叉树转化为森林

①抹线:将二叉树中根结点与其右孩子连线,及沿右分支搜索到的所有右孩子间连线全部抹掉,使之变成孤立的二叉树
②还原:将孤立的二叉树还原成树
二叉树变森林:去掉全部右孩线,孤立二叉再还原。
在这里插入图片描述

3.树与森林的遍历

3.1树的遍历(三种方式)

3.1.1先根遍历

若树不空,则先访问根节点,然后依次先根遍历各个子树。

3.1.2后根遍历

若树不空,则先依次后根遍历各子树,然后访问根节点。

3.1.1层次遍历

若树不空,则自上而下,自左至右访问树中的每个结点。

3.2森林的遍历(三种方式)

将森林看作由三部分构成:
1、森林中第一棵树的根结点;
2.森林中第一棵树的子树森林;
3.森林中其它树构成的森林。

3.2.1先序遍历

若森林不空,则
1.访问森林中第一棵树的根结点;
2.先序遍历森林中第一棵树的子树森林;
3.先序遍历森林中(除第一棵树之外)其余树构成的森林。

3.1.1中序遍历

若森林不空,则
1.中序遍历森林中第一棵树的子树森林;
2.访问森林中第一棵树的根结点;
3.中序遍历森林中(除第一棵树之外)其余树构成的森林。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值