使用C++创建一个线索二叉树

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Coulson_Zhao/article/details/87970596

线索二叉树的结构

由于二叉树每次遍历的时候都会造成大量的时间消耗,因此创建一个线索二叉树就显得十分必要。
线索二叉树的结构如图所示:
在这里插入图片描述
在这里,我们可以发现线索二叉树的规则:
若结点p有左孩子,则p->lchild指向其左孩子结点,否则令其指向其(先序、中序、后序、层序)前驱;
若结点p有右孩子,则p->rchild指向其右孩子结点,否则令其指向其(先序、中序、后序、层序)后继;
那么我们要做的就是在左右孩子结点为空的时候准确找到该结点的前驱和后继。

线索二叉树的创建

首先,我们先创建一个正常的二叉树。

//输入顺序与#的输入要注意
void ini_BTree(Node &N)
{
	string elem;
	cin >> elem;
	if (elem == "#")
	{
		N = NULL;
	}
	else
	{
		N = new node;
		N->data = stoi(elem);
		N->ltag = true;
		N->rtag = true;
		ini_BTree(N->lchild);
		ini_BTree(N->rchild);
	}
}

之后,我们再通过中序遍历的方式创建一个中序线索二叉树。我们首先给出头节点,如上图所示,最左的左儿子指向它,最右的右儿子也指向它。
并且我们让这个头结点左儿子指向二叉树第一个结点;右儿子指向头结点自己。
在创建好头结点后,我们就需要将线索串联起来。在这里,我们需要创建一个全局变量的结点 pre,以便于得到中序遍历时的前驱元素。

//p在这里代表着头结点
void InOrderThreading(Node N, Node &p)
{
	p = new node;
	p->ltag = true;
	p->rtag = true;
	p->rchild = p;
	if (!N)
	{
		p->lchild = p;
	}
	else
	{
		p->lchild = N;
		pre = p;
		InThreading(N);
		pre->rchild = p;
		pre->rtag = false;
	}
}

void InThreading(Node N)
{
	if (N)
	{
		InThreading(N->lchild);
		if (!N->lchild)
		{
			N->lchild = pre;
			N->ltag = false;
		}
		if (!pre->rchild)
		{
			pre->rchild = N;
			pre->rtag = false;
		}
		pre = N;
		InThreading(N->rchild);
	}
}

函数的执行顺序为:
1.找到最左儿子H,令其指向头结点
2.判断pre右儿子是否为空,但由于目前pre指向头结点,不为空,因此不进入判断部分,并且pre重置为当前结点H
3.跳出第一层递归,Node N 目前代表着结点D,D的左儿子不为空,因此不进入判断部分;但D的右儿子为空,因此将pre(也就是H结点)的右儿子指向D,从而构成H的后继
4.重复以上步骤,直至所有线索完成(左数完成搞右数)

完整代码

#include "stdafx.h"
#include <iostream>
#include "string"

using namespace std;

typedef int Elemtype;
struct node
{
	Elemtype data;
	node* lchild;
	node* rchild;
	bool ltag;
	bool rtag;
};
typedef node* Node;

void ini_BTree(Node &N);
void InOrderThreading(Node N, Node &p);
void InThreading(Node N);
void Innext(Node N);
Node pre = NULL;

int main()
{
	Node n, p;
	n = new node;
	p = new node;
	pre = new node;
	pre->data = -1;
	ini_BTree(n);
	Innext(n);
	InOrderThreading(n, p);
	Innext(n);
	return 0;
}

//输入顺序与#的输入要注意
void ini_BTree(Node &N)
{
	string elem;
	cin >> elem;
	if (elem == "#")
	{
		N = NULL;
	}
	else
	{
		N = new node;
		N->data = stoi(elem);
		N->ltag = true;
		N->rtag = true;
		ini_BTree(N->lchild);
		ini_BTree(N->rchild);
	}
}

//p在这里代表着头结点
void InOrderThreading(Node N, Node &p)
{
	p = new node;
	p->ltag = true;
	p->rtag = true;
	p->rchild = p;
	if (!N)
	{
		p->lchild = p;
	}
	else
	{
		p->lchild = N;
		pre = p;
		InThreading(N);
		pre->rchild = p;
		pre->rtag = false;
	}
}

//线索的构建
void InThreading(Node N)
{
	if (N)
	{
		InThreading(N->lchild);
		if (!N->lchild)
		{
			N->lchild = pre;
			N->ltag = false;
		}
		if (!pre->rchild)
		{
			pre->rchild = N;
			pre->rtag = false;
		}
		pre = N;
		InThreading(N->rchild);
	}
}

void Innext(Node N)
{
	if (N != NULL)
	{
		Innext(N->lchild);
		cout << N->data << "and" << N->ltag << " ";
		Innext(N->rchild);
	}
}

猜你喜欢

转载自blog.csdn.net/Coulson_Zhao/article/details/87970596