C++实现二叉树的前序、中序、后序非递归扁历

这三种常见的扁历方式,是考研面试等场合经常遇到的,在此做一个总结。

1、前序遍历比较简单:用指针p指向根节点,若p!=NULL且栈非空,则直接访问节点,并将节点的右孩子入栈,同时指针p向左孩子移动。

2、中序扁历:用指针p指向根节点,若p!=NULL且栈非空,则当前节点入栈,同时指针p向左孩子移动,出栈是指针指向当前节点的右孩子。

3、后序扁历相对复杂:需要设置一个辅助栈,标识该节点是否是第二次出栈,只有第二次出栈的节点才可被访问。

具体实现就不啰嗦了,直接上代码吧!

#include <stack>
#include <queue>

using namespace std;

// Binary tree struct
struct BinaryTreeNode
{
	BinaryTreeNode() :m_nValue(0), m_pLeft(NULL), m_pRight(NULL){}

	int m_nValue;
	BinaryTreeNode* m_pLeft;
	BinaryTreeNode* m_pRight;
};

// 按层次创建节点
BinaryTreeNode* CreateBinaryTree()
{
	int a;
	BinaryTreeNode *t = NULL;
	queue<BinaryTreeNode*> queue_nodes;

	cout << "Enter the value of current node value, (space to the leaf node)." << endl;
	if (cin >> a && a != -1)
	{
		t = new BinaryTreeNode;
		t->m_nValue = a;
		queue_nodes.push(t);
	}

	while (!queue_nodes.empty())
	{
		BinaryTreeNode *tNode = queue_nodes.front();
		queue_nodes.pop();
		if (cin >> a && a != -1)
		{
			BinaryTreeNode *newLeftNode = new BinaryTreeNode;
			newLeftNode->m_nValue = a;
			tNode->m_pLeft = newLeftNode;
			queue_nodes.push(newLeftNode);
		}

		if (cin >> a && a != -1)
		{
			BinaryTreeNode *newRightNode = new BinaryTreeNode;
			newRightNode->m_nValue = a;
			tNode->m_pRight = newRightNode;
			queue_nodes.push(newRightNode);
		}
	}

	return t;
}

void PreOrderTraverse(BinaryTreeNode *t, void(*visit)(int))
{
	stack<BinaryTreeNode*> stack_nodes;
	BinaryTreeNode *p = t;

	while (p || !stack_nodes.empty())
	{
		if (p){
			visit(p->m_nValue);
			if (p->m_pRight)
				stack_nodes.push(p->m_pRight);
			p = p->m_pLeft;
		}
		else{
			p = stack_nodes.top();
			stack_nodes.pop();
		}
	}
}

void InOrderTraverse(BinaryTreeNode *t, void(*visit)(int))
{
	stack<BinaryTreeNode*> stack_nodes;
	BinaryTreeNode *p = t;

	while (p || !stack_nodes.empty())
	{
		if (p){
			stack_nodes.push(p);
			p = p->m_pLeft;
		}
		else{
			p = stack_nodes.top();
			stack_nodes.pop();
			visit(p->m_nValue);
			p = p->m_pRight;
		}
	}
}

void PostOrderTraverse(BinaryTreeNode *t, void(*visit)(int))
{
	stack<BinaryTreeNode*> stack_nodes;
	stack<bool> stack_visited; // 辅助栈,标识节点是否已经出过栈,只有第二次出栈的节点才能被访问
	BinaryTreeNode *p = t;
	bool visited = false;

	while (p || !stack_nodes.empty())
	{
		if (p){
			stack_nodes.push(p); // 当前节点入栈
			stack_visited.push(false); // 对应的辅助标识入栈
			p = p->m_pLeft;  // 对左孩子进行操作
		}
		else{
			p = stack_nodes.top();
			stack_nodes.pop();
			visited = stack_visited.top();
			stack_visited.pop();
			if (!visited){
				stack_nodes.push(p);
				stack_visited.push(true);
				p = p->m_pRight;  // 对第一次出栈的节点,入栈后跳转到其右孩子
			}
			else{
				visit(p->m_nValue);
				p = NULL;
			}
		}
	}
}
时间: 2024-10-11 23:12:53

C++实现二叉树的前序、中序、后序非递归扁历的相关文章

(原)neuq oj 1022给定二叉树的前序遍历和后序遍历确定二叉树的个数

