c++ 二叉树的线索化(前中后序遍历)

#pragma once//.hpp函数头文件

#include<iostream>

using namespace std;

enum BinTreeNodeChildType
{
	Thread,
	Link
};

template <class T>
struct BinaryTreeThrNode
{
public:
	T _data;  //数据域
	BinaryTreeThrNode<T>* _leftChild;//做孩子
	BinaryTreeThrNode<T>* _rightChild;//右孩子
	BinTreeNodeChildType _leftType;//左节点类型
	BinTreeNodeChildType _rightType;//右节点类型
	BinaryTreeThrNode<T>* _parent;//父节点  (后续线索化 遍历 用到)

public:
	BinaryTreeThrNode(const T& data)
		:_data(data)
		, _leftChild(NULL)
		, _rightChild(NULL)
		, _leftType(Link)
		, _rightType(Link)
		, _parent(NULL)
	{}

	~BinaryTreeThrNode()
	{}
};

template <class T>
class BinaryTreeThread
{
public:
	BinaryTreeThrNode<T>* _root;
public:
	BinaryTreeThread()
		:_root(NULL)
	{}

	BinaryTreeThread(T*a, size_t size)
	{
		size_t index = 0;
		_root = _CreateBiTree(a, index, size);
	}

	void InOrderThread()
	{
		BinaryTreeThrNode<T>* prev = NULL;
		BinaryTreeThrNode<T>* cur = _root;
		_InOrderThread(cur,prev );
	}

	void PreOrderThread()
	{
		BinaryTreeThrNode<T>* prev = NULL;
		_PreOrderThread(_root,prev);
	}

	void InOrderThe1()  //cur每次循环跳一次
	{
		BinaryTreeThrNode<T>* cur = _root;
		BinaryTreeThrNode<T>*prev = _root;
		while (cur)
		{
			if (cur->_leftChild&&prev->_rightChild != cur&&cur->_leftType == Link)
				cur = cur->_leftChild;
			else
			{
				cout << cur->_data << ‘ ‘;
				if (cur->_rightType == Thread)
					prev = cur;
				cur = cur->_rightChild;
			}
		}
	}
	void InOrderThe()  //cur每次循环中有循环
	{
		BinaryTreeThrNode<T>* cur = _root;
		while (cur)
		{
			while (cur&&cur->_leftType == Link)
			{
				cur = cur->_leftChild;
			}
			cout << cur->_data << ‘ ‘;
			while (cur&&cur->_leftType== Thread)
			{
				cur = cur->_rightChild;
				cout << cur->_data<<‘ ‘;
			}
			cur = cur->_rightChild;
		}
	}

	//前序线索遍历
	void PreOrderThe()
	{
		BinaryTreeThrNode<T>* cur = _root;
		while (cur&&cur->_rightChild)
		{
			while (cur->_leftType != Thread)
			{
				cout << cur->_data << ‘ ‘;
				cur = cur->_leftChild;
			}
			while (cur->_rightType == Thread)
			{
				cout << cur->_data << ‘ ‘;
				cur = cur->_rightChild;
				if (cur->_rightChild == NULL)
					cout << cur->_data << ‘ ‘;

			}
		}

	}
        //后续线索遍历
	void PostOrderThe1()//老师的方法
	{
		if (_root == NULL)
			return;

		BinaryTreeThrNode<T>* cur = _root->_left;
		BinaryTreeThrNode<T>* prev = NULL;

		while (cur != _root)
		{
			// 1.找最左节点
			while (cur && cur->_leftTag == LINK)
				cur = cur->_left;

			while (cur && cur->_rightTag == THREAD)
			{
				cout << cur->_data << " ";
				prev = cur;
				cur = cur->_right;
			}

			// 当跳到root则遍历完成
			if (cur == _root)
			{
				cout << _root->_data << " ";
				break;
			}

			// 一个节点的右树已经访问完成,则跳转到根节点
			if (cur && cur->_rightTag == LINK
				&& cur->_right == prev)
			{
				cout << cur->_data << " ";
				prev = cur;

				cur = cur->_parent;
			}

			// 往右树跳转
			if (cur && cur->_rightTag == LINK)
			{
				cur = cur->_right;
			}
		}

		cout << endl;
	}

