首页/数据结构/04-tree/树的存储结构 🔗 在 Obsidian 中打开
数据结构 · 04-tree

树的存储结构

重要度 ⭐⭐ 存储结构双亲表示法孩子兄弟表示法
速查
三种存储:双亲表示法(parent 下标,找父 O(1)、找孩子 O(n));孩子表示法(孩子链表,找孩子 O(1)、空间 O(n+e));孩子兄弟表示法(左孩子右兄弟,树↔二叉树转换的基础)。

核心概念

树的存储结构主要有三种:双亲表示法孩子表示法孩子兄弟表示法

一、双亲表示法

用一组连续空间存储结点,每个结点含 dataparent(父结点下标,根为 -1):

#define MaxSize 100
typedef struct { ElemType data; int parent; } PTNode;   // parent:父结点下标,根为 -1
typedef struct { PTNode nodes[MaxSize]; int n; } PTree;

示例树 A(B(D,E),C(F)) 的双亲表示:

下标dataparent
0A-1
1B0
2C0
3D1
4E1
5F2

优点:找父结点 O(1);缺点:找孩子需遍历整个数组 O(n)。

二、孩子表示法

typedef struct CTNode { int child; struct CTNode *next; } CTNode;
typedef struct { ElemType data; CTNode *firstChild; } CTBox;   // 孩子链表头
typedef struct { CTBox nodes[MaxSize]; int n, r; } CTree;      // r = 根位置
下标  data  孩子链表
 0    A  → [1] → [2] → NULL
 1    B  → [3] → [4] → NULL
 2    C  → [5] → NULL
 3    D  → NULL …

优点:找孩子方便;缺点:找父结点需遍历。

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

typedef struct CSNode {
    ElemType data;
    struct CSNode *firstChild, *nextSibling;  // 第一个孩子、下一个兄弟
} CSNode, *CSTree;

示例:A(B,C,D) 且 B 有孩子 E、F:

     A
    /
   B        ← B 的左孩子 = 第一个孩子;右孩子 = 下一个兄弟 C
  / \
 D   E      ← 等价二叉树:D→E 相当于"E 是 D 的下一个兄弟"…
意义孩子兄弟表示法将任意树转换为二叉树(左孩子右兄弟),是树与二叉树转换的理论基础。

关键性质

表示法找父结点找孩子空间
双亲表示法O(1)O(n)O(n)
孩子表示法O(n)O(1)O(n+e)
孩子兄弟表示法O(n)O(第一个孩子)O(n)
左指针 = 第一个孩子,右指针 = 下一个兄弟这是孩子兄弟表示法的核心约定,也是左孩子右兄弟转换的来源。

手算示例

示例一:双亲表示法的构造

       1
      / \
     2   3
    /   / \
   4   5   6
下标dataparent
01-1
120
230
341
452
562

示例二:孩子兄弟表示法

       A
     / | \
    B  C  D
   / \
  E   F
  →
      A
     /
    B
   / \
  E   C
   \   \
    F   D
  • A 的第一个孩子 B(左指针)
  • B 的下一个兄弟 C(B 的右指针),C 的下一个兄弟 D(C 的右指针)
  • B 的第一个孩子 E(左指针),E 的下一个兄弟 F(E 的右指针)

示例三:求祖先路径

双亲表示中求 E(下标 4)的祖先路径:$E(4) \to parent=1(B) \to parent=0(A) \to parent=-1$(结束)→ 路径 E → B → A

常见考法

题型一给定一棵树,画出其双亲/孩子/孩子兄弟表示法。
题型二各种表示法中查找父/孩子结点的时间复杂度。
题型三用孩子兄弟表示法表示给定树,并画出等价二叉树。
题型四 · 场景频繁找父结点用双亲表示法;频繁找孩子用孩子表示法。

易错点

易错清单
  1. 双亲表示法根结点 parent 为 -1:不是 0。
  2. 左指针 = 第一个孩子,右指针 = 下一个兄弟:不要搞反。
  3. 孩子表示法空间是 O(n+e):不是 O(n),因为有孩子链表额外空间。
  4. 孩子兄弟表示法是树转二叉树的基础:重要考点。
  5. 双亲表示法找孩子要遍历整个数组:虽然找父是 O(1)。

核心结论

表示法核心思想最适合场景
双亲表示法每个结点记录父结点下标频繁找父结点
孩子表示法每个结点维护孩子链表频繁找孩子
孩子兄弟表示法左孩子右兄弟,可转二叉树树与二叉树转换
最重要孩子兄弟表示法树转二叉树的理论基础(左孩子右兄弟)。

记忆卡片

双亲表示法中根结点的 parent?
-1(表示没有父结点,不是 0)。
孩子兄弟表示法的左右指针?
左指针→第一个孩子,右指针→下一个兄弟。
为什么孩子兄弟表示法最重要?
能把任意树转换为二叉树(左孩子右兄弟),是树与二叉树转换的理论基础。
双亲表示法求祖先路径?
反复取 parent 直到 -1,如 E(4)→B(1)→A(0)→结束。

交互动画 · 双亲表示法操作

树(左侧)与双亲表示法数组(右侧) A B C D E F 下标dataparent 0 A -1 1 B 0 2 C 0 3 D 1 4 E 1 5 F 2 parent = 父结点 下标(O(1) 直达) 找孩子须遍历全表: 扫描 parent==1 → D、E
双亲表示法:parent 存父结点下标,根为 -1
点按钮观察 O(1) 找父、O(n) 找孩子、祖先路径
双亲表示找父 O(1);找孩子需遍历整个数组 O(n)(孩子表示法反之)。

相关知识点

(暂无关联知识点)

↑ 以上为站内 HTML 相对链接(纯网页可浏览);本页右上「在 Obsidian 中打开」跳回源笔记。