二叉树的前序、中序和后序线索化

二叉树是一种非线性结构,遍历二叉树需要通过递归或者用栈辅助实现非递归的遍历。

用二叉树作为压缩存储结构时,取到一个结点,只能获取节点的左孩子和右孩子,不能直接得到结点的任一遍历序列的前驱或者后继。为了实现这种遍历,偶们利用二叉树中指向左右子树的空指针来存放结点的前驱和后继。

线索化二叉树思路:

当某一结点的左结点或结右点存在NULL时,则该结点的为空的子结点需要线索化。

在进行线索化时,结点的前驱指向前一个访问过的结点,故定义一个指针prev来保存前一个结点;结点的后继偶们并不知道,则对于未来的事情并不知道,偶们可以在未来对该结点的后继进行线索化,使prev的后继指向cur。

前序遍历二叉树------根->左->右(1,2,3,4,5,6)

template<class T>
void BinaryTreeThd<T>::PrevOrderTag()//前序线索化二叉树
{
	Node* prev = NULL;
	_PrevOrderTag(_root, prev);
}
template<class T>
void BinaryTreeThd<T>::_PrevOrderTag(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)//线索化左结点
	{
		_PrevOrderTag(cur->_left, prev);
	}
	if (cur->_rightTag == LINK)//线索化右结点
	{
		_PrevOrderTag(cur->_right, prev);
	}
}

中序遍历二叉树------左->根->右(3,2,4,1,6,5)

递归实现:

template<class T>
void BinaryTreeThd<T>::InOrderTag()//中序线索化二叉树
{
	//递归实现中序线索化
	Node* prev = NULL;//线索化的前一个结点
	_InOrederTag(_root, prev);
}
template<class T>
void BinaryTreeThd<T>::_InOrederTag(Node* cur,Node*& prev)//中序线索化二叉树
{
	if (cur == NULL)
	{
		return;
	}
	_InOrederTag(cur->_left, prev);//递归出cur->_left为空
	if (cur->_left == NULL)
	{
		cur->_leftTag = THREAD;
		cur->_left = prev;//当前结点的前驱指向前一个结点
	}
	//对先前的结点后继进行线索化,在cur指向下一个结点即后继时,将先前节点的后继指向cur
	//到未来的结点进行先前结点后继的线索化
	if (prev && prev->_right == NULL)
	{
		cur->_rightTag = THREAD;
		prev->_right = cur;
	}
	prev = cur;
	_InOrederTag(cur->_right, prev);//递归出cur->_right为空
}

非递归实现(利用栈):

template<class T>
void BinaryTreeThd<T>::InOrderTag_NonR()//中序线索化二叉树--非递归
{
	//栈实现中序线索化
	stack<Node*> s;
	Node* prev = NULL;
	Node* cur = _root;
	if (cur == NULL)
	{
		return;
	}
	while (cur || !s.empty())
	{
		while(cur)//找到最左结点,入栈
		{
			s.push(cur);
			cur = cur->_left;
		}//cur不为空进栈,cur为空说明cur已经线索化了
		cur = s.top();//循环进入使cur为栈顶元素并判断是否需要线索化
		if (cur->_left == NULL)
		{
			cur->_leftTag = THREAD;
			cur->_left = prev;
		}
		s.pop();//弹出栈顶元素,使栈顶保存需要线索化的cur的后继
		prev = cur;
		if (cur->_right == NULL && !s.empty())
		{
			cur->_rightTag = THREAD;
			cur->_right = s.top();
			cur = NULL;//设置cur为空,防止死循环(2)
		}
		else
		{
			cur = cur->_right;//线索化跳到右子树进行
		}
	}
}

后序遍历二叉树------左->右->根(3,4,2,6,5,1)

template<class T>
void BinaryTreeThd<T>::PastOrderTag()//后序线索化二叉树
{
	Node* prev = NULL;
	_PastOrderTag(_root, prev);
}
template<class T>
void BinaryTreeThd<T>::_PastOrderTag(Node* cur, Node*& prev)//后序线索化二叉树
{
	if (cur == NULL)
	{
		return;
	}
	_PastOrderTag(cur->_left, prev);//最左结点
	_PastOrderTag(cur->_right, prev);//最右结点
	if (cur->_left == NULL)//线索化前驱
	{
		cur->_leftTag = THREAD;
		cur->_left = prev;
	}
	if (prev && prev->_right == NULL)//线索化后继
	{
		prev->_rightTag = THREAD;
		prev->_right = cur;
	}
	prev = cur;
}
时间: 2024-11-08 12:24:36

二叉树的前序、中序和后序线索化的相关文章

中序与后序或者前序都可以确定一颗二叉树 一点点dfs

中序与后序或者前序都可以确定一颗二叉树原理:  中序是 访问顺序是左子树 根 右子树 后续是 左子树 右子树 根 所以一棵二叉树如果给了后续的信息 可以把树根确定下来 带入中序的信息中 找出左右子树 再带回后续的信息找这样反复,也就是递归下去,可以把树给确定下来. DFS  大概可以用于 又要向下延伸 又要左右延伸  比如 枚举 ,搜索 都可以用:

【基础备忘】 二叉树前序、中序、后序遍历相互求法

