1. 程式人生 > >C語言線索二叉樹的實現

C語言線索二叉樹的實現

        線索二叉樹的主要操作,包含:以p為根節點的子樹中序線索化,帶頭結點的二叉樹中序線索化和遍歷線索二叉樹這幾個函式。

        下面講一下實現程式碼:           

        首先,依然是型別定義,並宣告一個全域性變數pre:

typedef char ElemType;
typedef struct BiThrNode{
	ElemType data;
	BiThrNode *lchild, *rchild;
	int LTag, RTag;
}BiThrNode,*BiThrTree;
BiThrTree pre;

        帶頭結點的二叉樹中序線索化:

BiThrNode *InOrderThreading(BiThrTree T)
{
	BiThrTree Thrt, p;
	Thrt = (BiThrNode *)malloc(sizeof(BiThrNode));
	Thrt->LTag = 0;
	Thrt->RTag = 1;
	Thrt->rchild = Thrt;
	if (!T)
		Thrt->lchild = Thrt;
	else
	{
		Thrt->lchild = T;
		pre = Thrt;
		InThreading(T);
		Thrt->rchild = pre;
		pre->RTag = 1;
		pre->rchild = Thrt;
	}
	return Thrt;
}

        先為Thrt動態分配空間,並讓Thrt->LTag=0,Thrt->Rtag=1,讓Thrt的右子樹指向自己。判斷二叉樹T是否為空樹,如果為空樹,則讓Thrt的左子樹也指向自己;否則,讓其左子樹指向T的根節點,並且讓全域性變數pre=Thrt,線索化T(利用InThreading(),下面會提供程式碼)。注意線索化之後Thrt的右子樹指向的是二叉樹T最左端的節點,pre指向的是T最右端的節點且pre的RTag尚未賦值,pre的rchild並未指向任何位置。所以讓Thrt的右子樹指向pre節點,讓pre->Rtag=1,pre的右節點指向Thrt.最後返回Thrt的值作為樹的頭節點。

        以p為根節點的子樹中序線索化:

void InThreading(BiThrTree p)
{
	if (p)
	{
		InThreading(p->lchild);
		if (!p->lchild)
		{
			p->LTag = 1;
			p->rchild = pre;
		}
		else
			p->LTag = 0;
		if (!pre->rchild)
		{
			pre->RTag = 1;
			pre->rchild = p;
		}
		else
			pre->RTag = 0;
		pre = p;
		InThreading(p->rchild);
	}
}

        先判斷p子樹是否為空,如果不為空,利用遞迴對p的左子樹進行線索化。如果p的左子樹為空,則讓p->LTag為1,表示指向p的前驅,並且讓pre賦值給p的右子樹;如果不為空,則讓p->LTag為0,表示指向p的後繼。對pre進行同理操作。最後讓pre移動到p的位置,並利用遞迴對p的右子樹進行線索化。

        遍歷線索二叉樹:

void InOrderTraverse_Thr(BiThrTree T)
{
	BiThrTree p;
	p = T->lchild;
	while (p != T)
	{
		while (p->LTag == 0)
			p = p->lchild;
		printf("%c", p->data);
		while (p->RTag == 1 && p->rchild != T)
		{
			p = p->rchild;
			printf("%c", p->data);
		}
		p = p->rchild;
	}
	printf("\n");
}

        先宣告一個指標p,讓p指向T的左子樹。當p不為T的時候,則執行以下迴圈:當p->LTag等於0的時候,表示p的左子樹不為空,則一直迴圈讓p指向p的左子樹,讓p到達T最左端的葉子。輸出p的data資料。然後當p->Rtag等於1並且p的右子樹不等於T的時候表示p有後繼並p的右子樹指向其後繼,此時讓p移動到p的右子樹的位置,輸出p的data資料。讓p移動到p的右子樹位置。自此最外的迴圈結束。

        建立新二叉樹

BiThrNode *CreateBiTree(BiThrTree T)
{
	ElemType ch;
	scanf("%c", &ch);
	if (ch == '#')
		T = NULL;
	else
	{
		T = (BiThrNode *)malloc(sizeof(BiThrNode));
		T->data = ch;
		T->lchild = CreateBiTree(T->lchild);
		T->rchild = CreateBiTree(T->rchild);
	}
	return T;
}

        加入main()測試:
int main(void)
{
	BiThrTree T;
	int n;
	T = NULL;
	printf("1.建立二叉樹\n2.轉換為邏輯樹\n3.遍歷二叉樹(按邏輯結構)\n");
	while (1)
	{
		printf("請選擇:");
		scanf("%d", &n);
		fflush(stdin);
		switch (n)
		{
		case 1:
			T = CreateBiTree(T);
			break;
		case 2:
			T = InOrderThreading(T);
			break;
		case 3:
			InOrderTraverse_Thr(T);
		}
	}
	return 0;
}