题目描述 众所周知,遍历一棵二叉树就是按某条搜索路径巡访其中每个结点,使得每个结点均被访问一次,而且仅被访问一次.最常使用的有三种遍历的方式: 1.前序遍历:若二叉树为空,则空操作:否则先访问根结点,接着前序遍历左子树,最后再前序遍历右子树. 2.中序遍历:若二叉树为空,则空操作:否则先中序遍历左子树,接着访问根结点,最后再前中遍历右子树. 3.后序遍历:若二叉树为空,则空操作:否则先后序遍历左子树,接着后序遍历右子树,最后再访问根结点. 现在的问题是给定前序遍历和后序遍历的顺序,要求出总共有多

二叉树的前序遍历、后序遍历、中序遍历规则(递归)

1.前序遍历的规则:(根左右) (1)访问根节点 (2)前序遍历左子树 (3)前序遍历右子树 对于图中二叉树,前序遍历结果:ABDECF 2.中序遍历的规则:(左根右) (1)中序遍历左子树 (2)访问根节点 (3)中序遍历右子树 对于图中二叉树,中序遍历结果:DBEAFC 3.后序遍历二叉树的规则:(左右根) (1)后序遍历左子树 (2)后序遍历右子树 (3)访问根节点 对于图中二叉树,后序遍历结果:DEBFCA 例题:POJ2255 给了前.中序遍历,求后序遍历.参考:https://blo

分别求二叉树前、中、后序的第k个节点

一.求二叉树的前序遍历中的第k个节点 //求先序遍历中的第k个节点的值 int n=1; elemType preNode(BTNode *root,int k){ if(root==NULL) return ' '; if(n==k) return root->data; n++; elemType ch = preNode(root->lchild,k); if(ch!=' ') return ch; ch = preNode(root->rchild,k); return ch;

由二叉树的前序遍历和后序遍历来求后序遍历的结果

假设有棵树,长下面这个样子,它的前序遍历,中序遍历,后续遍历都很容易知道. PreOrder:         GDAFEMHZ InOrder:            ADEFGHMZ PostOrder:       AEFDHZMG 现在,假设仅仅知道前序和中序遍历,如何求后序遍历呢?比如,已知一棵树的前序遍历是"GDAFEMHZ",而中序遍历是"ADEFGHMZ"应该如何求后续遍历? 第一步,root最简单,前序遍历的第一节点G就是root. 第二步,继续观

输入某二叉树的前序遍历和后序遍历的结果,请重建该二叉树。

思路:根据前序遍历依次访问对应的中序遍历的节点,分为左子树和右子树创建. #include<iostream> #include<stdlib.h> using namespace std; struct BinaryTreeNode { BinaryTreeNode(int _value) :m_nValue(_value) ,m_pLeft(NULL) ,m_pRight(NULL) {} int m_nValue; struct BinaryTreeNode* m_pLeft

算法实验-二叉树的创建和前序-中序-后序-层次 遍历

对于二叉树的创建我是利用先序遍历的序列进行创建 能够对于树节点的内容我定义为char型变量 '0'为空,即此处的节点不存在 头文件 Tree.h //链式二叉树的头文件 #pragma once #include<iostream> #include<queue> using namespace std; class BinaryTreeNode { public: char data; BinaryTreeNode *leftChild,*rightChild; BinaryTr

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

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

经典白话算法之二叉树中序前序序列(或后序)求解树

这种题一般有二种形式,共同点是都已知中序序列.如果没有中序序列,是无法唯一确定一棵树的. <1>已知二叉树的前序序列和中序序列,求解树. 1.确定树的根节点.树根是当前树中所有元素在前序遍历中最先出现的元素. 2.求解树的子树.找出根节点在中序遍历中的位置,根左边的所有元素就是左子树,根右边的所有元素就是右子树.若根节点左边或右边为空,则该方向子树为空:若根节点 边和右边都为空,则根节点已经为叶子节点. 3.递归求解树.将左子树和右子树分别看成一棵二叉树,重复1.2.3步,直到所有的节点完成定

面试之路(11)-java递归和非递归二叉树前序中序后序遍历

二叉树的遍历 对于二叉树来讲最主要.最基本的运算是遍历. 遍历二叉树 是指以一定的次序访问二叉树中的每个结点.所谓 访问结点 是指对结点进行各种操作的简称.例如,查询结点数据域的内容,或输出它的值,或找出结点位置,或是执行对结点的其他操作.遍历二叉树的过程实质是把二叉树的结点进行线性排列的过程.假设遍历二叉树时访问结点的操作就是输出结点数据域的值,那么遍历的结果得到一个线性序列. 从二叉树的递归定义可知,一棵非空的二叉树由根结点及左.右子树这三个基本部分组成.因此,在任一给定结点上,可以按某种次