1. 程式人生 > >線索二叉樹和中序非遞迴遍歷線索化後的二叉樹

線索二叉樹和中序非遞迴遍歷線索化後的二叉樹

//線索二叉樹
#include<stdio.h>
#include<malloc.h>
#include<process.h>
#define OVERFLOW -2
//二叉樹的二叉線索儲存結構
enum PointerTag{Link,Thread};  //列舉型別,Link(0):指標,Thread(1):線索
struct BiThrNode
{
	char data;
	BiThrNode *lchild,*rchild;//左右孩子指標
	PointerTag LTag,RTag;//左右標誌
};
typedef BiThrNode *BiThrTree;

//按照先序的次序輸入二叉樹中節點的值,構造線索二叉樹T,char,空格表示空節點
void CreateBiThrTree( BiThrTree &T)
{
	char ch;
	scanf("%c",&ch);
	if(ch == ' ')
		T=NULL;
	else
	{
		T=(BiThrTree)malloc(sizeof(BiThrNode));//生成根節點,先序
		if(!T)
			exit(OVERFLOW);
		T->data=ch;//給根節點賦值
		CreateBiThrTree(T->lchild);//遞迴構造左子樹
		if(T->lchild)//如果有左孩子
			T->LTag=Link;//給座標值賦值為0
		CreateBiThrTree(T->rchild);//遞迴構造右子樹
		if(T->rchild)
			T->RTag=Link;//如果有右孩子,就給右標誌賦值為0
	}
} 
BiThrTree pre;//全域性變數,始終指向剛剛訪問過的節點

//通過中序遍歷進行中序線索化,線索化之後,pre指向最後一個節點
void InThreading(BiThrTree p)//p為指向根節點的指標
{
	if(p)//線索二叉樹不空
	{
		InThreading(p->lchild);//遞迴左子樹線索化
		if(!p->lchild)//左子樹為空
		{
			p->LTag=Thread;//左標誌為線索
			p->lchild=pre;//左孩子指標指向前驅
		}
		if(!pre->rchild)//如果前驅沒有右孩子
		{
			pre->RTag=Thread;//前驅的右孩子為線索
			pre->rchild=p;//前驅的右孩子節點指向其後繼節點,(即當前節點p)
		}
		pre=p;//保持pre指向p的前驅
		InThreading(p->rchild);//遞迴右子樹線索化
	}
}
//中序遍歷二叉樹T,將其中序線索化,Thrt指向頭結點
void InOrderThreading(BiThrTree &Thrt,BiThrTree T)
{
	Thrt=(BiThrTree)malloc(sizeof(BiThrNode));//生成頭結點
	if(!Thrt)
	exit(OVERFLOW);
	Thrt->LTag=Link;//建立頭結點左標誌為指標
	Thrt->RTag=Thread;//右標誌為線索
	Thrt->lchild=Thrt;//右指標回指
	if(!T)//如果二叉樹空則左指標回指
		Thrt->lchild=Thrt;
	else
	{
		Thrt->lchild=T;//頭指標的左指標指向根節點
		pre=Thrt;//pre的初值指向頭結點
		InThreading(T);//中序遍歷,進行中序線索化,pre指向中序遍歷後的最後一個節點
		//收尾工作
		pre->RTag=Thread;//最後一個節點的右標誌為線索
		pre->rchild=Thrt;//最後一個節點的右指標指向頭結點
		Thrt->rchild=pre;//頭節點的右指標指向中序遍歷的最後一個節點
	}
}
//中序遍歷線索化後的二叉樹T(頭節點)的非遞迴演算法
void InOrderTraverse_Thr(BiThrTree T)
{
	BiThrTree p;
	p=T->lchild;//p指向根節點
	while(p != T) //空樹或者是遍歷結束時,p==T
	{
		while(p->LTag == Link)//由根節點一直找到二叉樹的最左節點
			p=p->lchild;
		printf("%c ",p->data);//訪問此節點
		while(p->RTag == Thread && p->rchild != T)//p->rchild是後繼,且不是遍歷的最後一個節點
		{
			p=p->rchild;
			printf("%c ",p->data);//訪問後繼節點
		}
		p=p->rchild;//若p->rchild不是線索,p指向右孩子,返回迴圈,找這棵子樹中序遍歷的第一個節點
	}
}
void main()
{
	BiThrTree H,T;
	printf("請按照先序的次序輸入二叉樹:\n");
	CreateBiThrTree(T);//按照先序產生二叉樹
	InOrderThreading(H,T);//H是頭,T是根,中序遍歷的過程中,中序線索化二叉樹
	printf("中序遍歷線索二叉樹:");
	InOrderTraverse_Thr(H);
	printf("\n");
}

程式的執行結果:

以下圖片能夠幫助你更好地理解本程式:

                      圖一 空的二叉樹

                                                                                          圖二  二叉樹的二叉線索儲存結構

                                          圖三 CreateBiThrTree()產生的二叉樹


                圖四   中序線索二叉樹儲存結構


                                                圖 5 中序線索化二叉樹