本文和该篇文章 leetcode | 二叉树的前序遍历、中序遍历、后续遍历的非递归实现有不同的实现方式,此文章的非递归遍历实现算法,易于理解和实现。
包含插入、遍历、统计树中节点的个数、统计树的深度等操作。
遍历操作包含:
- 迭代(非递归)实现的前序、中序、后序、层序遍历。
其中前序和中序,一个是先访问在入栈、一个是先入栈后访问有极大的相似性;
其中后序遍历使用了双栈操作,使思想简化易于实现;
其中层序遍历采用FIFO**队列**实现;
以下源码,采用c++实现
#include <stack>
#include <queue>
#include <algorithm>
#include <iostream>
using namespace std;
template<class T>
class Node {
public:
T item;
Node* left;
Node* right;
};
template<class T>
class BinaryTree {
private:
Node<T>* binary_tree;
int items_index;
// 用数组元素创建一棵树,以#作为分隔符结束当前子树的增长
template<size_t size>
Node<T>* Creat(Node<T>* tree, const T(&items)[size]) {
T item = items[items_index++];
if (item == '#') {
tree = NULL;
}
else {
tree = new Node<T>;
tree->item = item;
tree->left = Creat(tree->left, items);
tree->right = Creat(tree->right, items);
}
return tree;
}
//递归计算tree所有节点的个数:左子树+右子树+1(1为当前根)
int GetNodeNums(Node<T>* tree) {
if (tree == NULL)
return 0;
return GetNodeNums(tree->left) + GetNodeNums(tree->right) + 1;
}
// 递归计算tree的深度:max(左子树、右子树) + 1 (1为当前根)
int GetTreeDepth(Node<T>* tree) {
if (tree == NULL)
return 0;
return max(GetTreeDepth(tree->left), GetTreeDepth(tree->right)) + 1;
}
public:
BinaryTree() {
binary_tree = NULL;
items_index = 0;
}
public:
template<size_t size>
void CreatTree(const T(&items)[size]) {
binary_tree = Creat(binary_tree, items);
};
int size() {
return GetNodeNums(binary_tree);
}
int depth() {
return GetTreeDepth(binary_tree);
}
// 前序遍历:先访问根节点,再访问左、右节点
// 先访问、后入栈
// 如果tree非空:访问栈顶元素,把tree入栈,tree指向左子树
// 如果tree 为空:说明已经到左子树的尽头,弹出当前栈顶元素tree指向右子树。
void PreorderTravel() {
cout << "PreorderTravel: ";
if (binary_tree == NULL)
return;
stack<Node<T>*> stk;
Node<T>* tree = binary_tree;
while (tree || stk.empty() == false) {
if (tree) {
cout << tree->item << " ";
stk.push(tree);
tree = tree->left;
}
else {
tree = stk.top();
tree = tree->right;
stk.pop();
}
}
cout << endl;
}
// 中序遍历:先访问左,再根、最后右
// 先入栈、后访问
// 如果tree非空:把tree入栈,tree指向左子树
// 如果tree为空:说明已经向左走到了尽头,弹出当前栈顶元素,访问tree,tree指向右子树
void InorderTravel() {
cout << "InorderTravel: ";
if (binary_tree == NULL)
return;
stack<Node<T>*> stk;
Node<T>* tree = binary_tree;
while (tree || stk.empty() == false) {
if (tree) {
stk.push(tree);
tree = tree->left;
} else {
tree = stk.top();
stk.pop();
cout << tree->item << " ";
tree = tree->right;
}
}
cout << endl;
}
// 后续遍历:先左、再右,最后根
// 采用两个栈实现,先压入当前节点的左子树,然后压入右子树
// 得到的顺序:根-右-左,刚好是后序遍历的逆序;在另一个栈反转
void PostorderTravel() {
cout << "PostorderTravel: ";
if (binary_tree == NULL)
return;
Node<T>* tree = binary_tree;
stack<Node<T>* > stk1, stk2;
stk1.push(tree);
while (stk1.empty() == false) {
tree = stk1.top();
stk1.pop();
stk2.push(tree);
if (tree->left)
stk1.push(tree->left);
if (tree->right)
stk1.push(tree->right);
}
while (stk2.empty() == false) {
cout << stk2.top()->item << " ";
stk2.pop();
}
cout << endl;
}
// 层序遍历, 逐层从上到下从左到右访问
// 采用队列实现,先入先出
// 先把根入队列,当队列非空时,弹出队列最前的元素并访问,
// 如果左右子树非空则依次入队列
void LevelorderTravel() {
cout << "LevelorderTravel: ";
if (binary_tree == NULL)
return;
Node<T>* tree = binary_tree;
queue<Node<T>* > que;
que.push(tree);
while (que.empty() == false) {
tree = que.front();
que.pop();
cout << tree->item << " ";
if (tree->left)
que.push(tree->left);
if (tree->right)
que.push(tree->right);
}
cout << endl;
}
};
int main()
{
/*
A
B C
D E F G
H I J
K
*/
const char str[] = "ABDH#K###E##CFI###G#J##";
BinaryTree<char> btree;
btree.CreatTree(str);
cout << "Tree size: " << btree.size() << endl;
cout << "Tree Depth: " << btree.depth() << endl;
btree.PreorderTravel();
btree.InorderTravel();
btree.PostorderTravel();
btree.LevelorderTravel();
return 0;
}
创建树的结构如下:
A
B C
D E F G
H I J
K
输出结果如下:
Tree size: 11
Tree Depth: 5
PreorderTravel: A B D H K E C F I G J
InorderTravel: H K D B E A I F C G J
PostorderTravel: K H D E B I F J G C A
LevelorderTravel: A B C D E F G H I J K
[Finished in 0.7s]
参考资料:未知。。。