	void PosOrderThe()//后续线索遍历(借助 父节点)
	{
		BinaryTreeThrNode<T>* cur = _root;
		BinaryTreeThrNode<T>* prev = NULL;//防止死循环的记录指针
		while (cur)
		{

			while (prev!=cur->_leftChild&&cur!=prev&&cur->_leftType != Thread)//左支不为Thread且 prev不为cur坐支且prev!=cur 循环压左
				cur = cur->_leftChild;
			if (prev==cur&&cur->_rightType == Link)//右支不为Thread类型 压右
				cur = cur->_rightChild;
			else
			{
				while (cur->_rightType == Thread)  //右支为Thread类型 循环压右  输出
				{

					cout << cur->_data << ‘ ‘;
					cur = cur->_rightChild;
					prev= cur; 
				}
				cout << cur->_data << ‘ ‘;
				cur = cur->_parent;
				if (cur&&cur->_rightType == Link&&cur->_leftChild==prev)
				{
					prev = cur;//prev始终为右支返回的父节点
				}
			}
			if (cur == _root&&prev != cur)//prev是从右支返回的并且 cur为根节点结束循环
			{
				cout << cur->_data << ‘ ‘;
				break;
			}
		}
	}
        //后续线索化
	void PosOrderThread()
	{
		BinaryTreeThrNode<T>* prev = NULL;
		_PosOrderThread(_root,prev);
	}

