5.6 树和森林

发布时间 2023-07-31 11:53:54作者: 杭冷卉

5.6 树和森林


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

  • 若n=0,称为空树;

  • 若n>0,

    • 有且仅有一个特定的称为根(Root)的结点;
    • 其余结点可分为m(m>=0)个互不相交的有限集T1,T2,T3,...,Tm,

森林:是m(m>=0)颗互不相交的树的集合

5.6.1 树的存储结构

双亲表示法

实现:定义结构数组,存放树的结点,每个结点含两个域:

  • 数据域:存放结点本身信息
  • 双亲域:指示本结点的双亲结点在数组中的位置

r = 0 n = 10

数组下标 data parent
0 R -1
1 A 0
2 B 0
3 C 0
4 D 1
5 E 1
6 F 3
7 G 6
8 H 6
9 K 6

image-20230731093021810

特点:找双亲容易,找孩子难

C语言的类型描述:

typedef struct PTNode{
    TElemType data;
    int parent;	//双亲位置域
}PTNode;

树结构:

#define MAX_TREE_SIZE 100
typedef struct{
    PTNode nodes[MAX_TREE_SIZE];
    int r,n;		//根结点的位置和结点个数
}PTree;
孩子链表

​ 把每个结点的孩子结点排列起来,看成是一个线性表,用单链表存储,则n个结点有n个孩子链表(叶子的孩子链表为空表)。而n个头指针又组成一个线性表,用顺序表(含n个元素的结构数组)存储。

C语言的类型描述:

孩子结点结构:

typedef struct CTNode{
    int child;
    struct CTNode *next;
}*ChildPtr;

双亲结点结构:

typedef struct{
    TElemType data;
    ChildPtr firstchild;	//孩子链表头指针
}CTBox;

树结构:

typedef struct{
    CTBox nodes[MAX_TREE_SIZE];
    int n,r;	//结点数和根结点的位置
}CTree;

image-20230731094745339

特点:找孩子容易,找双亲难

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

实现:用二叉链表作树的存储结构,链表中每个结点的两个指针域分别指向其第一个孩子结点下一个兄弟结点

typedef struct CSNode{
    ElemType data;
    struct CSNode *firstchild,*nextsibling;
}CSNode,*CSTree;

image-20230731095528608

树与二叉树的转换


  • 将树转换为二叉树进行处理,利用二叉树的算法来实现对树的操作
  • 由于树和二叉树都可以用二叉链表作存储结构,则以二叉链表作媒介可以导出树与二叉树之间的一个对应关系

image-20230731100316251

给定一棵树,可以找到唯一的一颗二叉树与之对应

将树转换成二叉树


  1. 加线:在兄弟之间加一连线
  2. 抹线:对每个结点,除了其左孩子外,去除其与其余孩子之间的关系
  3. 旋转:以树的根节点为轴心,将整数顺时针转45°

树变二叉树:兄弟相连留长子

将二叉树转换为树


  1. 加线:若p结点是双亲结点的左孩子,则将p的右孩子,右孩子的右孩子......沿分支找到的所有右孩子,都与p的双亲用线连起来
  2. 抹线:抹掉原二叉树中双亲与右孩子之间的连线
  3. 调整:将结点按层次排列,形成树结构

二叉树变树:左孩右右练双亲,去掉原来右孩线

5.6.2 森林与二叉树的转化


森林转换成二叉树(二叉树与多棵树之间的关系)

  1. 将各颗树分别转换成二叉树
  2. 将每棵树的根节点用线相连
  3. 以第一颗树根节点为二叉树的根,再以根节点为轴心,顺时针旋转,构成二叉树型结构

森林变二叉树:树变二叉根相连

二叉树转换成森林

  1. 抹线:将二叉树中根结点与其右孩子连线,及沿右分支搜索到的所有右孩子间连线全部抹掉,使之变成孤立的二叉树
  2. 还原:将孤立的二叉树还原成树

二叉树变森林:去掉全部右孩线,孤立二叉再还原

5.6.3 树与森林的遍历


1.树的遍历(三种方式)

  • 先根(次序)遍历:

    • 若树不空,则先访问根节点,然后依次先根遍历各颗子树
  • 后根(次序)遍历

    • 若树不空,则先依次后根遍历各颗子树,然后访问根节点
  • 按层次遍历:

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

    image-20230731113446177

遍历结果
先根遍历 ABCDE
后根遍历 BDCEA
按层次遍历 ABCED

2.森林的遍历

将森林看作由三部分构成:

  1. 森林中第一颗树的根节点;
  2. 森林中第一颗树的子树森林;
  3. 森林中其他树构成的森林。
  • 先序遍历
    • 若森林不空,则
      • 访问森林中第一颗树的根节点
      • 先序遍历森林中第一颗树的子树森林;
      • 先序遍历森林中(除第一棵树之外)其余树构成的森林。
    • 即:依次从左至右对森林中的每一刻树进行先根遍历
  • 中序遍历
    • 若森林不空,则
      • 中序遍历森林中第一颗树的子树森林;
      • 访问森林中第一颗树的根节点;
      • 中序遍历森林中(除第一棵树之外)其余树构成的森林。
    • 即:依次从左至右对森林中的每一刻树进行后根遍历

image-20230731114038081

遍历结果
先序遍历 ABCDEFGHIJ
中序遍历 BCDAFEHJIG