数据结构之二叉树的所有遍历算法C++实现(递归和非递归)

定义头文件:BinTree.h

#pragma once
#include <iostream>
#include <vector>
#include <queue>
#include <stack>

using namespace std;

template <class NodeType>
struct TreeNode {
	NodeType val;
	TreeNode *parent;
	TreeNode *lchild;
	TreeNode *rchild;
	TreeNode() {};
	TreeNode(NodeType value) {
		val = value;
		parent = nullptr;
		lchild = nullptr;
		rchild = nullptr;
	}
};

template <class NodeType>
class BinTree {
public:
	BinTree():root(nullptr){}
	BinTree(TreeNode<NodeType> *node) {
		root = new TreeNode<NodeType>();
		root->lchild = nullptr;
		root->parent = nullptr;
		root->rchild = nullptr;
		root->val = node->val;
	}

	void visit(TreeNode<NodeType> &node) { cout << node.val << " "; }

	TreeNode<NodeType> *getRoot() { return root; }
	void makeCompleteTree();

	// 递归实现遍历三种基本遍历
	void preorderRecursion(TreeNode<NodeType> *node);
	void inorderRecursion(TreeNode<NodeType> *node);
	void postorderRecursion(TreeNode<NodeType> *node);

	// 非递归实现遍历三种基本遍历、层序遍历、深度优先遍历和广度优先遍历
	void preorderTraversal(TreeNode<NodeType> *node);
	void inorderTraversal(TreeNode<NodeType> *node);
	void inorderTraversal_2(TreeNode<NodeType> *node);
	void postorderTraversal(TreeNode<NodeType> *node);
	void postorderTraversal_2(TreeNode<NodeType> *node);

	void levelorderTraversal(TreeNode<NodeType> *node);

	void broadTraversal(TreeNode<NodeType> *node);
	void depthTraversal(TreeNode<NodeType> *node);
private:
	TreeNode<NodeType> *root;
};

template <class NodeType>
void BinTree<NodeType>::preorderRecursion(TreeNode<NodeType> *node) {
	if (node) {
		
		visit(*node);
		preorderRecursion(node->lchild);
		preorderRecursion(node->rchild);
	}
}

template <class NodeType>
void BinTree<NodeType>::inorderRecursion(TreeNode<NodeType> *node) {
	if (node) {
		inorderRecursion(node->lchild);
		visit(*node);
		inorderRecursion(node->rchild);
	}
}

template <class NodeType>
void BinTree<NodeType>::postorderRecursion(TreeNode<NodeType> *node) {
	if (node) {
		postorderRecursion(node->lchild);
		postorderRecursion(node->rchild);
		visit(*node);
	}
}

template <class NodeType>
void BinTree<NodeType>::preorderTraversal(TreeNode<NodeType> *node) {
	if (node == nullptr) return;

	stack<TreeNode<NodeType>* > mystack;
	mystack.push(node);
	while (!mystack.empty()) {
		TreeNode<NodeType> *curNode = mystack.top();
		visit(*curNode);
		mystack.pop();
		if (curNode->rchild != nullptr) mystack.push(curNode->rchild);
		if (curNode->lchild != nullptr) mystack.push(curNode->lchild);
	}
}

template <class NodeType>
void BinTree<NodeType>::inorderTraversal(TreeNode<NodeType> *node) {
	if (node == nullptr) return;
	
	stack<TreeNode<NodeType>* > mystack;
	TreeNode<NodeType> *curNode = node;
	while (curNode || !mystack.empty()) {
		if (curNode) {
			mystack.push(curNode);
			curNode = curNode->lchild;
		}
		else {
			curNode = mystack.top();
			visit(*curNode);
			mystack.pop();
			curNode = curNode->rchild;
		}
	}
}

