线索化二叉树的非递归遍历(用前驱结点和后继访问)

#pragma once
#include<iostream>
using namespace std;
enum PointTag
{
	THREAD,
	LINK
};
template<class T>
struct BinaryTreeNodeThd
{
	T _data;
	BinaryTreeNodeThd<T>* _left;
	BinaryTreeNodeThd<T>* _right;
	BinaryTreeNodeThd<T>* _parent;
	PointTag _leftTag;
	PointTag _rightTag;
	BinaryTreeNodeThd(const T& x)
		:_data(x)
		, _left(NULL)
		, _right(NULL)
		, _parent(NULL)
		, _leftTag(LINK)
		, _rightTag(LINK)
	{}
};
template<class T>
class BinaryTreeThd
{
protected:
	BinaryTreeNodeThd<T>* _CreateBinaryTree(T* a, size_t& index, const size_t size)
	{
		BinaryTreeNodeThd<T>* root = NULL;
		if (index < size&&a[index] != ‘#‘)
		{
			root = new BinaryTreeNodeThd<T>(a[index]);
			root->_left = _CreateBinaryTree(a, ++index, size);
			if (root->_left)
				root->_left->_parent = root;
			root->_right = _CreateBinaryTree(a, ++index, size);
			if (root->_right)
				root->_right->_parent = root;
		}
		return root;
	}
	void _Clear(BinaryTreeNodeThd<T>* root)
	{
		if (root)
		{
			if (root->_leftTag == LINK)
				_Clear(root->_left);
			if (root->_rightTag == LINK)
				_Clear(root->_right);
			delete root;
		}
	}
	void _InOrderThreading(BinaryTreeNodeThd<T>* cur, BinaryTreeNodeThd<T>*& 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 _PreOrderThreading(BinaryTreeNodeThd<T>* cur, BinaryTreeNodeThd<T>*& 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)
			_PreOrderThreading(cur->_left, prev);
		if (cur->_rightTag == LINK)
			_PreOrderThreading(cur->_right, prev);
	}
	void _PostOrderThreading(BinaryTreeNodeThd<T>* cur, BinaryTreeNodeThd<T>*& prev)
	{
		if (cur == NULL)
			return;
		_PostOrderThreading(cur->_left, prev);
		_PostOrderThreading(cur->_right, prev);
		if (cur&&cur->_left == NULL)
		{
			cur->_leftTag = THREAD;
			cur->_left = prev;
		}
		if (prev&&prev->_right == NULL)
		{
			prev->_rightTag = THREAD;
			prev->_right = cur;
		}
		prev = cur;
	}
public:
	BinaryTreeThd()
		:_root(NULL)
	{}
	BinaryTreeThd(T* a,size_t size)
	{
		size_t index = 0;
		_root=_CreateBinaryTree(a, index, size);
	}
	~BinaryTreeThd()
	{
		_Clear(_root);
		_root = NULL;
	}
	void  PreOrderThreading()
	{
		BinaryTreeNodeThd<T>* prev = NULL;
		_PreOrderThreading(_root, prev);
	}
	/*void PreOrderThd()
	{
		if (_root == NULL)
			return;
		BinaryTreeNodeThd<T>* cur = _root;

		while (cur)
		{

			cout << cur->_data << " ";
			while (cur&&cur->_leftTag != THREAD)
			{
				cur = cur->_left;
				cout << cur->_data << " ";
			}

			while (cur&&cur->_rightTag != LINK)
			{
				cur = cur->_right;
				cout << cur->_data << " ";
			}
			if (cur->_leftTag == LINK)
				cur = cur->_left;
			else
				cur = cur->_right;
		}
		cout << endl;
	}*/
	//优化版前序遍历,发现规律,注意观察
	void PreOrderThd()
	{
		if (_root == NULL)
			return;
		BinaryTreeNodeThd<T>*cur = _root;
		while (cur)
		{
			while (cur&&cur->_leftTag == LINK)
			{
				cout << cur->_data << " ";
				cur = cur->_left;
			}
			cout << cur->_data << " ";
			cur = cur->_right;
		}
		cout << endl;
	}
	void  InOrderThreading()
	{
		BinaryTreeNodeThd<T>* prev = NULL;
		_InOrderThreading(_root, prev);
	}
	void InOrderThd()
	{
		if (_root == NULL)
			return;
		BinaryTreeNodeThd<T>* cur = _root;
		while (cur)
		{
			while (cur&&cur->_leftTag != THREAD)
				cur = cur->_left;
			cout << cur->_data << " ";
			while (cur&&cur->_rightTag != LINK)
			{
				cur = cur->_right;
				cout << cur->_data << " ";
			}
			cur = cur->_right;
		}
		cout << endl;
	}
	void PostOrderThreading()
	{
		BinaryTreeNodeThd<T>* prev = NULL;
		_PostOrderThreading(_root, prev);
	}
	//重点
	void PostOrderThd()
	{
		if (_root == NULL)
			return;
		BinaryTreeNodeThd<T>* cur = _root->_left;
		BinaryTreeNodeThd<T>* prev = NULL;
		int flag = 0;
		while (cur != _root)
		{
			while (cur&&cur->_leftTag == LINK)
			{
				cur = cur->_left;
			}
			while (cur&&cur->_rightTag == THREAD)
			{
				cout << cur->_data << " ";
				prev = cur;
				cur = cur->_right;
 			}
			if (_root == cur)
			{
				cout << _root->_data << " ";
				prev = _root;
				break;
			}
			while(cur&&_root!=cur&&cur->_rightTag == LINK&&cur->_right == prev)
			{
				cout << cur->_data << " ";
				prev = cur;
				cur = cur->_parent;
			}
			if (cur == _root)
			{
				if (flag == 0)
					flag = 1;
				else
					break;
			}
			if (cur&&cur->_rightTag == LINK&&cur != prev)
				cur = cur->_right;
			else
			{
				cout << cur->_data << " ";
				prev = cur;
				cur = cur->_parent;
			}

		}
		if(prev!=_root)
			cout << _root->_data << " ";
		cout << endl;
	}
protected:
	BinaryTreeNodeThd<T>* _root;
};
void  Test3()
{
        //注意测试用例
	//int array[18] = { 1, 2, 3, 7, ‘#‘,‘#‘,‘#‘,4,8,‘#‘,‘#‘,9,‘#‘,‘#‘,5,6,‘#‘,10};

	int array[10] = { 1, 2, 3, ‘#‘, ‘#‘, 4, ‘#‘, ‘#‘, 5, 6 };
	//int array[15] = { 1, 2, ‘#‘, 3, ‘#‘, ‘#‘, 4, 5, ‘#‘, 6, ‘#‘, 7, ‘#‘, ‘#‘, 8 };
	BinaryTreeThd<int> b2(array, 10);
	/*b2.InOrderThreading();
	b2.InOrderThd();*/
    /*b2.PreOrderThreading();
	b2.PreOrderThd();*/
	b2.PostOrderThreading();
	b2.PostOrderThd();
}
int main()
{
	Test3();
	system("pause");
	return 0;
}
时间: 2024-11-12 04:44:05

线索化二叉树的非递归遍历(用前驱结点和后继访问)的相关文章

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

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

java实现线索化二叉树的前序、中序、后续的遍历(完整代码)

java实现线索化二叉树的前序.中序.后续的遍历 比如创建一个二叉树 1 / 3 6 / \ / 8 10 14 线索化二叉树几个概念: n个节点的二叉链表中含有n+1 [公式2n-(n-1)=n+1]个空指针域.利用二叉链表中的空指针域,存放指向该节点在某种遍历次序下的前驱和后继节点的指针(这种附加指针成为线索).如下面的就是6+1=7个空指针域 (8,10,14各有连个指针没有指向 6有一个) 加上了线索的二叉链表称为线索链表,相应的二叉树称为线索二叉树.分为前序线索二叉树.中序线索二叉树.

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

//二叉树的线索化 #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 *

线索化二叉树的构建与先序,中序遍历(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

JAVA递归实现线索化二叉树

JAVA递归实现线索化二叉树 基础理论 首先,二叉树递归遍历分为先序遍历.中序遍历和后序遍历. 先序遍历为:根节点+左子树+右子树 中序遍历为:左子树+根节点+右子树 后序遍历为:左子树+右子树+根节点 (只要记住根节点在哪里就是什么遍历,且都是先左再右) 线索化 现在有这么一棵二叉树,它的数据结构由左节点+权+右节点构成. 可以看到4,5,6,7这几个节点的左右节点空间被浪费了.因此,线索化是指有效利用这些空间. 中序遍历的顺序为:4 2 5 1 6 3 7 现在引入前驱节点以及后继节点. 前

遍历及线索化二叉树

①二叉树的遍历是指从根结点开始,按照某种次序依次访问二叉树中的所有结点 ②二叉树遍历方式(所谓前序.中序.后序,是对根结点来说的) 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

线索化二叉树

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