線索二叉樹【定義、應用、線索化、遍歷】

聽聞__發表於2018-04-19
1、定義
對於具有n個節點的二叉樹,採用二叉鏈儲存結構時,每個節點有兩個指標域,總共有2n個指標域,又由於只有n-1個節點被有效指標所指向,則共有2n-(n-1)=n+1個空鏈域。
空的左孩子指標指向該結點的前驅;空的右孩子指標指向該結點的後繼。這種附加的指標值稱為線索,帶線索的二叉樹稱為線索二叉樹。 
在不同的遍歷次序下,二叉樹中的每個結點一般有不同的前驅和後繼。因此,線索二叉樹又分為前序線索二叉樹中序線索二叉樹後序線索二叉樹3種。 
根據二叉樹的特性,n個結點的二叉樹,採用鏈式儲存結構時,有n+1個空鏈域,可以利用這些空鏈域存放指向結點的直接前驅和直接後繼結點的指標。為此做如下規定:當結點的左指標為空(即無左子樹)時,令該指標指向按某種方式遍歷二叉樹時得到的該結點的前驅結點;當結點的右指標為空(即無右子樹)時,令該指標指向按某種方式遍歷二叉樹時得到的該結點的後繼結點;為了避免混淆,還需要增加兩個標誌位來區分指標指向的是其孩子還是前驅及後繼。
2、應用
線索二叉樹能很快速地求出二叉樹節點的前驅節點和後繼節點,演算法的複雜度為O(n),雖然普通二叉樹遍歷求前驅和後繼節點複雜度也是O(n),但線索二叉樹的常數因子更小,求前驅和後繼節點比普通二叉樹遍歷更快。
注:先序線索二叉樹查詢後繼節點容易、查詢前驅節點困難;後序線索二叉樹查詢前驅節點容易、查詢後繼節點困難;而中序線索二叉樹查詢後繼節點和先驅節點都很容易。因此,先序和後序線索二叉樹應用較少,中序線索二叉樹應用更加廣泛。
3、線索化

        由於中序線索二叉樹的應用更加廣泛,而前序和後序應用較少,所以這裡只介紹中序序列二叉樹的線索化。

(1)以*b為當前節點,以*pre為直接前驅節點進行二叉樹的中序線索化

//create the thread binary tree
void ThreadBTNode_InOrder(BTNode* b, BTNode* &pre)
{
	if (b == NULL) return;
	//1.thread the left child node first
	ThreadBTNode_InOrder(b->left, pre);
	//2.then thread the self node
	if (b->left == NULL)
	{
		b->left = pre;
		b->lTag = 1;
	}
	else
		b->lTag = 0;
	if (pre->right == NULL)
	{
		pre->right = b;
		pre->rTag = 1;
	}
	else
		pre->rTag = 0;
	//update the pre node
	pre = b;
	//3.last thread the right child
	ThreadBTNode_InOrder(b->right, pre);
}
(2)將一顆二叉鏈儲存的二叉樹b進行中序線索化,返回附加線索化二叉樹的根節點
//create the thread binary tree, returns the root node
BTNode* CreateThreadBTNode_InOrder(BTNode* b)
{
	BTNode* root = new BTNode;
	root->data = '#';
	root->lTag = 0;
	root->left = b;
	root->right = NULL;
	BTNode* p = root;
	ThreadBTNode_InOrder(b, p);
	p->rTag == 1;
	p->right = root;
	return root;
}


4、遍歷

(1)求線索二叉樹的直接前驅

//get the pre node
BTNode* GetPreThreadBTNode_InOrder(BTNode* b)
{
	if (b->lTag == 0)
	{
		BTNode* p = b->left;
		while (p->rTag == 0)
			p = p->right;
		return p;
	}
	return b->left;
}

(2)求線索二叉樹的直接後繼

//get the next node
BTNode* GetNextThreadBTNode_InOrder(BTNode* b)
{
	if (b->rTag == 0)
	{
		BTNode* p = b->right;
		while (p->lTag == 0)
			p = p->left;
		return p;
	}
	return b->right;
}

(3)遍歷所有節點
//thread order to display a thread binary tree
void ThreadOrder(BTNode* root)
{
	BTNode* p = GetNextThreadBTNode_InOrder(root);
	while (p != NULL && p != root)
	{
		cout << p->data << ", ";
		p = GetNextThreadBTNode_InOrder(p);
	}
	cout << endl;
}


5、測試
#include <iostream>
using namespace std;

typedef char ElemType;

//declare the binary tree
typedef struct BTNode
{
	ElemType data;
	int lTag, rTag;
	BTNode *left, *right;
}BTNode;

//create binary tree by pre order and in order
BTNode* CreateBTByPreAndIn(ElemType* pre, ElemType* in, int n)
{
	if (n <= 0) return NULL;
	BTNode* b = new BTNode;
	b->data = *pre;
	int k;
	for (ElemType* p = in; p < in + n; p++)
	{
		if (*p == *pre)
		{
			k = p - in;
			break;
		}
	}
	b->left = CreateBTByPreAndIn(pre + 1, in, k);
	b->right = CreateBTByPreAndIn(pre + 1 + k, in + 1 + k, n - k - 1);
	return b;
}

//create the thread binary tree
void ThreadBTNode_InOrder(BTNode* b, BTNode* &pre)
{
	if (b == NULL) return;
	//1.thread the left child node first
	ThreadBTNode_InOrder(b->left, pre);
	//2.then thread the self node
	if (b->left == NULL)
	{
		b->left = pre;
		b->lTag = 1;
	}
	else
		b->lTag = 0;
	if (pre->right == NULL)
	{
		pre->right = b;
		pre->rTag = 1;
	}
	else
		pre->rTag = 0;
	//update the pre node
	pre = b;
	//3.last thread the right child
	ThreadBTNode_InOrder(b->right, pre);
}

//create the thread binary tree, returns the root node
BTNode* CreateThreadBTNode_InOrder(BTNode* b)
{
	BTNode* root = new BTNode;
	root->data = '#';
	root->lTag = 0;
	root->left = b;
	root->right = NULL;
	BTNode* p = root;
	ThreadBTNode_InOrder(b, p);
	p->rTag == 1;
	p->right = root;
	return root;
}

//get the pre node
BTNode* GetPreThreadBTNode_InOrder(BTNode* b)
{
	if (b->lTag == 0)
	{
		BTNode* p = b->left;
		while (p->rTag == 0)
			p = p->right;
		return p;
	}
	return b->left;
}

//get the next node
BTNode* GetNextThreadBTNode_InOrder(BTNode* b)
{
	if (b->rTag == 0)
	{
		BTNode* p = b->right;
		while (p->lTag == 0)
			p = p->left;
		return p;
	}
	return b->right;
}

//thread order to display a thread binary tree
void ThreadOrder(BTNode* root)
{
	BTNode* p = GetNextThreadBTNode_InOrder(root);
	while (p != NULL && p != root)
	{
		cout << p->data << ", ";
		p = GetNextThreadBTNode_InOrder(p);
	}
	cout << endl;
}

int main()
{
	//create binary tree by pre order and in order
	const char* pre = "ABDGCEF";
	const char* in = "DGBAECF";
	BTNode* b = CreateBTByPreAndIn(const_cast<ElemType*>(pre),
		const_cast<ElemType*>(in), strlen(pre));
	//create and display thread binary tree
	ThreadOrder(CreateThreadBTNode_InOrder(b));
	system("pause");
	return 0;
}

相關文章