C語言數(shù)據(jù)結(jié)構(gòu)之線索二叉樹及其遍歷
C語言數(shù)據(jù)結(jié)構(gòu)之線索二叉樹及其遍歷
遍歷二叉樹就是以一定的規(guī)則將二叉樹中的節(jié)點排列成一個線性序列,從而得到二叉樹節(jié)點的各種遍歷序列,其實質(zhì)是:對一個非線性的結(jié)構(gòu)進行線性化。使得在這個訪問序列中每一個節(jié)點都有一個直接前驅(qū)和直接后繼。傳統(tǒng)的鏈式結(jié)構(gòu)只能體現(xiàn)一種父子關(guān)系,¥不能直接得到節(jié)點在遍歷中的前驅(qū)和后繼¥,而我們知道二叉鏈表表示的二叉樹中有大量的空指針,當(dāng)使用這些空的指針存放指向節(jié)點的前驅(qū)和后繼的指針時,則可以更加方便的運用二叉樹的某些操作。引入線索二叉樹的目的是: 為了加快查找節(jié)點的前驅(qū)和后繼。對二叉樹的線索化就是對二叉樹進行一次遍歷,在遍歷的過程中檢測節(jié)點的左右指針是否為空,如果是空,則將他們改為指向前驅(qū)和后繼節(jié)點的線索。
如果二叉樹沒有被線索化,也可以使用<<非遞歸>>的代碼進行遍歷的,但是那就需要借助于<<棧>>,但是在線索化之后,對線索化的二叉樹進行<<非遞歸>>的遍歷就不再需要棧的輔助。
實現(xiàn)代碼:
#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define ERROR 0
typedef char ElemType;
typedef int Status;
/* 定義枚舉類型,其值只能是Link和Thread
* Link表示的該指針指示的是孩子
* Thread表示的是還指針指示的是前驅(qū)或者是后綴
* */
typedef enum {
Link,Thread
}PointerTag;
typedef struct ThrBiTrNode{
ElemType data;
struct ThrBiTrNode *lchild, *rchild;
PointerTag rTag, lTag;
}ThrBiTrNode, *ThrBiTree;
ThrBiTree Pre;
Status InitThreadBinaryTree(ThrBiTree* T){
*T = NULL;
return OK;
}
//先序建立二叉樹,lchild和rchild都是指示做孩子和右孩子,所以lTag和rTag為Link
Status ThreadBinaryTree_PreOrderInput(ThrBiTree* T){
ElemType c;
scanf("%c", &c);
if( ' ' == c ){
*T = NULL;
}
else{
*T = (ThrBiTrNode*)malloc(sizeof(ThrBiTrNode));
if( !*T ){
return ERROR;
}
(*T)->data = c;
(*T)->lTag = Link;
(*T)->rTag = Link;
ThreadBinaryTree_PreOrderInput(&(*T)->lchild);
ThreadBinaryTree_PreOrderInput(&(*T)->rchild);
}
return OK;
}
//<<中序遍歷>>對二叉樹進行<<線索化>>,但是沒有提供Pre的初始值,只是給出了
//中間的過程,遞歸的思想和思考方式。
//1 線索化左子樹
//2 對雙親節(jié)點處理//遞歸中的base
//3 線索化右子樹
Status InOrderThread(ThrBiTree T){
if( T != NULL ){
InOrderThread(T->lchild); //線索化左子樹
//對雙親節(jié)點進行線索化處理
if( T->lchild == NULL ){ //如果左孩子為空,則將lchild作為索引
//Pre指向剛剛訪問的節(jié)點
T->lTag = Thread;
T->lchild = Pre;
}
if( Pre->rchild == NULL ){ //直到現(xiàn)在才知道Pre的后綴是T,所以
//要對Pre進行設(shè)置,如果Pre的rchild為空
//則將Pre的rchild設(shè)置為后綴,指向T
Pre->rTag = Thread;
Pre->rchild = T;
}
Pre = T; //標記當(dāng)前的節(jié)點稱為剛剛訪問過的節(jié)點
//Pre最后會指向樹的中序遍歷的最后的
//一個節(jié)點
InOrderThread(T->rchild); //線索化右子樹
}
return OK;
}
//創(chuàng)建中序線索二叉樹,為上個函數(shù)提供Pre
Status CreateInOrderThreadBinaryTree(ThrBiTree T, ThrBiTree* headOfTree){
*headOfTree = (ThrBiTrNode*)malloc(sizeof(struct ThrBiTrNode));
if( !headOfTree )
return ERROR;
(*headOfTree)->lTag = Link; //將要指向T
(*headOfTree)->rTag = Thread; //將頭節(jié)點的rchild用于索引
(*headOfTree)->rchild = *headOfTree; //指向自身
if( T == NULL ){
(*headOfTree)->lchild = *headOfTree; //若T為空樹,則頭節(jié)點的lchild
//指向自身
}
else{
(*headOfTree)->lchild = T;
Pre = *headOfTree; //賦值了全局變量Pre
InOrderThread(T); //中序線索化
//printf("\n%c\n",Pre->data);
//執(zhí)行完InOrderThread之后Pre指向最后
//一個節(jié)點
Pre->rTag = Thread;
Pre->rchild = *headOfTree;
//(*headOfTree)->rchild = Pre;
}
return OK;
}
//對中序線索化后的線索二叉樹使用<<非遞歸>>的代碼進行中序遍歷
//并且原來的遞歸形式的代碼在這里是不再可以進行遍歷。
// 如果二叉樹沒有被線索化,也可以使用<<非遞歸>>的代碼進行遍
// 歷的,但是那就需要借助于<<棧>>,但是在線索化之后,對線索
// 化的二叉樹進行<<非遞歸>>的遍歷就不再需要棧的輔助。
Status visit(ElemType c){
printf("%c ", c);
return OK;
}
Status InOrderTeaverse_NoRecursion(ThrBiTree T, ThrBiTree headOfTree){
//headOfTree是T的頭節(jié)點的指針,headOfTree->lchild = T;
while( T != headOfTree ){
while( T->lTag == Link ){ //找到樹(子樹)的最左節(jié)點
//用while接替if//
//用if理解while//
T = T->lchild;
}
visit(T->data);
while( T->rTag == Thread && T->rchild != headOfTree){
//這個while和下面的T=T->rchild
//可用ifelse語句理解。
//if(rchild是線索 && 不是最后一個節(jié)點)
//else(rchild不是線索)-->走到右孩子
//也就是代碼T=T->rchild
T = T->rchild;
visit(T->data);
}
T = T->rchild;
}
return OK;
}
//求中序線索二叉樹中中序序列下的第一個節(jié)點
ThrBiTrNode* SeekFirstNode_InOrderThrBiTree(ThrBiTree T){
if( T != NULL ){
while( T->lTag == Link ){
T = T->lchild;
}
return T;
}
return ERROR;
}
//求中序線索二叉樹中節(jié)點P在中序序列下的下一個節(jié)點
ThrBiTrNode* GetNextNode(ThrBiTrNode* CurrentP){
if( CurrentP->rTag == Link ){ //有右孩子的時候,那么下一個就是以
//右孩子為root的樹的最左下角元素。
//即seekFirstNode的返回值。
return SeekFirstNode_InOrderThrBiTree(CurrentP->rchild);
}
else{ //沒有右孩子,則rchild指向后綴
return CurrentP->rchild;
}
}
//使用上面兩個函數(shù),SeekFirstNode_InOrderThrBiTree和GetNextNode來實現(xiàn)對
//中序先做二叉樹的遍歷
Status InOrderTraverse_NoRecursion_Method(ThrBiTree T, ThrBiTree head){
for( T = SeekFirstNode_InOrderThrBiTree(T) ; T != head ; T = GetNextNode(T) )
visit(T->data);
return OK;
}
//test
/* ShowThread函數(shù)的目的是想在將T中序線索化之后,使用函數(shù)InOrderTraverse
* 函數(shù)中序遍歷,輸出一下節(jié)點中的信息以檢驗線索化,但是失敗。原因是:在
* 線索化之后,空指針域都被應(yīng)用,所有InOrderTraverse函數(shù)中的if( T )是滿
* 足不了的,故失敗。
Status ShowThread(ThrBiTree C){
printf("%d %d %d %d\n",(C->lchild)->data,(C->rchild)->data,C->lTag,C->rTag);
printf("%d %d\n",C->lTag,C->rTag);
return OK;
* */
//中序遍歷二叉樹
Status InOrderTraverse(ThrBiTree T){
if( T ){
InOrderTraverse(T->lchild);
visit(T->data);
InOrderTraverse(T->rchild);
}
return OK;
}
int main(){
ThrBiTree T,R,Head = NULL;
InitThreadBinaryTree(&T);
printf("Please Input Binary Tree By PreOrder\n ");
ThreadBinaryTree_PreOrderInput(&T);
printf(" InOrder Traverse before Thread with Recursion\n");
InOrderTraverse(T);
printf("\n");
CreateInOrderThreadBinaryTree(T,&Head);
printf(" InOrder Traverse after Thread with no-Recursion\n");
InOrderTeaverse_NoRecursion(T,Head);
printf("\n");
printf("The root is %c \n", T->data); //不能夠通過指針形參的值改變指針實參的值
//或者說,對指針形參的改變不會作用到指針
//實參上。
ThrBiTrNode *firstOfInOrder = NULL,*secondOfInOrder = NULL;
if( SeekFirstNode_InOrderThrBiTree(T) != ERROR ){
firstOfInOrder = SeekFirstNode_InOrderThrBiTree(T);
printf("the value of First Node of InOrderThreadBinaryTree is %c\n", firstOfInOrder->data);
}
secondOfInOrder = GetNextNode(firstOfInOrder);
printf("the value of Node after D is: %c \n", secondOfInOrder->data);
secondOfInOrder = GetNextNode(secondOfInOrder);
printf("the value of Node after B is: %c \n", secondOfInOrder->data);
secondOfInOrder = GetNextNode(secondOfInOrder);
printf("the value of Node after E is: %c \n", secondOfInOrder->data);
secondOfInOrder = GetNextNode(secondOfInOrder);
printf("the value of Node after A is: %c \n", secondOfInOrder->data);
secondOfInOrder = GetNextNode(secondOfInOrder);
printf("the value of Node after C is: %c \n", secondOfInOrder->data);
secondOfInOrder = GetNextNode(secondOfInOrder);
printf("the value of Node after G is: %c \n", secondOfInOrder->data);
secondOfInOrder = GetNextNode(secondOfInOrder);
printf("the value of Node after root is: %c \n", secondOfInOrder->data);
printf(" InOrder Traverse after Thread with no-Recursion Method_2\n");
InOrderTraverse_NoRecursion_Method(T,Head);
return 0;
}
以上就是線索二叉樹及遍歷的實例,如有疑問請留言或者到本站社區(qū)交流討論,感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
您可能感興趣的文章
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用函數(shù)刪除字符
- 04-02c語言的正則匹配函數(shù) c語言正則表達式函數(shù)庫
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言中對數(shù)函數(shù)的表達式 c語言中對數(shù)怎么表達
- 04-02c語言用函數(shù)寫分段 用c語言表示分段函數(shù)
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排序法函數(shù)
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段函數(shù)
- 04-02C語言中怎么打出三角函數(shù) c語言中怎么打出三角函數(shù)的值
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求階乘


閱讀排行
本欄相關(guān)
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言的正則匹配函數(shù) c語言正則表達
- 04-02c語言用函數(shù)寫分段 用c語言表示分段
- 04-02c語言中對數(shù)函數(shù)的表達式 c語言中對
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段
- 04-02C語言中怎么打出三角函數(shù) c語言中怎
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求
隨機閱讀
- 04-02jquery與jsp,用jquery
- 01-10delphi制作wav文件的方法
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 01-10C#中split用法實例總結(jié)
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 01-11ajax實現(xiàn)頁面的局部加載
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 08-05織夢dedecms什么時候用欄目交叉功能?
- 01-10使用C語言求解撲克牌的順子及n個骰子


