二叉树的几种遍历算法
1.二叉树的前序遍历
2.二叉树的中序遍历
3.二叉树的后序遍历
4 .二叉树的后序遍历
一. 二叉树的前序遍历
前序遍历算法是判断节点是否为空,如果不为空,先访问根节点,再访问左子树,最后访问右子树;
前序的递归: 根->左子树(为空)->右子树。对于每一个子树又可以用同样的访问顺序来遍历。
void PrevOrder()
{
_PrevOrder(_root);
cout << endl;
}
具体实现:
void _PrevOrder(Node *root)
{
Node *cur = root;
if (cur == NULL)
{
return ;
}
cout << cur->_data << " ";
_PrevOrder(cur->_left);
_PrevOrder(cur->_right);
}
前序的非递归算法
对于任意节点cur:
1:判断根节点是否为空,空则返回
2:根节点不为空,输出节点,将根节点入栈,再看cur的左子树是否为空。
3:若cur的左子树不为空,将cur左子树置为当前节点,重复3操作。
4:若cur的左子树为空,将栈顶节点出栈,但不输出,将右子树的节点置为当前节点,看右子树是否为空。
5:不为空重复3操作
6:为空重复4操作
7:直到当前节点为NULL,且栈为空,则遍历结束。
前序
void PrevOrder_NotR()
{
cout << "前序非递归" << endl;
return _PrevOrder_NotR(_root);
cout << endl;
}
`void _PrevOrder_NotR(Node *root)
{
if (root == NULL)//空树
{
return;
}
Node*cur = root;
stack<Node*> s;
while ( !s.empty()||cur!= NULL)
{
//边遍历边将节点压栈
while(cur)
{
cout << cur->_data << " ";
s.push(cur);//根节点入栈
cur = cur->_left;
}
//说明此时左子树已经遍历完了,要遍历要遍历右子树
if (!s.empty())
{
cur = s.top();//取栈顶元素
s.pop();//出栈
cur = cur->_right;
}
}
cout << endl;
}
二:二叉树的中序遍历****
二叉树的中序遍历算法:先访问左子树,再访问根节点,最后访问右子树。
中序:
void InOrder()
{
_InOrder(_root);
cout << endl;
}
实现:
void _InOrder(Node *root)
{
Node *cur = root;
if (cur == NULL)
{
return;
}
_InOrder(cur->_left);
cout << cur->_data << " ";
_InOrder(cur->_right);
}
中序的非递归算法:
对于任意节点cur:
1:cur是否为空若为空返回。
2:cur不为空,判断cur的左子树是否为空,若不为空,将cur入栈,将cur的左子树置为当前节点。并对当前节点进行相同操作。
3:cur的左子树为空,输出cur,并将cur的右子树当前节点,看是否为空。
4:不为空重复2和3操作。
5:为空,则执行出栈操作,输出栈顶结点,并将右孩子置为当前节点,看是否为空重复3和4操作。
6:直到当前节点P为NULL并且栈为空,则遍历结束
非递归的实现:
void _InOrder_NotR(Node*root)
{
Node*cur = root;
if (cur == NULL)
{
return;
}
stack<Node *> s;
while (cur!= NULL||!s.empty())
{
//一直遍历到左子树的最下面
while (cur)
{
s.push(cur);
cur = cur->_left;
}
//说明左子树已经遍历完了;这时需要出栈
if (!s.empty())
{
cur = s.top();
s.pop();
cout << cur->_data << " ";
//遍历右子树
cur = cur->_right;
}
}
cout << endl;
}
三:二叉树的后序遍历:
后序遍历算法:根节点->右子树->左子树
后序的递归:
void PosOrder()
{
_PosOrder(_root);
cout << endl;
}
实现:
void _PosOrder(Node *root)
{
Node *cur = root;
if (cur == NULL)
{
return;
}
_PosOrder(cur->_right);
cout << cur->_data << " ";
_PosOrder(cur->_left);
}
后序的非递归算法:
对于任意节点cur:
1:cur是否为空若为空返回。
2:cur不为空,判断cur的右子树是否为空,若不为空,将cur入栈,将cur的右子树置为当前节点。并对当前节点进行相同操作。
3:cur的右子树为空,输出cur,并将cur的左子树当前节点,看是否为空。
4:不为空重复2和3操作。
5:为空,则执行出栈操作,输出栈顶结点,并将左孩子置为当前节点,看是否为空重复3和4操作。
6:直到当前节点P为NULL并且栈为空,则遍历结束
非递归的实现:
//后序非递归
void _PosOrder_NotR(Node*root)
{
Node*cur = root;
if (cur == NULL)//空树
{
return;
}
stack<Node*>s;
while (!s.empty() || cur!=NULL)
{
//一直遍历右子树的最下面,边遍历边将节点压栈
while (cur)
{
s.push(cur);
cur=cur->_right;
}
if (!s.empty())
{
//右子树已经遍历完了,
cur = s.top();
s.pop();
cout << cur->_data << " ";
//遍历左子树
cur = cur->_left;
}
}
cout << endl;
}
四:二叉树的层序遍历:
我们可以利用队的先进先出的性质,具体实现是,先遍历当前层,入队,然后遍历下一层。置到结束:
实现:
void _LevelOeder(Node *root)
{
queue<Node *> q;
if (root == NULL)
{
return;
}
if (root)
{
q.push(root);//把根节点入队
}
while (!q.empty())
{
Node*front = q.front();
cout << front->_data << " ";
q.pop();
if (front->_left)
q.push(front->_left);//左子树入队
if (front->_right)
q.push(front->_right);//右子树入队
}
cout << endl;
}
五:实现及其测试函数:
.h文件
#pragma once
#include<queue>
#include<stack>
#include<assert.h>
using namespace std;
template<class T>
struct BinaryTreeNode
{
T _data;//数据
BinaryTreeNode<T>* _left;//左节点
BinaryTreeNode<T>* _right;//右节点
BinaryTreeNode(const T&x =T())
:_data(x)
, _left(NULL)
, _right(NULL)
{}
};
template<class T>
class BinaryTree
{
typedef BinaryTreeNode<T> Node;
public:
BinaryTree()
:_root(NULL)
{}
BinaryTree(const BinaryTree<T> &t)
{
_root = _copy(t._root);
}
BinaryTree<T>&operator = (BinaryTree<T> &t)
{
//BinaryTree<T> tmp(t._root);
swap(_root, t._root);
return *this;
}
~BinaryTree()
{
_Destroy(_root);
}
BinaryTree(const T*a, size_t n, const T&invalued = T())
{
size_t indes = 0;
_root = _CreatTree(a, n, indes, invalued);//创建一个二叉树
}
//数节点的个数
size_t Size()
{
return _Size(_root);
}
//深度
size_t Depth()
{
return _Depth(_root);
}
//叶子节点的个数
size_t LeftSize()
{
return _LeftSize(_root);
}
//获取k的节点
int GetkLevel(Node *root, int k)
{
if (root == NULL||k<1)
{
return 0;
}
if (k == 1)
{
return 1;
}
int leftGetkLevel = GetkLevel(root->_left, k - 1);
int rightGetkLevel = GetkLevel(root->_right, k - 1);
return (leftGetkLevel + rightGetkLevel);
}
//前序
void PrevOrder()
{
_PrevOrder(_root);
cout << endl;
}
//前序非递归
void PrevOrder_NotR()
{
cout << "前序非递归" << endl;
return _PrevOrder_NotR(_root);
cout << endl;
}
//中序
void InOrder()
{
_InOrder(_root);
cout << endl;
}
//中序非递归
void InOrder_NotR()
{
cout << "中序非递归" << endl;
return _InOrder_NotR(_root);
cout << endl;
}
//后序
void PosOrder()
{
_PosOrder(_root);
cout << endl;
}
//后序非递归
void PosOrder_NotR()
{
cout << "后序非递归" << endl;
return _PosOrder_NotR(_root);
cout << endl;
}
//层序
void LevelOrder()
{
_LevelOeder(_root);
cout << endl;
}
protected:
Node*_CreatTree(const T*a, size_t n, size_t &indes, const T&invalued)
{
assert(a);
Node* root = NULL;
if (indes<n && a[indes] != invalued)
{
root = new Node(a[indes]);//创建根节点
root->_left = _CreatTree(a, n,++indes,invalued);
root->_right= _CreatTree(a, n,++indes,invalued);
}
return root;
}
//拷贝
Node *_copy(Node *node)
{
Node*cur = node;
Node root = NULL;//
if (cur)
{
root = new Node(cur->_data);//创建新节点
root->_left = _copy(cur->_left);//递归调用
root->_right = _copy(cur->_right);//递归调用
}
return root;
}
//删除
void _Destroy(Node *node)
{
Node* del = node;
if (del)
{
_Destroy(del->_left);
_Destroy(del->_right);
delete del;
del = NULL;
}
}
//树节点的个数
size_t _Size(Node *root)
{
if (root == NULL)
{
return 0;
}
return _Size(root->_left) + _Size(root->_right) + 1;
}
//深度
size_t _Depth(Node *root)
{
Node *cur = root;
if (cur == NULL)
{
return 0;
}
//比较左子树和右子树的大小
return 1 + (_Depth(cur->_left) > _Depth(cur->_right)
? _Depth(cur->_left) : _Depth(cur->_right));
}
//叶子节点的个数
size_t _LeftSize(Node *root)
{
Node*cur = root;
if (NULL == cur)//空树
{
return 0;
}
if (cur->_left == NULL&&cur->_right == NULL)//只有根节点
{
return 1;
}
return _LeftSize(cur->_left)+_LeftSize(cur->_right);//左子树与右子树的和
}
//前序
void _PrevOrder(Node *root)
{
Node *cur = root;
if (cur == NULL)
{
return ;
}
cout << cur->_data << " ";
_PrevOrder(cur->_left);
_PrevOrder(cur->_right);
}
//前序非递归
void _PrevOrder_NotR(Node *root)
{
if (root == NULL)//空树
{
return;
}
Node*cur = root;
stack<Node*> s;
while ( !s.empty()||cur!= NULL)
{
//边遍历边将节点压栈
while(cur)
{
cout << cur->_data << " ";
s.push(cur);//根节点入栈
cur = cur->_left;
}
//说明此时左子树已经遍历完了,要遍历要遍历右子树
if (!s.empty())
{
cur = s.top();//取栈顶元素
s.pop();//出栈
cur = cur->_right;
}
}
cout << endl;
}
//中序
void _InOrder(Node *root)
{
Node *cur = root;
if (cur == NULL)
{
return;
}
_InOrder(cur->_left);
cout << cur->_data << " ";
_InOrder(cur->_right);
}
//中序非递归
void _InOrder_NotR(Node*root)
{
Node*cur = root;
if (cur == NULL)
{
return;
}
stack<Node *> s;
while (cur!= NULL||!s.empty())
{
//一直遍历到左子树的最下面
while (cur)
{
s.push(cur);
cur = cur->_left;
}
//说明左子树已经遍历完了;这时需要出栈
if (!s.empty())
{
cur = s.top();
s.pop();
cout << cur->_data << " ";
//遍历右子树
cur = cur->_right;
}
}
cout << endl;
}
//后序
void _PosOrder(Node *root)
{
Node *cur = root;
if (cur == NULL)
{
return;
}
_PosOrder(cur->_right);
cout << cur->_data << " ";
_PosOrder(cur->_left);
}
//后序非递归
void _PosOrder_NotR(Node*root)
{
Node*cur = root;
if (cur == NULL)//空树
{
return;
}
stack<Node*>s;
while (!s.empty() || cur!=NULL)
{
//一直遍历右子树的最下面,边遍历边将节点压栈
while (cur)
{
s.push(cur);
cur=cur->_right;
}
if (!s.empty())
{
//右子树已经遍历完了,
cur = s.top();
s.pop();
cout << cur->_data << " ";
//遍历左子树
cur = cur->_left;
}
}
cout << endl;
}
//层序
void _LevelOeder(Node *root)
{
queue<Node *> q;
if (root == NULL)
{
return;
}
if (root)
{
q.push(root);//把根节点入队
}
while (!q.empty())
{
Node*front = q.front();
cout << front->_data << " ";
q.pop();
if (front->_left)
q.push(front->_left);//左子树入队
if (front->_right)
q.push(front->_right);//右子树入队
}
cout << endl;
}
protected:
Node *_root;
};
void TestBinaryTree()
{
int a1[10] = { 1, 2, 3, '#', '#', 4, '#', '#', 5, 6 };
size_t sz = sizeof(a1) / sizeof(a1[0]);
BinaryTree<int> t(a1, sz, '#');
BinaryTree<int> t1;
t1 = t;//调赋值运算符的重载
cout << t1.Size() << endl;
cout << t1.Depth() << endl;
cout << t1.LeftSize() << endl;
cout << t1.LeftSize() << endl;
t1.PrevOrder();
t1.InOrder();
t1.PosOrder();
t1.LevelOrder();
t1.PrevOrder_NotR();
t1.InOrder_NotR();
t1.PosOrder_NotR();
}
.cpp文件
#include<iostream>
#include"BinaryTree.h"
using namespace std;
int main()
{
TestBinaryTree();
system("pause");
return 0;
}