网上代码一搜一大片,大同小异咯。

书上的函数实现代码甚至更胜一筹,而且抄一遍就能用,唯一问题是没有写二叉树节点和树的模版类的构造实现,和没有具体实现 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;
}

最新文章

  1. Spring MVC学习笔记——返回JSON对象
  2. Net设计模式实例之简单工厂模式(Simple Factory Pattern)
  3. 具备 jQuery 经验的人如何学习AngularJS(附:学习路径)
  4. 转 Microsoft&#39;s Objective-C tech started on BlackBerryOS, Tizen
  5. PyCharm、IntelliJ IDEA等jetbrains软件授权服务器
  6. [JS5] 利用onload执行脚本
  7. 《疯狂Java:突破程序员基本功的16课》读书笔记-第二章 对象与内存控制
  8. 【练习】ViewPager标签滑动
  9. Google地图接口API之地图事件(四)
  10. jsp页面中的问题:Date cannot be resolved to a type
  11. ListView的setOnItemClickListener和setOnItemLongClickListener同时响应的问题
  12. Milking Grid
  13. 熊猫猪新系统测试之三:iOS 8.0.2
  14. GitHub 开源的 MySQL 在线更改 Schema 工具【转】
  15. 一款好用 mongodb 可视化工具
  16. C# 服务端篇之实现RestFul Service开发(简单实用)
  17. sitecore系列教程之Sitecore个性化-配置文件,模式和角色
  18. Linux下mysql的远程连接(转)
  19. web前端开发与iOS终端开发的异同[转]
  20. 域名相关:DNS A记录 NS记录 MX记录 CNAME记录

热门文章

  1. .NET Core教程--给API加一个服务端缓存啦
  2. Jenkins入门【转】
  3. keepalived vip removed with dhcp renewal【原创】
  4. https://suchprogramming.com/epoll-in-3-easy-steps/
  5. linux都有哪些运行级别?
  6. Qt编写自定义控件63-水波效果
  7. 安卓 android studio 报错 All flavors must now belong to a named flavor dimension. Learn more at https://d.android.com
  8. SharpGL学习笔记(一) 平台构建与Opengl的hello World (转)
  9. new (std::nothrow) 与 new
  10. LODOP中带caption的表格被关联并次页偏移测试