[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 ...
随机推荐
- 常用spaceclaim脚本
#创建一个长方体,通过两点来确定一个立方体 #MM表示的是以毫米作为单位 #返回的是一个BlockBody的对象 #本函数还有第三个参数可选,分别代表增加材料,切除材料等等 #默认值为增加材料 注:第 ...
- Spring boot Bean装配
. Spring boot bean 默认创建的bean 为singleton模式 . @Component 注解 . @Value 为属性初始化 . @Value("${}") ...
- UDP如何实现可靠传输
概述 UDP不属于连接协议,具有资源消耗少,处理速度快的优点,所以通常音频,视频和普通数据在传送时,使用UDP较多,因为即使丢失少量的包,也不会对接受结果产生较大的影响. 传输层无法保证数据的可靠传输 ...
- selenium之 下拉选择框Select
今天总结下selenium的下拉选择框.我们通常会遇到两种下拉框,一种使用的是html的标签select,另一种是使用input标签做的假下拉框. 后者我们通常的处理方式与其他的元素类似,点击或使用J ...
- [转] FileZilla Server超详细配置
FileZilla Server下载安装完成后,必须启动软件进行设置,由于此软件是英文,本来就是一款陌生的软件,再加上英文(注:本站提供中文版本,请点击下载),配置难度可想而知,站长从网上找到一篇非常 ...
- fork 可能导致subprocess崩溃
https://docs.python.org/zh-cn/3/library/multiprocessing.html 在 3.8 版更改: 对于 macOS,spawn 启动方式是默认方式. 因为 ...
- [原][OE][官方例子]osgearth_annotation OE地球添加热点标签
OE所有官方例子 OE代码样例 /* -*-c++-*- */ /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph * Co ...
- 六、postman做ui测试
一.思路 发请求去拿到网站的响应——>html 解析html标签,判断一些元素是否显示 二.目的 快速检查ui是否正确 三.用到的库 Cheerio https://cheerios.js.or ...
- C/C++如何监测内存泄漏
C/C++如何监测内存泄漏 C/C++内存泄漏及检测 内存溢出就是内存越界.内存越界有一种很常见的情况是调用栈溢出(即stackoverflow),虽然这种情况可以看成是栈内存不足的一种体现.例如:递 ...
- WPF分析工具
分析WPF程序是理解其行为很重要的一步,市场上有大量现成的WPF程序分析工具,如Snoop,WPFPerf,Perforator和Visual Profiler,其中Perforator和Visual ...