转自:http://www.cnblogs.com/fzhe/archive/2013/01/07/2849040.html 今天来总结下二叉树前序.中序.后序遍历相互求法,即如果知道两个的遍历,如何求第三种遍历方法,比较笨的方法是画出来二叉树,然后根据各种遍历不同的特性来求,也可以编程求出,下面我们分别说明. 首先,我们看看前序.中序.后序遍历的特性: 前序遍历:     1.访问根节点     2.前序遍历左子树     3.前序遍历右子树 中序遍历:     1.中序遍历左子树     2

树(二叉树)的建立和遍历算法(一)(前序,中序,后序)

最近学习树的概念,有关二叉树的实现算法记录下来... 不过学习之前要了解的预备知识:树的概念:二叉树的存储结构:二叉树的遍历方法.. 二叉树的存储结构主要了解二叉链表结构,也就是一个数据域,两个指针域,(分别为指向左右孩子的指针),从下面程序1,二叉树的存储结构可以看出. 二叉树的遍历方法:主要有前序遍历,中序遍历,后序遍历,层序遍历.(层序遍历下一篇再讲,本篇主要讲的递归法) 如这样一个二叉树: 它的前序遍历顺序为:ABDGHCEIF(规则是先是根结点,再前序遍历左子树,再前序遍历右子树) 它

二叉树各种相关操作(建立二叉树、前序、中序、后序、求二叉树的深度、查找二叉树节点,层次遍历二叉树等)(C语言版)

将二叉树相关的操作集中在一个实例里,有助于理解有关二叉树的相关操作: 1.定义树的结构体: 1 typedef struct TreeNode{ 2 int data; 3 struct TreeNode *left; 4 struct TreeNode *right; 5 }TreeNode; 2.创建根节点: 1 TreeNode *creatRoot(){ 2 TreeNode * root =(TreeNode *)malloc(sizeof(TreeNode)); 3 if(NULL=

二叉树的前序、中序、后序遍历的递归和非递归算法实现

1 /** 2 * 二叉树的前序.中序.后序遍历的递归和非递归算法实现 3 **/ 4 5 //二叉链表存储 6 struct BTNode 7 { 8 struct BTNode *LChild; // 指向左孩子指针 9 ELEMENTTYPE data; // 结点数据 10 struct BTNode *RChild; // 指向右孩子指针 11 }; 12 13 /** 14 * 前序遍历 15 **/ 16 // 递归实现 17 void PreorderTraversal(BTNo

二叉树前序、中序、后序遍历相互求法

今天来总结下二叉树前序.中序.后序遍历相互求法,即如果知道两个的遍历,如何求第三种遍历方法,比较笨的方法是画出来二叉树,然后根据各种遍历不同的特性来求,也可以编程求出,下面我们分别说明. 首先,我们看看前序.中序.后序遍历的特性: 前序遍历:     1.访问根节点     2.前序遍历左子树     3.前序遍历右子树 中序遍历:     1.中序遍历左子树     2.访问根节点     3.中序遍历右子树 后序遍历:     1.后序遍历左子树     2.后序遍历右子树     3.访问

二叉树遍历(前序、中序、后序、层次、深度优先、广度优先遍历)

二叉树是一种非常重要的数据结构,很多其它数据结构都是基于二叉树的基础演变而来的.对于二叉树,有深度遍历和广度遍历,深度遍历有前序.中序以及后序三种遍历方法,广度遍历即我们平常所说的层次遍历.因为树的定义本身就是递归定义,因此采用递归的方法去实现树的三种遍历不仅容易理解而且代码很简洁,而对于广度遍历来说,需要其他数据结构的支撑,比如堆了.所以,对于一段代码来说,可读性有时候要比代码本身的效率要重要的多. 四种主要的遍历思想为: 前序遍历:根结点 ---> 左子树 ---> 右子树 中序遍历:左子

关于二叉树的问题1-已知前序,中序求后序遍历

对于一棵二叉树而言,可以由其前序和中序或者中序和后序的遍历序列,确定一棵二叉树. 那么对于已知前序和中序序列,求后序序列也就是先还原二叉树,然后对其进行后序遍历即可. 二叉树结点的结构定义如下: struct TreeNode { char value; TreeNode *leftChild; TreeNode *rightChild; }; 实现代码如下: #include <stdio.h> #include <string.h> #include <stdlib.h&

二叉树基本操作:前序、中序、后序遍历(递归方式)

二叉树是最常见最重要的数据结构之一,它的定义如下: 二叉树(binary tree)是有限多个节点的集合,这个结合或者是空集,或者由一个根节点和两颗互不相交的.分别称为左子树和右子树的二叉树组成. 二叉树最基本的操作是遍历:一般约定遍历时左节点优先于右节点,这样根据根节点的遍历顺序可分为三种遍历操作:前序-先遍历根节点,再处理左右节点:中序-先遍历左节点,然后处理根节点,最后处理右节点:后序-先遍历左右节点,然后处理根节点. 从上边二叉树定义可以看出:二叉树使用了递归的概念描述.所以,二叉树的很

二叉树的前序中序后序遍历相互求法

二叉树的前中后序遍历,他们的递归非递归.还有广度遍历,参见二叉树的前中后序遍历迭代&广度遍历和二叉树的前中后序遍历简单的递归 现在记录已知二叉树的前序中序后序遍历的两个,求另外一个.一般,这两个中一定有中序遍历. 1.已知前序和中序,求后序遍历: 前序:ABDECFG  中序:DBEAFCG 思路简单:前序的第一个节点就是根节点, 中序中找到根节点的位置,根节点之前是其左子树,之后是右子树   按此顺序,依次在左子树部分遍历,右子树部分遍历 C++ 代码: TreeNode *BinaryTre