树和森林

树的存储结构

一 双亲表示法

使用一维数组,每个元素有两个域,数据域和父结点索引域

数据结构定义:

#define	size	10
typedef	struct
{
  char data;
  int	parent;
} Node;
Node slist[size];

图示:

image-20200610094753525

特点:

找父结点容易,找结点 的孩子麻烦,需遍历整张表。

二 孩子链表表示法

使用一维数组存储树中所有节点,每个元素有两个域数据域和第一个孩子节点的指针域

孩子节点也有两个域分别是自身对应的索引域以及下一个孩子节点的指针域

数据结构定义:

# define MAXND 20
typedef struct bnode
{int child;
    struct bnode *next;
}node,*childlink;
typedef struct
{ 
  char data;  
  childlink hp;
}headnode;
headnode link[MAXND];

图示:

image-20200610100421170

特点:

查找子节点方便,查找父结点困难

双亲孩子表示法

为了接查找父结点困难的问题,可以在数组元素中增加一个域存储父结点的索引

数据结构定义:

# define MAXND 20
typedef struct bnode
{
    int child;
    struct bnode *next;
}node,*childlink;
typedef struct{
    char data;
    int parent; childlink hp;
}headnode;
headnode link[MAXND];

图示:

image-20200610101225384

三 孩子兄弟表示法(二叉链表表示法)

使用链表存储树中的节点,链表中每个元素有三个域分别为第一个孩子指针域,数据域,下一个兄弟指针域

节点组成:

image-20200610104808018

数据结构定义:

Typedef struct tnode
{
int data;
struct tnode *son,*brother;
}*Tree;

图示:

image-20200610104528702

特点:

  • 数据结构定义与二叉树的二叉链表表示法安全相同,但是指针所表示的含义是不同的

  • 查找父结点需遍历链表

树/森林与二叉树之间的转换

一般树转换二叉树

转换方法:

  1. 个兄弟节点之间添加连线
  2. 对任一节点,除最左孩子之外,抹掉该节点与其他子节点的各枝(取消连线)
  3. 以根节点为中心,将连线顺时针转45度

图示:

image-20200610160118557

一棵树的孩子兄弟链表示法与将该树转为二叉树后的二叉链表表示法存储结构完全相同,仅节点中指针含义不同

设有以下树(左),并将其转换为二叉树(右):

image-20200610160545060

使用孩子兄弟表示法存储以上树得到存储结构如图(左)

使用二叉链表表示法存储转换后的二叉树得到结构如图(右)

image-20200610161225219

森林转换二叉树

转换方法:

  1. 将每棵树转换为对应的二叉树
  2. 将第一步得到的各二叉树的根节点看作是兄弟节点,加连线,以最左侧根节点作为中心将根节点连线顺时针旋转45度

图示:

image-20200610163705219

二叉树还原为一般树

明确:根节点没有右孩子的二叉树可转为一般树

还原方法:

  1. 从根节点起
  2. 当前节点的左孩子和左孩子右枝上的所有节点作为当前节点的孩子节点
  3. 重复第一步

也是树转二叉树的逆运算即以根节点为中心所有节点逆时针旋转45度

图示:

image-20200610195745932

二叉树还原为森林

明确:根节点有右孩子的二叉树可转为森林

还原方法:

  1. 根节点右枝上的每一个节点作为一个的根节点
  2. 将拆开后的二叉树按二叉树还原为一般树的方法转换为一般树

也是森林转二叉树的逆运算

图示:

image-20200610202905880

树的遍历

先序遍历:先访问根节点,然后依次先序遍历根的每个子树

后序遍历:先依次遍历每棵子树,最后访问根节点

层次遍历:从上到下从左到右依次遍历所有节点

由于子节点个数不确定所以没有无法实现中序遍历

示例:

image-20200610203816192

上图对应的遍历顺序

先序:ABCDE

后序:BDCEA

层次:ABCED

树的遍历结果与转为二叉树后的遍历结果对应关系

树 => 二叉树

先序 == 先序

后序 == 中序

森林的遍历

先序遍历:依次使用先序遍历森林中每棵树

中序遍历:对每棵树按照先子后根的方式遍历每个节点

之所以叫中序: 因为 树的后序==树转二叉树的中序

示例:

image-20200610211307262

上图对应的遍历顺序

先序:ABCDEFGHJI

中序:BCDAFEJHIG

原文地址:https://www.cnblogs.com/yangyuanhu/p/13089669.html