线索化二叉树

 在二叉树中,有很多节点的指针域为空域,造成结点的浪费。针对这种现象,提出线索化二叉树这一概念,其基本思想是遵从中序遍历二叉树,将二叉树的空节点有效的利用起来。具体来说,是按照以下的步骤来实现的。

本文是利用中序遍历的思想对二叉树进行一个线索化:已知一颗二叉树如图所示:


如图1,是一颗普通的二叉树,一个节点有左右孩子和数据域。现在我们知道这个二叉树的中序遍历结果,如图2所示,然后按照中序遍历的结果,将这个二叉树线索化。


根据图2,我们能够清楚的看清每一个结点的前驱,每个结点的后继。而线索化二叉树所做的工作就是,将每一个结点的左孩子指向该结点的前驱,将每个结点的右孩子指向该结点的后继。那么,现在的工作就是具体来实现这个过程。首先,一个线索化二叉树的结点的数据结构是这个样子的:

typedef int ElemType;
typedef enum{LINK=0,THREAD=1} Tag;

typedef struct BiNode
{
	BiNode *left;
	BiNode *right;
	ElemType data;
	Tag taglef, tagright;
}BiNode, *BiTree;
然后,按照中序遍历的过程,找到最左边的孩子结点p,令p的左孩子指向一个提前定义的全局变量,并且,修改p的做孩子标志,表示已将其线索化。并且将pre修改为p,p指向p中序遍历的下一个。其中p的遍历顺序为DBGEHACF,pre永远为p的前一个。


按照图3,图4,一直到图5的顺序,实现了所有结点,除了最后一个结点的线索化,最后,再对最后一个结点进行一个线索化,二叉树中序线索化就完成了。以下是具体的实现代码,以及最终的实现界面:

#include<iostream>
using namespace std;

typedef int ElemType;
typedef enum{LINK=0,THREAD=1} Tag;

typedef struct BiNode
{
	BiNode *left;
	BiNode *right;
	ElemType data;
	Tag taglef, tagright;
}BiNode, *BiTree;

BiNode* BuyNode(ElemType dat)
{
	BiNode* newnode = new BiNode[1];
	newnode->data = dat;
	newnode->left = NULL;
	newnode->right = NULL;
	newnode->taglef = LINK;
	newnode->tagright = LINK;
	return newnode;
}

BiNode*  CreatePreorder(ElemType* &p)
{
	BiNode* root = NULL;
	
	if (*p < 0 )
	{
		return root;
	}
	else
	{
		root = BuyNode(*p); 
		if (root == NULL) return NULL;
		
		root->left = CreatePreorder(++p);
		root->right = CreatePreorder(++p);

		return root;
	}
}


void Inorder(BiNode* root)
{
	if (root)
	{
		Inorder(root->left);
		cout << root->data << "   ";
		Inorder(root->right);
	}
}
void Preorder(BiNode* root)
{
	if (root)
	{
		cout << root->data << "   ";
		Preorder(root->left);
		Preorder(root->right);
	}
}



void Pastorder(BiNode* root)
{
	if (root)
	{
		Pastorder(root->left);
		Pastorder(root->right);
		cout << root->data << "   ";
	}
}
void transform(BiNode* root, BiNode* &pre)
{
	if (root)
	{
		transform(root->left, pre);
		if (root->left == NULL)
		{
			root->left = pre;
			root->taglef = THREAD;
		}
		if (pre->right == NULL)
		{
			pre->right = root;
			pre -> tagright = THREAD;
		}
		pre = root;
		transform(root->right, pre);
	}
}

void ThreadBiTree(BiNode* root)
{
	if (root == NULL) return ;
	BiNode* pre =BuyNode(-1);
	transform(root, pre);
	BiNode* temp = root;
	while (temp->right != NULL)
	{
		temp = temp->right;
	}
	temp->tagright = THREAD;
	temp->right =NULL;
}

void InOrderThr(BiNode* root)
{
	if (root == NULL) return;
	BiNode* first = root;
	while (first->right!=NULL)
	{
		while (first->taglef != THREAD)
		{
			first = first->left;
		}
		cout << first->data << "  ";
		while (first->tagright == THREAD)
		{
			first = first->right;
			cout << first->data << "  ";
		}
		first = first->right;
	}
	cout << first->data << endl;
}

void main()
{
	int arr[] = { 12, 23,  45,-1,-1, 56, 67,-1,-1, 78, -1,-1,34,-1,89,-1,-1  };
	int len = sizeof(arr) / sizeof(arr[0]);                                                 
	BiTree root = NULL;
	int *p = arr;
	root = CreatePreorder(p);
	cout << "中序遍历二叉树"<<endl;
	Inorder(root);
	cout << endl;
	cout << "先序遍历二叉树" << endl;
	Preorder(root);
	cout << endl;
	cout << "后序遍历二叉树" << endl;
	Pastorder(root);
	ThreadBiTree(root);
	cout << endl;
	cout << "中序遍历线索化二叉树" << endl;
	InOrderThr(root);
}


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值