資料結構 樹筆記-5 線索二叉樹 以及 線索二叉連結串列
線索二叉連結串列
線索二叉連結串列 來自於 二叉連結串列。一個二叉連結串列,如果存放n個結點,就一定有n+1個空指標域,而線上索鏈 表中,就讓這n+1個空指標域有了用武之地。
空指標域 用於存放 某種遍歷順序下的 前驅或者後繼的地址。
已知 一棵二叉樹的結構:
|
|
|
孩子地址:B的地址 |
A |
孩子地址:D的地址 |
|
|
孩子地址:NULL |
B |
孩子地址: C的地址 |
|
孩子地址: |
D |
孩子地址: E的地址 |
|
|
孩子地址:NULL |
C |
孩子地址:NULL |
|
孩子地址: F的地址 |
E |
孩子地址:NULL |
|
|
|
|
孩子地址:NULL |
F |
孩子地址:NULL |
|
其先序遍歷結果:ABCDEF,對應的先序線索二叉樹(二叉樹的先序線索化)
|
|
|
孩子地址:B的地址 |
A |
孩子地址:D的地址 |
|
|
線索地址: A的地址 |
B |
孩子地址: C的地址 |
|
線索地址: C的地址 |
D |
孩子地址: E的地址 |
|
|
線索地址: B的地址 |
C |
線索地址: D的地址 |
|
孩子地址: F的地址 |
E |
線索地址: F的地址 |
|
|
|
|
線索地址: E的地址 |
F |
線索地址:NULL |
|
其中序遍歷結果:BCADFE,對應的中序線索二叉樹(二叉樹的中序線索化)
|
|
|
孩子地址: B的地址 |
A |
孩子地址: D的地址 |
|
|
線索地址: NULL |
B |
孩子地址: C的地址 |
|
線索地址: A的地址 |
D |
孩子地址: E的地址 |
|
|
線索地址: B的地址 |
C |
線索地址: A的地址 |
|
孩子地址: F的地址 |
E |
線索地址: NULL |
|
|
|
|
線索地址: D的地址 |
F |
線索地址: E的地址 |
|
其後序遍歷結果:CBFEDA,對應的後線索二叉樹(二叉樹的後序線索化)
|
|
|
孩子地址: B的地址 |
A |
孩子地址: D的地址 |
|
|
線索地址: C的地址 |
B |
孩子地址: C的地址 |
|
線索地址: E的地址 |
D |
孩子地址: E的地址 |
|
|
線索地址: NULL |
C |
線索地址: B的地址 |
|
孩子地址: F的地址 |
E |
線索地址: D的地址 |
|
|
|
|
線索地址: B的地址 |
F |
線索地址: E的地址 |
|
線索二叉樹的程式碼定義:
#define TElemType char;
typedef enum{
Link,Thread
}PointerTag;
// 列舉型別PointerTag中的Link=0,標識 孩子指標;
// 列舉型別PointerTag中的Thread=1,標識 線索
typedef struct BiThrNode{
TElemType data;
struct BiThrNode *lc,*rc;
PointerTag LTag,RTag;
}BiThrNode, *BiThrTree;
說明:
如果某結點 有 左孩子,則LTag=Link=0,lc=左孩子的地址
沒有 左孩子,則LTag=Thread=1,lc=此結點在某遍歷順序下的前驅結點的地址
(思考:為什麼如果存線索,存的是前驅結點的地址,而不是後繼結點的地址?)
如果某結點 有 右孩子,則RTag=Link=0,lc=右孩子的地址
沒有 右孩子,則RTag=Thread=1,rc=此結點在某遍歷順序下的後繼結點的地址
(同理思考:為什麼如果存線索,存的是後繼結點的地址,而不是前驅結點的地址?)