	BinaryTreeThrNode<T>* _CreateBiTree(const T* tmp,  size_t& index, size_t size)
	{
		BinaryTreeThrNode<T>* root = NULL;
		BinaryTreeThrNode<T>* parent = NULL;
		if (index < size&&tmp[index] != ‘#‘)
		{

			root = new BinaryTreeThrNode<T>(tmp[index]);
			parent=_CreateBiTree(tmp, ++index, size);
			if (parent)
			{
				root->_leftChild = parent;
				parent->_parent = root;
			}
			parent = _CreateBiTree(tmp, ++index, size);

		}
		if (parent)
		{
			root->_rightChild = parent;
			parent->_parent = root;
		}
		return root;
	}

	//中序线索化

	void _InOrderThread(BinaryTreeThrNode<T>*cur,BinaryTreeThrNode<T>* & prev)
	{
		if (cur ==NULL)
			return;
		_InOrderThread(cur->_leftChild,prev);//向左树遍历
		if (cur->_leftChild==NULL)            //左为空  改变左类型 左指向prev
		{
			cur->_leftType = Thread;
			cur->_leftChild = prev;

		}
		if (prev&&prev->_rightChild == NULL) //prev!=NULL 且prev右不空 改变右类型 让右指向当前
		{
			prev->_rightType = Thread;
			prev->_rightChild = cur;
		}
		prev = cur;                          //prev指向递归返回前的节点
		_InOrderThread(cur->_rightChild, prev);  //指向右数节点

}

	//前序线索化 自己的笨办法
	void _PreOrderThread1(BinaryTreeThrNode<T>* cur, BinaryTreeThrNode<T>* &prev)
	{
		if (cur == NULL)
			return;
		if (prev&&prev->_rightType == Thread&&prev->_rightChild==NULL)//给右为空的左节点
			prev->_rightChild = cur;
		if (cur->_leftChild)//左不空  压左
		{
			prev = cur;   //prev=上个节点
			_PreOrderThread(cur->_leftChild, prev);
		}
		else
		{
			cur->_leftType = Thread;//左空  左节点类型为线索类型
			cur->_leftChild = prev;//线索指向prev
		}
		if (cur->_rightChild)//右不为空
		{
			_PreOrderThread(cur->_rightChild, prev);//压右
		}
		else
		{

			if (prev&&prev->_rightType==Thread&&cur->_leftType==Link&&cur->_rightChild==NULL)
				cur->_rightChild =prev;//判断是否该节点为只有左分支 是的话使右线索指向左分支
			cur->_rightType = Thread;//右分支为线索类型
			if (cur->_rightChild==NULL)//不连续压左情况  右分支为空  使prev=cur
				prev = cur;
		}
	}

	void _PreOrderThread(BinaryTreeThrNode<T>* cur, BinaryTreeThrNode<T>* &prev)//老师方法
	{
		if (cur == NULL)//空返回
			return;
		if (cur->_leftChild == NULL)//左植线索化  当前递归中
		{
			cur->_leftType = Thread;
			cur->_leftChild = prev;
		}
		if (prev&&prev->_rightChild == NULL)//右植线索化 返回上次递归中
		{
			prev->_rightType = Thread;
			prev->_rightChild = cur;
		}

		prev = cur; //prev为上次递归cur

		if (cur->_leftType==Link)//cur左值类型为节点类型 继续递归
			_PreOrderThread(cur->_leftChild, prev);
		if (cur->_rightType==Link)//cur右植类型为节点类型 继续递归
		_PreOrderThread(cur->_rightChild, prev);
	}

	//后续线索化
	void _PosOrderThread(BinaryTreeThrNode<T>* cur,BinaryTreeThrNode<T>*& prev)
	{
		if (cur == NULL)
			return;

		if (cur->_leftChild == NULL)//作为空左支线索化=prev
		{
			cur->_leftType = Thread;
			cur->_leftChild = prev;
		}

		if (cur->_leftType==Link)//cur左支类型为节点类型  递归左
			_PosOrderThread(cur->_leftChild,prev);

		if (cur->_rightType==Link)//cur右植为节点类型  递归右
			_PosOrderThread(cur->_rightChild,prev);
		if (prev&&prev->_rightChild == NULL)  //prev右植为空  prev指向当前
		{
			prev->_rightType = Thread;
			prev->_rightChild = cur;
		}
		prev = cur;  //子树递归结束 prev=cur  

	}
};

//测试用例
#include"bintreethread.hpp"
#include"BinaryTreeThreading.h"

using namespace std;

void test()
{
	int a[10] = { 1, 2, 3, ‘#‘, ‘#‘,4, ‘#‘, ‘#‘, 5, 6 };
	int s[18] = { 1, 2, 3, 4, ‘#‘, ‘#‘, 5, ‘#‘, ‘#‘, 6, ‘#‘, ‘#‘, 7, 8, ‘#‘, ‘#‘, 9, 10 };
	int k[14] = { 1, 2, 3, 4, ‘#‘,‘#‘,‘#‘,5,‘#‘,‘#‘, 6, 7,‘#‘,‘#‘ };
	BinaryTreeThread<int> s1;
	BinaryTreeThread<int> s2(s,18);
	//BinaryTreeThread<int> s2(k, 14);
	//BinaryTreeThread<int> s2(a, 10);

	/*s2.InOrderThread();
	s2.InOrderThe();*/
	//s2.PreOrderThread();

	s2.PosOrderThread();
	s2.PosOrderThe();
}

int main()
{
	test();
	return 0;
}
时间: 2024-08-03 17:26:08

c++ 二叉树的线索化(前中后序遍历)的相关文章

二叉树的建立及其前中后序遍历

1 //二叉树存储结构: 2 struct node 3 { 4 Int data; 5 node *lchild; 6 node *rchild; 7 }; 8 9 //二叉树在建树前根节点不存在: 10 Node *root = NULL; 11 12 //新建结点: 13 node *newNode(int v) 14 { 15 node *Node = new node; 16 Node->data = v; 17 Node->lchild = NULL; 18 Node->rc

二叉树的前中后序遍历简单的递归

二叉树的遍历 无外乎广度和深度 其中深度又分为前中后序遍历三种情况  这三种遍历若只是递归方法 自然很是简单 但递归代码简单 若嵌套层次太深 会栈溢出 二叉树节点数据结构: struct Binary_node{    int val;    Binary_node *left;    Binary_node *right;    Binary_node(int v = 0, Binary_node *le = nullptr, Binary_node *ri = nullptr) :val(v

二叉树的前序建立,前中后序遍历的非递归算法

二叉树的前序建立递归算法以及前中后序遍历的递归算法已经是人尽皆知了,递归算法也确实为代码的编写带来了很大的方便.然而,有时我们也确实需要它们的非递归算法.将递归算法转化为非递归算法可以帮助我们深入了解函数的调用与栈的原理.这里总结一下二叉树的这些重要的非递归算法. 一.前序建树 前序建树的基本思路是,接收用户输入的一组字符串,其中'#'代表空树,其他代表树结点的数据域值.例如,要建立如下一棵树 需要输入"AB#D##C##". 而非递归的思路是,1.设一个标志位来判断当前创建的结点是左

002.深入浅出理解[二叉树的构建、先中后序遍历、树的深度、左右子树互换]

二叉树本来就是递归定义的,如果对递归还不是特别了解,建议看一下<001.深入浅出解释[递归]> 写一个递归函数很简单,只需要记住下面2点: 1.递归中止条件:对于二叉树来说一般是node==null的时候判断到了叶子结点 2.递归函数::描述一个中间过程,然后用代码实现,调用自身的时候传递的参数就是你想要递归的方式. 下面的代码就是一个二叉树的创建.先中后序遍历.树的深度.左右子树的互换的过程 #include <stdio.h> // 定义二叉树的结点 struct treeNo

非递归前中后序遍历二叉树

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 写在前面: 最近准备找工作,捡起原来学习过的各种知识,加上一些自己的理解,梳理一下流程,巩固自己的认识,一步两步,一步两步... ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 二叉树的遍历是树操作的基础,一般的前中后序递归遍历比较简单,这里就不列出了,主要是非递归实

二叉树系列 - 二叉树的前/中/后序遍历(非递归)

二叉树的遍历是二叉树中最最基础的部分. 这里整理二叉树不用递归实现三种顺序遍历的方式. 不用递归的话,一般需要栈来完成.当然线索二叉树(不需要栈或递归)也可以完成中序遍历,这种方式在这篇文章中已经讨论过.这里着重讨论使用栈的实现方式. 中序遍历 (1) 双while,第二个内层while是为了不断压入left child. vector<int> inorderTraversal(TreeNode *root) { vector<int> v; if(!root) return v

POJ 2255 Tree Recovery &amp;&amp; Ulm Local 1997 Tree Recovery (二叉树的前中后序遍历)

链接:poj.org/problem?id=2255 题意: 分别给你一个二叉树的前序遍历序列和中序遍历序列,让你给出这个二叉树的后序遍历序列. 思路: 对于二叉树的三种遍历方式,都可以使用递归来实现,那么也一定可以使用递归来拆解,以达到从遍历序列确定二叉树具体结构的目的.对于前序遍历来说,第一个字母一定是根,并且在序列中根的左子树包含的点一定出现在根的右子树的前面.对于中序遍历序列来说,根前面出现的字母所代表的点一定出现在左子树中,根后面出现的字母所代表的点一定出现在右子树中.在根据前序与中序

【数据结构】 非递归前中后序遍历二叉树

数据结构学的递归了,深入了解后写一个三序非递归的版本. //测试数据:abd##eg##h##c#f## #include <cstdio> #include <iostream> typedef char ElemType; typedef struct Node { ElemType elem; struct Node *lchild,*rchild; }Node,*BiTree; typedef struct{ BiTree *base; BiTree *top; int s

二叉树的前中后序遍历

#include<stdio.h> #include<string.h> #include<stdlib.h> #define Size 100 #define Resize 10 typedef struct Bitnode{ //定义结点 char data; struct Bitnode *lchild,*rchild; }Bitnode,*Bitree; typedef struct Stack{ //定义栈 Bitree *base; int top; int

二叉树的前中后序遍历迭代&amp;广度遍历

递归很是简单 但也应该掌握其迭代方式的遍历方法 这三种的迭代遍历方法需要通过栈来存储节点 尤其是后序遍历还需要 记录当前节点的右子树是否已被遍历 决定是否遍历当前节点 而其广度遍历 只需要一个队列来顺序记录遍历节点 即可轻松解决问题  主要思想在程序代码中来做说明 前序遍历:遍历结果返回一个vector容器中 std::vector<int> BinaryTree::pre_order_iter(Binary_node *root){    std::vector<int> res