1. 程式人生 > >資料結構-------------線索二叉樹(c語言)

資料結構-------------線索二叉樹(c語言)

一、線索二叉樹

如果二叉樹的節點包含資料域和兩個指標域( lchild 和 rchild ),當節點沒有下一個節點時,將指標域賦值為空(NULL),但有時會造成很大的浪費,所以可以將空指標域利用起來,存放其他節點的地址,這樣就便於索引,像二叉樹遍歷,查詢之類就會變得相對容易。


像上面的二叉樹就會造成很大的浪費。當該二叉樹以中序遍歷輸出時,為FDGBACE, 紅色表示有兩個指標域可以利用,藍色表示有一個指標域可以利用,而黑色表示沒有多餘的指標域可以利用,若果將一個節點的lchild(如果可以使用)指向它前一個節rchlid(如果可以使用)指向它的後一個節點(這裡的前後是針對於FDGBACE這個序列而言的)。而假若在最前面增加一個頭結點,資料域為data,那麼會更加便捷。最終它們的指向會變為:


這樣的對於中序遍歷二叉樹就會變得很容易。

然而,機器怎麼判斷一個節點到底有多少個指標域可以使用呢?這樣就需要一個標誌,指示該節點的兩個指標域是否可以被利用,於是,我們把節點擴容,變為:


ltag為0時指向該結點的左孩子,為1時指向該結點的前驅。rtag為0時指向該結點的右孩子,為1時指向該結點的後繼。

這樣就能分別指示左右指標域是否可以利用。雖然犧牲了一點空間,但換來的是效率的提高。

二、程式碼實現

#include <stdio.h>
#include <stdlib.h>

typedef char ElemType;

// 線索儲存標誌位
// Link(0):表示指向左右孩子的指標
// Thread(1):表示指向前驅後繼的線索
typedef enum {Link, Thread} PointerTag;

typedef struct BiThrNode
{
	char data;
	struct BiThrNode *lchild, *rchild;
	PointerTag ltag;
	PointerTag rtag;
} BiThrNode, *BiThrTree;

// 全域性變數,始終指向剛剛訪問過的結點
BiThrTree pre;

// 建立一棵二叉樹,約定使用者遵照前序遍歷的方式輸入資料
void CreateBiThrTree( BiThrTree *T )
{
	char c;

	scanf("%c", &c);
	if( ' ' == c )
	{
		*T = NULL;
	}
	else
	{
		*T = (BiThrNode *)malloc(sizeof(BiThrNode));
		(*T)->data = c;
		(*T)->ltag = Link;
		(*T)->rtag = Link;

		CreateBiThrTree(&(*T)->lchild);
		CreateBiThrTree(&(*T)->rchild);
	}
}

// 中序遍歷線索化
void InThreading(BiThrTree T)
{
	if( T )
	{
		InThreading( T->lchild );		// 遞迴左孩子線索化

		if( !T->lchild )	// 如果該結點沒有左孩子,設定ltag為Thread,並把lchild指向剛剛訪問的結點。
		{
			T->ltag = Thread;
			T->lchild = pre;
		}

		if( !pre->rchild )
		{
			pre->rtag = Thread;
			pre->rchild = T;
		}

		pre = T;

		InThreading( T->rchild );		// 遞迴右孩子線索化
	}
}

void InOrderThreading( BiThrTree *p, BiThrTree T )
{
	*p = (BiThrTree)malloc(sizeof(BiThrNode));
	(*p)->ltag = Link;
	(*p)->rtag = Thread;
	(*p)->rchild = *p;
	if( !T )
	{
		(*p)->lchild = *p;
	}
	else
	{
		(*p)->lchild = T;
		pre = *p;
		InThreading(T);
		pre->rchild = *p;
		pre->rtag = Thread;
		(*p)->rchild = pre;
	}
}

void visit( char c )
{
	printf("%c", c);
}

// 中序遍歷二叉樹,非遞迴
void InOrderTraverse( BiThrTree T )
{
	BiThrTree p;
	p = T->lchild;

	while( p != T )
	{
		while( p->ltag == Link )
		{
			p = p->lchild;
		}
		visit(p->data);

		while( p->rtag == Thread && p->rchild != T )
		{
			p = p->rchild;
			visit(p->data);
		}
		
		p = p->rchild;
	}
}

int main()
{
	BiThrTree P, T = NULL;

	CreateBiThrTree( &T );

	InOrderThreading( &P, T );

	printf("中序遍歷輸出結果為: ");

	InOrderTraverse( P );

	printf("\n");

	return 0;
}

三、效果展示