數據結構之線索二叉樹和森林
線索二叉樹
利用空指針域來真存放結點的前驅和後繼信息
♦ 定義:
- 前驅與後繼:在二叉樹的先序、中序或後序遍歷序列中兩個相鄰的結點互稱為~
- 線索:指向前驅或後繼結點的指針稱為~
- 線索二叉樹:加上線索的二叉鏈表表示的二叉樹叫~
- 線索化:對二叉樹按某種遍歷次序使其變為線索二叉樹的過程叫~
♦ 實現:
- 在有n個結點的二叉鏈表中必定有n+1個空鏈域
- 在線索二叉樹的結點中增加兩個標誌域(0指結點,1左前右後)
- ltag :若 ltag=0, lchild 域指向左孩子;
- 若 ltar=1, lchild域指向其前驅
- rtag :若 rtag =0, rchild 域指向右孩子;
- 若 rtag=1, rchild域指向其後繼
例如:遍歷中序線索二叉樹
在中序線索二叉樹中找結點後繼的方法:
(1)若rtag=1, 則rchild域直接指向其後繼
(2)若rtag=0, 則結點的後繼應是其右子樹的左鏈尾(ltag=1)的結點
在中序線索二叉樹中找結點前驅的方法:
(1)若ltag=1, 則lchild域直接指向其前驅
(2)若ltag=0, 則結點的前驅應是其左子樹的右鏈尾(rtag=1)的結點
樹和森林
樹的存儲結構有:雙親表示法、孩子表示法、孩子兄弟表示法。
1.雙親存儲表示法
用一組地址連續的存儲單元來存放樹的結點,每個結點有兩個域:
data域-----存放結點的信息;
parent域-----存放該結點唯一的雙親結點的位置(數組下標)
雙親表示法的存儲結構描述為:
#define MaxTreeSize 100 typedef char DataType; typedef struct{ DataType data; int parent; } PTreeNode; typedef struct { PTreeNode nodes[MaxTreeSize]; int r,n;//根結點的位置和結點個數 }PTree; PTree T;
2、孩子表示法
把每個結點的孩子結點排列起來,看作線性表,且以單鏈表做存儲結構。
孩子表示法的存儲結構描述為:
typedef struct Cnode { int child; struct CNode *next; } Cnode; /*孩子結點類型說明*/ typedef struct { DataType data; Cnode *firstchild; } PTNode; /*數組的每個元素的類型說明*/ typedef struct { PTNode nodes[MaxTreeSize]; int n,root; } Ctree;
3、孩子兄弟表示法
用二叉鏈表作為樹的存儲結構,每個結點的左鏈域指向該結點的第一個孩子,右鏈域指向下一個兄弟結點。由於結點中的兩個指針指示的分別為“孩子”和“兄弟”,故稱為“孩子-兄弟鏈表”。(左孩右兄)
樹的孩子兄弟鏈表的存儲結構描述為:
typedef struct CSNode{ ElemType data; struct CSNode *firstchild,*nextsibling; } CSNode, *CSTree;
孩子兄弟存儲結構的優點是可以方便地實現樹和二叉樹的相互轉換和樹的各種操作;
缺點是查找當前結點的雙親結點比較麻煩。 解決方法:增設parent域。
森林轉換成二叉樹
轉換原則:
(1)將森林中的每棵樹轉換成等價的二叉樹;
(2)保留第一棵二叉樹,從第二棵二叉樹開始,依次將後一棵二叉樹的根結點作為前一棵二叉樹根結點的右孩子,所有二叉樹依此相連。
樹轉化為二叉樹的意義:
1、因為對二叉樹的許多操作算法簡單,而任何樹都可以與二叉樹相互轉換,這樣就解決了樹的存儲結構及其運算中存在的復雜性。
2、所有的樹中,2度樹的鏈域(存儲空間)利用率最高。
樹和森林的遍歷
1.樹的遍歷
所謂樹的遍歷,就是按照某種順序依次訪問樹中各個結點,並使得每個結點只被訪問一次。也就是把非線性結構的樹結點變成線性序列的一種方式。
樹的遍歷方法有:
按廣度優先遍歷(即按層次遍歷)
按深度優先遍歷,又可分為:前序遍歷和後序遍歷
2.森林的遍歷
森林的遍歷可分為前序遍歷與中序遍歷
數據結構之線索二叉樹和森林