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

線索二叉樹的實現

線索二叉樹的作用是為了加快查詢結點的前驅和後繼的速度
線索二叉樹實現的是利用每個結點的空指標(如果有)指向左子樹指標指向前一個結點(中序遍歷順序,下同)右子樹指向後繼結點,但是要新增兩個方向指標

LTag, RTag,如果LTag = 0,則表示該節點有左孩子,等於1則表示指標為空指向可以指向前驅結點, RTag = 0,則表示該節點有右孩子,等於1則表示指標為空指向可以指向後繼結點



#include <iostream>
using namespace std;

#define Elemtype char

typedef enum PointerTag
{
	Link, Thread
};

typedef struct BiThrNode
{
	Elemtype data;
	struct BiThrNode *lchild, *rchild;
	PointerTag LTag, RTag;
}BiThrNode,*BiThrTree;

BiThrTree Pre = NULL;//全域性變數始終指向剛剛經過的結點;

void CreateTree(BiThrTree *T)//先序的方法創造二叉樹
{
	char ch;
	scanf_s("%c",&ch);

	if (' ' == ch)
	{
		(*T) = NULL;
	}
	else
	{
		(*T) = new BiThrNode;
		(*T)->data = ch;
		(*T)->LTag = Link;
		(*T)->RTag = Link;
		CreateTree(&(*T)->lchild);
		CreateTree(&(*T)->rchild);
	}
	
}

void InThreading(BiThrTree p)//中序遍歷線索化
{
	if (p)
	{
		InThreading(p->lchild);//左子樹線索化
		
		if (!p->lchild)//如果p的左子樹為空即將LTag設定成1,將lchild指向剛剛訪問的結點
		{
			p->LTag = Thread;
			p->lchild = Pre;//左子樹指向前驅
		}
		if (!Pre->rchild)//如果p的右子樹為空即將LTag設定成1,表明下一個結點是他的後繼
		{
			Pre->RTag = Thread;
			Pre->rchild = p;//右子樹指向後繼
		}
		Pre = p;//保持pre指向p的前驅

		InThreading(p->rchild);//線索化右子樹
	}

}

void InOrderThreading(BiThrTree *Thrt, BiThrTree T)
{
	*Thrt = new BiThrNode;//設定一個頭結點
	(*Thrt)->LTag = Link;//頭結點的左標誌設定成Link證明他有左子樹
	(*Thrt)->RTag = Thread;//頭結點的右標誌設定成thread證明他有後繼結點
	(*Thrt)->rchild = *Thrt;//開始先讓他的右子樹指向自己

	if (!T)//若果二叉樹是空樹就讓頭結點的左子樹指向頭結點
	{
		(*Thrt)->lchild = *Thrt;
	}
	else
	{
		(*Thrt)->lchild = T;//如果樹不為空,頭結點的左子樹指向樹的根
		Pre = *Thrt;//pre指向頭結點
		InThreading(T);//開始中序線索化二叉樹
		Pre->rchild = *Thrt;//收尾工作,讓二叉樹中序遍歷的最後一個結點的右子樹指向頭結點
		Pre->RTag = Thread;//
		(*Thrt)->rchild = Pre;//讓頭結點的右子樹指向前一個結點也就是二叉樹中序遍歷的最後一個結點
	}

}

void InOrderTraverse(BiThrTree Thrt)//中序遍歷線索化二叉樹,非遞迴
{
	BiThrTree p;
	p = Thrt->lchild;//讓p 指向樹的根結點

	
	while (p != Thrt)//如果P不等於頭結點說明二叉樹非空,或者p還沒有指向頭結點
	{
		while (p->LTag == Link)//如果p->LTag == Link說明p一直有右子樹,這個操作是為了找出最左邊的結點
		{
			p = p->lchild;
		}

		cout << p->data << " ";//輸出結點

		while (p->RTag == Thread && p->rchild != Thrt)//p->RTag == Thread && p->rchild != Thrt如果p有後繼結點,並且p的右子樹還沒有指向頭結點,就一直按照線索遍歷
		{
			p = p->rchild;
			cout << p->data << " ";
		}

		p = p->rchild;//收尾工作將P再次指向頭結點
	}
}

int main()
{
	char ch;
	BiThrTree T, Thrt;
	CreateTree(&T);
	InOrderThreading(&Thrt, T);
	InOrderTraverse(Thrt);
	system("pause");
	return 0;
}

演示結果: