C++实现线索化二叉树

当以二叉树作为存储结构时,只能找到节点的左右孩子信息,不能直接得到结点在任一序列中的前驱和后继信息,只有在遍历过程中才能得到这种信息。我们知道,在n个结点的二叉链表栈必定存在n+1个空链域,因此,可以利用这些空链域来存放这些结点信息。所以作如下规定:若结点右左子树,则其lchild域指向其左孩子,否则令lchild域指向其前驱;若结点有右子树,其rchild域指向其右孩子,否则指向其后继。以这种结构构成的二叉链表叫做线索链表。

前序线索化:

源代码:

#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;

enum PointerTag
{
	THREAD,
	LINK,
};

template <class T>
struct BinaryTreeNodeThd
{
	T _data;
	BinaryTreeNodeThd<T>*_left;
	BinaryTreeNodeThd<T>*_right;
	PointerTag _leftTag;
	PointerTag _rightTag;

	BinaryTreeNodeThd(const T&data)//线索化 :利用二叉树中指向左右子树的空指针来存放节点的前驱和后继信息
		:_data(data)
		, _left(NULL)
		, _right(NULL)
		, _leftTag(LINK)
		, _rightTag(LINK)
	{}

};

template <class T>
class BinaryTreeThd
{
	typedef BinaryTreeNodeThd<T>  Node;

private:
	Node* _root;
public:

	BinaryTreeThd()
		:_root(NULL)
	{}

	BinaryTreeThd(const T* a, size_t size,size_t index,const T& invalid)
	{

		_root = _CreateBinaryTreeThd(a, size, index, invalid);
	}

	//中序线索化
	void InorderThreading()
	{
	  Node* prev=NULL;
	  _InorderThreading(_root,prev);
	}

	//先序线索化
	void PrevtorderThreading()
	{
	Node* prev=NULL;
	_PrevorderThreading(_root,prev);
	}

	//中序线索化遍历
	void _InorderThd()
	{
		Node* cur=_root;
		while(cur)
		{
		//	访问最左边的叶子节点
	     while(cur->_leftTag ==LINK)
		 {
		 cur=cur->_left ;
		 }

		 cout<<cur->_data <<" ";

		 while(cur->_rightTag ==THREAD)
		 {
			cur=cur->_right ;
			cout<<cur->_data <<" ";
		 }
		 //访问右子树
		 cur=cur->_right ;
		}
	}

	//先序线索化遍历二叉树
	void _Prevorderthd( )
	{
	Node*cur=_root;
	if(cur==NULL)
	{
		return;
	}
	while(cur)
	{ //输出左边的节点
		while(cur->_leftTag ==LINK)
			{
			cout<<cur->_data <<" ";
			cur=cur->_left ;
			}
			cout<<cur->_data <<" ";
			//转移到右边的节点
			cur=cur->_right;

			/*while(cur->_rightTag ==THREAD )
			{
			cur=cur->_right ;
			cout<<cur->_data<<" " ;
			}*/
		}
	}
protected:
	//
	Node* _CreateBinaryTreeThd(const T*a, size_t size, size_t& index, const T& invalid)
	{
		Node* root=NULL;
		if(index<size&&a[index]!=invalid)
		{
			root=new Node(a[index]);
			root->_left = _CreateBinaryTreeThd(a,size,++index,invalid);
			root->_right =_CreateBinaryTreeThd(a,size,++index,invalid);
		}
		return root;
	}

	//中序线索化子树
	void _InorderThreading(Node* cur,Node*& prev)
	{
		if(cur==NULL)
		{
		 return;
		}
		//递归遍历左子树
		_InorderThreading(cur->_left ,prev);
		if(cur->_left ==NULL)
		{
		 cur->_leftTag =THREAD;
		 cur->_left =prev;
		}
		if(prev&&prev->_right ==NULL)
		{
		prev->_rightTag =THREAD ;
		prev->_right =cur;
		}
		prev=cur;
		//递归遍历右子树
		_InorderThreading(cur->_right ,prev);
	}

	//先序线索化子树
	void _PrevorderThreading(Node* cur,Node*& prev)
	{
	 if(cur==NULL)
		 return;
	 //置前线索化
	 if(cur->_left ==NULL)
	 {
		 cur->_leftTag =THREAD ;
		 cur->_left =prev;
	 }
	 //置后线索化
	 if(prev&&prev->_right ==NULL)
	 {
	 prev->_rightTag =THREAD;
	 prev->_right =cur;
	 }

	 prev=cur;

	 if(cur->_leftTag ==LINK)
	 {
		 _PrevorderThreading(cur->_left ,prev);
	 }

	  if(cur->_rightTag ==LINK)
	 {
		_PrevorderThreading(cur->_right ,prev);
	 }

	}
};

测试代码:

