中序線索化二叉樹及遍歷。
函數接口定義:
void InThreading(BiThrTree p);// 以結點P爲根的子樹中序線索化
void InOrderTraverse_Thr(BiThrTree T);// 中序遍歷二叉線索樹T的非遞歸算法,對每個數據元素直接輸出
裁判測試程序樣例:
#include<iostream>
using namespace std;
typedef struct BiThrNode
{
char data;
struct BiThrNode *lchild,*rchild;
int LTag,RTag;
}BiThrNode,*BiThrTree;
BiThrNode *pre=new BiThrNode;
void CreateBiTree(BiThrTree &T)
{
char ch;
cin >> ch;
if(ch=='#') T=NULL;
else
{
T=new BiThrNode;
T->data=ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
}
void InThreading(BiThrTree p);
void InOrderTraverse_Thr(BiThrTree T);
int main()
{
pre->RTag=1;
pre->rchild=NULL;
BiThrTree tree;
CreateBiTree(tree);
InThreading(tree);
InOrderTraverse_Thr(tree);
return 0;
}
/* 請在這裏填寫答案 */
輸入樣例:
ABD###CEG###FH##I##
輸出樣例:
DBAGECHFI
分析:從裁判樣例入手
- 先序遍歷建樹
void CreateBiTree(BiThrTree &T)
{
char ch;
cin >> ch;
if(ch=='#')
T=NULL;
else
{
T=new BiThrNode;
T->data=ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
}
- 建立中序線索,賦予前驅和後繼的值
void InThreading(BiThrTree root)/* 對root所指的二叉樹進行中序線索化,其中pre始終指向剛訪問過的結點,其初值爲NULL*/
{
if (root!=NULL)
{
InThreading(root->lchild); /* 線索化左子樹 */
if (root->lchild==NULL)/*沒有左孩子指向前驅*/
{
root->LTag=1;
root->lchild=pre->rchild; /*置前驅線索 */
/*主函數是對pre->rchild=NULL,賦值爲空。第一個結點的前驅爲空,此時要把pre->rchild賦給root->lchild,而不是把pre賦給root->lchild*/
}
if (pre!=NULL&&pre->rchild==NULL) /* 置後繼線索 */
{
pre->rchild=root;
pre->RTag=1;
}
pre=root;
InThreading(root->rchild); /*線索化右子樹*/
}
}
- 找到中序遍歷的第一個結點,並不斷找後繼,此時輸出的就是中序遍歷
BiThrNode * InNext(BiThrNode *p)
/*在中序線索二叉樹中查找p的中序後繼結點,並用next指針返回結果*/
{
BiThrNode *Next;
BiThrNode *q;
if (p->RTag==1)
Next=p->rchild; /*直接利用線索*/
else
{
/*在p的右子樹中查找"最左下端"結點*/
if(p->rchild!=NULL)
{
for(q=p->rchild; q->LTag==0 ; q=q->lchild);
Next=q;
}
else
Next = NULL;
}
return Next;
}
BiThrNode* TinFirst(BiThrTree root)
{
BiThrNode *q=root;
q=root;
if(q)
while(q->lchild!=NULL)/*找左子樹的左子樹。。。*/
q=q->lchild;
return q;
}
void InOrderTraverse_Thr(BiThrTree root)
{
BiThrNode *p;
p=TinFirst(root);/*找到第一個結點*/
while(p!=NULL)
{
printf("%c",p->data);
p=InNext(p);
}
}
完整代碼:
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
typedef struct BiThrNode
{
char data;
struct BiThrNode *lchild,*rchild;
int LTag,RTag;
} BiThrNode,*BiThrTree;
BiThrNode *pre=new BiThrNode;
void CreateBiTree(BiThrTree &T)
{
char ch;
cin >> ch;
if(ch=='#')
T=NULL;
else
{
T=new BiThrNode;
T->data=ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
}
void InThreading(BiThrTree root)/* 對root所指的二叉樹進行中序線索化,其中pre始終指向剛訪問過的結點,其初值爲NULL*/
{
if (root!=NULL)
{
InThreading(root->lchild); /* 線索化左子樹 */
if (root->lchild==NULL)/*沒有左孩子指向前驅*/
{
root->LTag=1;
root->lchild=pre->rchild; /*置前驅線索 */
}
if (pre!=NULL&&pre->rchild==NULL) /* 置後繼線索 */
{
pre->rchild=root;
pre->RTag=1;
}
pre=root;
InThreading(root->rchild); /*線索化右子樹*/
}
}
BiThrNode * InNext(BiThrNode *p)
/*在中序線索二叉樹中查找p的中序後繼結點,並用next指針返回結果*/
{
BiThrNode *Next;
BiThrNode *q;
if (p->RTag==1)
Next=p->rchild; /*直接利用線索*/
else
{
/*在p的右子樹中查找"最左下端"結點*/
if(p->rchild!=NULL)
{
for(q=p->rchild; q->LTag==0 ; q=q->lchild);
Next=q;
}
else
Next = NULL;
}
return Next;
}
BiThrNode* TinFirst(BiThrTree root)
{
BiThrNode *q=root;
q=root;
if(q)
while(q->lchild!=NULL)/*找左子樹的左子樹。。。*/
q=q->lchild;
return q;
}
void InOrderTraverse_Thr(BiThrTree root)
{
BiThrNode *p;
p=TinFirst(root);/*找到第一個結點*/
while(p!=NULL)
{
printf("%c",p->data);
p=InNext(p);
}
}
int main()
{
pre->RTag=1;
pre->rchild=NULL;
BiThrTree tree;
CreateBiTree(tree);
InThreading(tree);
InOrderTraverse_Thr(tree);
return 0;
}
若在主函數初始化pre爲NULL,則建立中序線索二叉樹時
void Inthread(BiTree root)/* 對root所指的二叉樹進行中序線索化,其中pre始終指向剛訪問過的結點,其初值爲NULL*/
{
if (root!=NULL)
{
Inthread(root->LChild); /* 線索化左子樹 */
if (root->LChild==NULL)/*沒有左孩子指向前驅*/
{
root->Ltag=1;
root->LChild=pre; /*置前驅線索*/
/*第一個結點沒有前驅,則直接把pre賦值給root->LChild*/
}
if (pre!=NULL&& pre->RChild==NULL) /* 置後繼線索 */
{
pre->RChild=root;
pre->Rtag=1;
}
pre=root;
Inthread(root->RChild); /*線索化右子樹*/
}
}
完整代碼:
#include <stdio.h>
#include <malloc.h>
#include <conio.h>
typedef char DataType;
typedef struct Node
{
DataType data;
int Ltag;
int Rtag;
struct Node *LChild;
struct Node *RChild;
} BiTNode, *BiTree;
BiTree pre;
void CreateBiTree(BiTree *bt)/*先序遍歷建立二叉樹*/
{
char ch;
ch = getchar();
if(ch=='#')
*bt=NULL;
else
{
*bt=(BiTree)malloc(sizeof(BiTNode)); //生成一個新結點
(*bt)->data=ch;
(*bt)->Ltag=0;/*相當於初始化*/
(*bt)->Rtag=0;
CreateBiTree(&((*bt)->LChild)); //生成左子樹
CreateBiTree(&((*bt)->RChild)); //生成右子樹
}
}
void Inthread(BiTree root)/* 對root所指的二叉樹進行中序線索化,其中pre始終指向剛訪問過的結點,其初值爲NULL*/
{
if (root!=NULL)
{
Inthread(root->LChild); /* 線索化左子樹 */
if (root->LChild==NULL)/*沒有左孩子指向前驅*/
{
root->Ltag=1;
root->LChild=pre; /*置前驅線索 */
}
if (pre!=NULL&& pre->RChild==NULL) /* 置後繼線索 */
{
pre->RChild=root;
pre->Rtag=1;
}
pre=root;
Inthread(root->RChild); /*線索化右子樹*/
}
}
BiTNode * InNext(BiTNode * p)
/*在中序線索二叉樹中查找p的中序後繼結點,並用next指針返回結果*/
{
BiTNode *Next;
BiTNode *q;
if (p->Rtag==1)
Next = p->RChild; /*直接利用線索*/
else
{
/*在p的右子樹中查找"最左下端"結點*/
if(p->RChild!=NULL)
{
for(q=p->RChild; q->Ltag==0 ; q=q->LChild);
Next=q;
}
else
Next = NULL;
}
return(Next);
}
BiTNode* TinFirst(BiTree root)
{
BiTNode *p;
p = root;
if(p)
while(p->LChild!=NULL)
p=p->LChild;
return p;
}
void TinOrder(BiTree root)
{
BiTNode *p;
p=TinFirst(root);
while(p!=NULL)
{
printf("%c",p->data);
p=InNext(p);
}
}
int main()
{
BiTree T;
BiTree p,q;
CreateBiTree(&T);
pre=NULL;
Inthread(T);
TinOrder(T);
return 0;
}