// 另一种写法的中序遍历非递归实现,思路完全一样
template <class NodeType>
void BinTree<NodeType>::inorderTraversal_2(TreeNode<NodeType> *node) {
	if (node == nullptr) return;

	stack<TreeNode<NodeType>* > mystack;
	TreeNode<NodeType> *curNode = node;
	while (curNode || !mystack.empty()) {
		while(curNode) {
			mystack.push(curNode);
			curNode = curNode->lchild;
		}
		curNode = mystack.top();
		visit(*curNode);
		mystack.pop();
		curNode = curNode->rchild;
	}
}


// 使用两个栈实现的后序非递归遍历算法,一个栈用于存放标记位
template<class NodeType>
void BinTree<NodeType>::postorderTraversal(TreeNode<NodeType> *node) {
	if (node == nullptr) return;
	stack<TreeNode<NodeType> *> mystack;
	stack<int> flagstack;
	mystack.push(node);
	flagstack.push(0);
	while (!mystack.empty()) {
		TreeNode<NodeType> *curNode = mystack.top();
		int curFlag = flagstack.top();
		flagstack.pop();
		if (curFlag == 0) {
			flagstack.push(1);
			if (curNode->rchild != nullptr) {
				mystack.push(curNode->rchild);
				flagstack.push(0);
			}
			if (curNode->lchild != nullptr) {
				mystack.push(curNode->lchild);
				flagstack.push(0);
			}
		}
		else {
			visit(*curNode);
			mystack.pop();
		}
	}
}

// 另一种使用两个栈实现的后序非递归遍历算法,先将结点放在第一个栈中,再放入第二个栈中进行进行访问
// 需要强调的是,在第一个栈中要先把当前结点的左结点入栈,再把右结点入栈,不要弄反了顺序
template<class NodeType>
void BinTree<NodeType>::postorderTraversal_2(TreeNode<NodeType> *node) {
	if (node == nullptr) return;
	stack<TreeNode<NodeType> *> firststack, secondstack;
	firststack.push(node);
	while (!firststack.empty()) {
		TreeNode<NodeType> *curNode = firststack.top();
		firststack.pop();
		secondstack.push(curNode);
		if (curNode->lchild != nullptr) firststack.push(curNode->lchild);
		if (curNode->rchild != nullptr) firststack.push(curNode->rchild);
	}
	while (!secondstack.empty()) {
		TreeNode<NodeType> *curNode = secondstack.top();
		visit(*curNode);
		secondstack.pop();
	}
}

// 使用队列实现的层序遍历
template <class NodeType>
void BinTree<NodeType>::levelorderTraversal(TreeNode<NodeType> *node) {
	if (node == nullptr) return;

	queue<TreeNode<NodeType> *> myqueue;
	myqueue.push(node);
	while (!myqueue.empty()) {
		TreeNode<NodeType> *curNode = myqueue.front();
		myqueue.pop();
		visit(*curNode);
		if (curNode->lchild != nullptr) myqueue.push(curNode->lchild);
		if (curNode->rchild != nullptr) myqueue.push(curNode->rchild);
	}
}

// 广度优先遍历本质上就是层序遍历
template <class NodeType>
void BinTree<NodeType>::broadTraversal(TreeNode<NodeType> *node) {
	levelorderTraversal(node);
}

// 深度优先遍历实际上就是二叉树的先序遍历,这里直接调用先序遍历
template <class NodeType>
void BinTree<NodeType>::depthTraversal(TreeNode<NodeType> *node) {
	preorderTraversal(node);
}

测试代码:main.cpp

#include "pch.h"
#include "binTree.h"
#include <iostream>

int main()
{
	TreeNode<int> node1(1);
	TreeNode<int> node2(2);
	TreeNode<int> node3(3);
	TreeNode<int> node4(4);
	TreeNode<int> node5(5);
	node1.lchild = &node2;
	node1.rchild = &node3;
	node2.lchild = nullptr;
	node2.rchild = nullptr;
	node3.lchild = &node4;
	node3.rchild = &node5;
	node4.lchild = nullptr;
	node4.rchild = nullptr;
	node5.lchild = nullptr;
	node5.rchild = nullptr;
	BinTree<int> bTree(&node1);
	bTree.postorderTraversal(&node1);
}

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值