void test()
{
	int a1[10]={1,2,3,‘#‘,‘#‘,4,‘#‘,‘#‘,5,6};
	int a2[15]={1,2,‘#‘,3,‘#‘,‘#‘,4,5,‘#‘,6,‘#‘,7,‘#‘,‘#‘,8};
	BinaryTreeThd<int>btt1(a1,10,0,‘#‘);
	BinaryTreeThd<int>btt2(a2,15,0,‘#‘);
	cout<<"中序线索化遍历二叉树:";
	btt1.InorderThreading ();
	btt1._InorderThd();
	cout<<endl;
	btt2.InorderThreading ();
	btt2._InorderThd();
	cout<<endl;
	cout<<"先序线索化遍历二叉树:";
	btt1.PrevtorderThreading();
	btt1. _Prevorderthd();
	cout<<endl;
	btt2.PrevtorderThreading();
	btt2. _Prevorderthd();
	cout<<endl;
}
时间: 2025-01-02 03:44:31

C++实现线索化二叉树的相关文章

线索化二叉树

二叉树的遍历运算是将二叉树中节点按一定规律线性化的过程,当二叉链表作为存储结构时,只能找到节点的左.右孩子信息,而不能直接得到节点在遍历序列中的前驱和后继信息.线索化二叉树能够解决这样的问题,将二叉链表中的空指针域填上相应节点的遍历前驱或后继节点的地址,而前驱和后继的地址只能在动态的遍历过程中才能得到.可以按照不同的遍历次序进行线索化,先序遍历.遍历过程中的节点的前驱.后继信息保存下来.下面是线索化二叉树节点结构: 其中,_left和_right表示节点的左.右孩子,_leftTag和_righ

中序线索化二叉树

中序线索化二叉树 1 void Tree::_inTree(Node * root, Node * &pre) { 2 if (root == NULL) { // 结点为空, 1:二叉树为空 2:已到达右子树的最后一个右结点的 rchild 3 return; 4 } 5 _inTree(root->lchild, pre); // 到达当前结点的左子树的底部左结点 6 if (root->lchild == NULL) { 7 root->ltag = nChild; //

数据结构 树的创建(线索化二叉树)

//二叉树的线索化 #include<stdio.h> #include<stdlib.h> #include<string.h> //定义二叉树线索化节点 typedef struct _TreeNode{ char data; char lefttag;//0表示没有线索化,1表示线索化---每次创建节点都会初始化 所以所有节点默认都是0 char righttag; struct _TreeNode * leftchild; struct _TreeNode *

数据结构例程——线索化二叉树(中序)

本文是数据结构基础系列(6):树和二叉树中第14课时线索二叉树的例程. #include <stdio.h> #include <malloc.h> #define MaxSize 100 typedef char ElemType; typedef struct node { ElemType data; int ltag,rtag; //增加的线索标记 struct node *lchild; struct node *rchild; } TBTNode; void Creat

线索化二叉树的构建与先序,中序遍历(C++版)

贴出学习C++数据结构线索化二叉树的过程, 方便和我一样的新手进行测试和学习 同时欢迎各位大神纠正. 不同与普通二叉树的地方会用背景色填充 //BinTreeNode_Thr.h 1 enum PointTag 2 {Link,Thread}; 3 4 template<typename ElemType> 5 struct BinTreeNode 6 { 7 ElemType data; //数据元素 8 PointTag LTag,RTag; //左标志,右标志 9 BinTreeNode

树五:线索化二叉树

线索化二叉树: 线索化二叉树指的是将二叉树中的结点进行逻辑意义上的“重排列”,使其可以线性的方式访问每一个结点. 二叉树线索化后每个结点都有一个线性下标,通过这个下标可以快速访问结点,而不需要遍历二叉树.

【数据结构】线索化二叉树中序线索化的递归写法和非递归写法

二叉树是一种非线性结构,遍历二叉树几乎都是通过递归或者用栈辅助实现非递归的遍历.用二叉树作为存储结构时,取到一个节点,只能获取节点的左孩子和右孩子,不能直接得到节点的任一遍历序列的前驱或者后继. 为了保存这种在遍历中需要的信息,我们利用二叉树中指向左右子树的空指针来存放节点的前驱和后继信息.所以引入了线索化二叉树.下面我们讲一下线索化二叉树中序线索化的两种实现方法: (1).递归实现中序线索化二叉树 首先我们先看一下线索化二叉树的结构 enum PointerTag{ THREAD, LINK 

遍历及线索化二叉树

①二叉树的遍历是指从根结点开始,按照某种次序依次访问二叉树中的所有结点 ②二叉树遍历方式(所谓前序.中序.后序,是对根结点来说的) 1.前序遍历 2.中序遍历 3.后续遍历 4.层次遍历 前序遍历:1.2.4.8.9.5.10.3.6.7 中序遍历:8.4.9.2.10.5.1.6.3.7 后序遍历:8.9.4.10.5.2.6.7.3.1 层次遍历:1.2.3.4.5.6.7.8.9.10 ③线索化二叉树指的是将二叉树中的结点进行逻辑意义上的"重排列",使其可以以线性的方式访问每一个

数据结构与算法---线索化二叉树(Threaded BinaryTree)

先看一个问题 将数列 {1, 3, 6, 8, 10, 14  } 构建成一颗二叉树 问题分析: 当我们对上面的二叉树进行中序遍历时,数列为 {8, 3, 10, 1, 6, 14 } 但是 6, 8, 10, 14 这几个节点的 左右指针,并没有完全的利用上. 如果我们希望充分的利用 各个节点的左右指针, 让各个节点可以指向自己的前后节点,怎么办? 解决方案-线索二叉树 线索二叉树基本介绍 1.n个结点的二叉链表中含有n+1  [公式 2n-(n-1)=n+1] 个空指针域.利用二叉链表中的空

数据--第37课 - 线索化二叉树

第37课 - 线索化二叉树 1. 问题 在一些项目中需要频繁的遍历二叉树,但是二叉树的遍历比单链表的遍历复杂多了,并且递归总是会后额外的开销. 2. 线索化二叉树 线索化二叉树指的是将二叉树中的结点进行逻辑意义上的“重新排列”,使其可以线性的方式访问每一个结点. 二叉树线索化后每个结点都有一个线性下标,用过这个下标可以快速访问结点,而不需要遍历二叉树. 3. 方法1 利用结点中的空指针,使其指向后继结点. 算法思想: 初始化位置指针:p = NULL: 前序遍历二叉树: 若p不为空,将p->le