[C++] 非递归实现前中后序遍历二叉树
网上代码一搜一大片,大同小异咯。
书上的函数实现代码甚至更胜一筹,而且抄一遍就能用,唯一问题是没有写二叉树节点和树的模版类的构造实现,和没有具体实现 visit 函数(也没说明,略坑)。
只需要前中后序遍历的话很多函数都不需要,此外值得吐槽的一点是,明明 BinaryTreeNode 类里面接口写的很明确,私有成员也都保护起来了,最后却把 BinaryTree 添加为了友元类,这波操作着实令人费解。
为了添加这个友元类还需要先进行两个类的声明,之后才能逐个实现,迷了。
但这都不是我按顺序实现了接口函数,最后还是没有调用接口函数的理由。所以根本原因其实就是懒。
前置技能
四种遍历方法分别为:
- 层次遍历 “ 从上到下,从左到右 ”
- 前序遍历 “ 根结点 -> 左子树 -> 右子树 ”
- 中序遍历 “ 左子树 -> 根结点 -> 右子树 ”
- 后序遍历 “ 左子树 -> 右子树 -> 根结点 ”

层次遍历使用了队列进行实现,而前中后序遍历是利用的栈来实现。而前序遍历、中序遍历和后序遍历中,后序遍历的实现无疑是最复杂的。
需求描述
直接上头文件,需要注意的是我没有实现建树、删树和插入的函数,顺手还多抄了一个层次遍历的函数。整体来看是一个很菜的代码,只在主函数里随便构了一个二叉树测试遍历函数。
全部都是模版类的实现写起来很麻烦,实现好了很舒服23333
binarytree.h
template<class T>
class BinaryTreeNode;
template<class T>
class BinaryTree;
template<class T>
class BinaryTreeNode{
private:
	T element;                        //数据域
	BinaryTreeNode<T> * leftChild;    //左孩子
	BinaryTreeNode<T> * rightChild;   //右孩子
public:
	BinaryTreeNode();                 //默认构造
	BinaryTreeNode(T& ele);           //给定数据域值的构造
	BinaryTreeNode(T& ele, BinaryTreeNode<T> * l, BinaryTreeNode<T> * r);
	BinaryTreeNode<T> * getLeftChild();           //返回左孩子
	BinaryTreeNode<T> * getRightChild();          //返回右孩子
	bool setLeftChild(BinaryTreeNode<T> * l);     //设置左孩子
	bool setRightChild(BinaryTreeNode<T> * r);    //设置右孩子
	T getValue() const;                           //返回数据值
	bool isLeaf() const;                          //判断是否为叶子节点
	friend class BinaryTree<T>;
};
template<class T>
class BinaryTree{
private:
	BinaryTreeNode<T> * root;  //根节点
public:
	BinaryTree();              //默认构造
	BinaryTree(BinaryTreeNode<T> * r);
	~BinaryTree();             //析构
	bool isEmpty() const;      //判断是否为空树
	void visit(BinaryTreeNode<T> * pointer);
	BinaryTreeNode<T> * getRoot() const;              //返回根节点
	void preOrder(BinaryTreeNode<T> * root);          //先序遍历
	void inOrder(BinaryTreeNode<T> * root);           //中序遍历
	void postOrder(BinaryTreeNode<T> * root);         //后序遍历
	void levelOrder(BinaryTreeNode<T> * root);        //层次遍历
};
具体实现
binarytree.cpp
#include"binarytree.h"
#include<iostream>
#include<queue>
#include<stack>
template<class T>
BinaryTreeNode<T>::BinaryTreeNode(){
	element = 0;
	leftChild = nullptr;
	rightChild = nullptr;
}
template<class T>
BinaryTreeNode<T>::BinaryTreeNode(T& ele){
	element = ele;
	leftChild = nullptr;
	rightChild = nullptr;
}
template<class T>
BinaryTreeNode<T>::BinaryTreeNode(T& ele, BinaryTreeNode<T> * l,
                                  BinaryTreeNode<T> * r){
	element = ele;
	leftChild = l;
	rightChild = r;
}
template<class T>
BinaryTreeNode<T> * BinaryTreeNode<T>::getLeftChild(){
	return leftChild;
}
template<class T>
BinaryTreeNode<T> * BinaryTreeNode<T>::getRightChild(){
	return rightChild;
}
template<class T>
T BinaryTreeNode<T>::getValue() const{
	return element;
}
template<class T>
bool BinaryTreeNode<T>::setLeftChild(BinaryTreeNode<T> * l){
	if(leftChild == nullptr){
		leftChild = l;
		return true;
	}
	else return false;
}
template<class T>
bool BinaryTreeNode<T>::setRightChild(BinaryTreeNode<T> * r){
	if(rightChild == nullptr){
		rightChild = r;
		return true;
	}
	else return false;
}
template<class T>
bool BinaryTreeNode<T>::isLeaf() const{
	if(leftChild == nullptr && rightChild == nullptr)
		return true;
	else return false;
}
template<class T>
BinaryTree<T>::BinaryTree(){
	root = nullptr;
}
template<class T>
BinaryTree<T>::BinaryTree(BinaryTreeNode<T> * r){
	root = r;
}
template<class T>
BinaryTree<T>::~BinaryTree(){
	root = nullptr;
}
template<class T>
bool BinaryTree<T>::isEmpty() const{
	if (root == nullptr)	return true;
	else return false;
}
template<class T>
BinaryTreeNode<T> * BinaryTree<T>::getRoot() const{
	return root;
}
template<class T>
void BinaryTree<T>::visit(BinaryTreeNode<T> * pointer){
	std::cout<<pointer->element<<std::endl;
}
template<class T>
void BinaryTree<T>::preOrder(BinaryTreeNode<T> * root){
	using std::stack;
	stack<BinaryTreeNode<T> * > nodeStack;
	BinaryTreeNode<T> * pointer = root;
	while(!nodeStack.empty()||pointer != nullptr){
		if(pointer != nullptr){
			visit(pointer);
			if(pointer -> rightChild !=  nullptr)
				nodeStack.push(pointer->rightChild);
			pointer = pointer->leftChild;
		}
		else{
			pointer = nodeStack.top();
			nodeStack.pop();
		}
	}
}
template<class T>
void BinaryTree<T>::inOrder(BinaryTreeNode<T> * root){
	using std::stack;
	stack<BinaryTreeNode<T> * > nodeStack;
	BinaryTreeNode<T> * pointer = root;
	while(!nodeStack.empty()||pointer){
		if(pointer){
			nodeStack.push(pointer);
			pointer = pointer -> leftChild;
		}
		else{
			pointer = nodeStack.top();
			visit(pointer);
			pointer = pointer -> rightChild;
			nodeStack.pop();
		}
	}
}
template<class T>
void BinaryTree<T>::postOrder(BinaryTreeNode<T> * root){
	using std::stack;
	stack<BinaryTreeNode<T> * > nodeStack;
	BinaryTreeNode<T> * pointer = root;
	BinaryTreeNode<T> * pre = root;
	while(pointer != nullptr){
		while(pointer -> leftChild != nullptr){
			nodeStack.push(pointer);
			pointer = pointer -> leftChild;
		}
		while(pointer != nullptr && (pointer -> rightChild == nullptr ||
                                     pre == pointer->rightChild)){
			visit(pointer);
			pre = pointer;
			pointer = nodeStack.top();
			nodeStack.pop();
		}
		nodeStack.push(pointer);
		pointer = pointer -> rightChild;
	}
}
template<class T>
void BinaryTree<T>::levelOrder(BinaryTreeNode<T> * root){
	using std::queue;
	queue<BinaryTreeNode<T> *>nodeQueue;
	BinaryTreeNode<T> * pointer = root;
	if(pointer)
		nodeQueue.push(pointer);
	while(!nodeQueue.empty()){
		pointer = nodeQueue.front();
		visit(pointer);
		nodeQueue.pop();
		if(pointer->leftChild)	nodeQueue.push(pointer->leftChild);
		if(pointer->rightChild)	nodeQueue.push(pointer->rightChild);
	}
}
main.cpp
#include"binarytree.h"
#include <iostream>
using namespace std;
int main(){
	int a1,a2,a3,a4,a5;
	cin>>a1>>a2>>a3>>a4>>a5;
	BinaryTreeNode<int> n1(a1),n2(a2),n3(a3),n4(a4),n5(a5);
	BinaryTree<int> t(&n1);
	n1.setLeftChild(&n2);
	n1.setRightChild(&n3);
	n2.setLeftChild(&n4);
	n2.setRightChild(&n5);          //真·随便接的
	cout<<"层次遍历:"<<endl;
	t.levelOrder(&n1);
	cout<<"前序遍历:"<<endl;
	t.preOrder(&n1);
	cout<<"中序遍历:"<<endl;
	t.inOrder(&n1);
	cout<<"后序遍历:"<<endl;
	t.postOrder(&n1);
	return 0;
}
[C++] 非递归实现前中后序遍历二叉树的更多相关文章
- C++二叉树前中后序遍历(递归&非递归)统一代码格式
		统一下二叉树的代码格式,递归和非递归都统一格式,方便记忆管理. 三种递归格式: 前序遍历: void PreOrder(TreeNode* root, vector<int>&pa ... 
- 数据结构-C语言递归实现树的前中后序遍历
		#include <stdio.h> #include <stdlib.h> typedef struct tree { int number ; struct tree *l ... 
- Binary Tree Traversal 二叉树的前中后序遍历
		[抄题]:二叉树前序遍历 [思维问题]: 不会递归.三要素:下定义.拆分问题(eg root-root.left).终止条件 [一句话思路]: 节点非空时往左移,否则新取一个点 再往右移. [输入量] ... 
- POJ 2255 Tree Recovery && Ulm Local 1997 Tree Recovery (二叉树的前中后序遍历)
		链接:poj.org/problem?id=2255 本文链接:http://www.cnblogs.com/Ash-ly/p/5463375.html 题意: 分别给你一个二叉树的前序遍历序列和中序 ... 
- C++实现对树的创建和前中后序遍历
		#include<iostream>#include<stdio.h> using namespace std; class BitNode{ public: char dat ... 
- 前中后序递归遍历树的体会 with Python
		前序:跟->左->右 中序:左->根->右 后序:左>右->根 采用递归遍历时,编译器/解释器负责将递归函数调用过程压入栈并保护现场,在不同位置处理根节点即可实现不 ... 
- 二叉树前中后/层次遍历的递归与非递归形式(c++)
		/* 二叉树前中后/层次遍历的递归与非递归形式 */ //*************** void preOrder1(BinaryTreeNode* pRoot) { if(pRoot==NULL) ... 
- Qt实现 动态化遍历二叉树(前中后层次遍历)
		binarytree.h 头文件 #ifndef LINKEDBINARYTREE_H #define LINKEDBINARYTREE_H #include<c++/algorithm> ... 
- PHP递归方法实现前序、中序、后序遍历二叉树
		二叉树是每个节点最多有两个子树的树结构.通常子树被称作“左子树”(left subtree)和“右子树”(right subtree). class Node { public $value; pub ... 
随机推荐
- 和小哥哥一起刷洛谷(4) 图论之广度优先搜索BFS
			关于bfs: 你怎么会连这个都不知道!!!自己好好谷歌一下!!!(其实我也刚学) bfs伪代码: while(队列非空){ 取出队首元素u; 弹出队首元素; u染色为黑色; for(int i=0;i ... 
- js函数运行方式一览
			定义对象然后调用 j = {} j["delete"]=function () { console.log("ok") } j["delete&quo ... 
- certification on windows and
			https://jingyan.baidu.com/article/335530dae0eb2319ca41c378.html 
- #C++初学记录(A==B?##高精度)
			Problem Description Give you two numbers A and B, if A is equal to B, you should print "YES&quo ... 
- 2019SDN课程阅读作业(2)
			1.过去20年中可编程网络的发展可以分为几个阶段?每个阶段的贡献是什么? 分为三个阶段,第一个阶段是主动网络(从20世纪90年代中期到21世纪初),它在网络中引入了可编程功能,以实现更大的创新:第二个 ... 
- oralce 超过1亿条数据的数据库表清理实践
			2018-08-18 16:58 无腿鸟 阅读(331) 评论(0) 编辑 收藏 问题:当一个表的数据量超过一亿条,要删除其中的5000w条,如何处理. 如果直接使用delete语句,会涉及到到大量的 ... 
- 肿瘤免疫疗法 | 细胞治疗和PD1/PDL1 | Tumor immunotherapy | cell therapy
			人类肿瘤治疗史上的里程碑无疑一定有一座是肿瘤免疫疗法的. 而肿瘤免疫疗法的主要两大领域,细胞治疗以及以PD1/PDL1为代表的免疫检查点抑制剂都在飞速发展. 目前,已经有5种抗PD1/PDL1抗体药物 ... 
- zabbix ALL = NOPASSWD: ALL
- Android命名规范(重点讲解:包名)
			Android程序开发中,使用规范的命名有益于程序的开发和后期阅读.本文主要对Android程序包名的定义做详细介绍,并附带一些简单的命名规则. 一.标识符命名方法1 .小驼峰命名法,除首单词外,其余 ... 
- TypeScript封装统一操作Mysql Mongodb Mssql的底层类库demo
			/* 功能:定义一个操作数据库的库 支持 Mysql Mssql MongoDb 要求1:Mysql MsSql MongoDb功能一样 都有 add update delete get方法 注意:约 ... 
