遍历概念
所谓遍历(Traversal)是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问。访问结点所做的操作依赖于具体的应用问题。
遍历是二叉树上最重要的运算之一,是二叉树上进行其它运算之基础。
遍历方案
- 遍历方案
从二叉树的递归定义可知,一棵非空的二叉树由根结点及左、右子树这三个基本部分组成。因此,在任一给定结点上,可以按某种次序执行三个操作:
(1)访问结点本身(N),
(2)遍历该结点的左子树(L),
(3)遍历该结点的右子树(R)。
以上三种操作有六种执行次序:
NLR、LNR、LRN、NRL、RNL、RLN。
注意:
前三种次序与后三种次序对称,故只讨论先左后右的前三种次序。 - 三种遍历的命名
根据访问结点操作发生位置命名:
① NLR:前序遍历(PreorderTraversal亦称(先序遍历))
——访问结点的操作发生在遍历其左右子树之前。
② LNR:中序遍历(InorderTraversal)
——访问结点的操作发生在遍历其左右子树之中(间)。
③ LRN:后序遍历(PostorderTraversal)
——访问结点的操作发生在遍历其左右子树之后。
- 由于被访问的结点必是某子树的根,所以N(Node)、L(Left subtlee)和R(Right subtree)又可解释为根、根的左子树和根的右子树。NLR、LNR和LRN分别又称为先根遍历、中根遍历和后根遍历。
遍历算法
- 中序遍历的递归算法定义:
若二叉树非空,则依次执行如下操作:
(1)遍历左子树;
(2)访问根结点;
(3)遍历右子树。 - 先序遍历的递归算法定义:
若二叉树非空,则依次执行如下操作:
(1) 访问根结点;
(2) 遍历左子树;
(3) 遍历右子树。 - 后序遍历得递归算法定义:
若二叉树非空,则依次执行如下操作:
(1)遍历左子树;
(2)遍历右子树;
(3)访问根结点。
代码实现
- 建立二叉树
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <stack>
#define N 10
#define max(first,second,third) (first>second?first:second)>third?(first>second?first:second):third
#define max_dp(first,second) (first>second?first:second)
#define min(first,second) (first<second?first:second)
template<typename T> struct Result
{
T distance,depth;
Result(T dis=0,T dep=0):distance(dis),depth(dep){}
};
template<typename T> struct BNode
{
T m_data;
BNode<T>* rchild;
BNode<T>* lchild;
BNode<T>* parent;
int ltag;
int rtag;
BNode(T data=0):m_data(data),rchild(NULL),lchild(NULL),parent(NULL),ltag(0),rtag(0){}
};
template<typename T> struct BTree
{
BNode<T>* m_root;
BNode<T>* index;
BNode<T>* pre;
T m_data;
BTree(BNode<T>* root=NULL,T data=0):m_root(root),m_data(data),pre(NULL){}
void insert_node(BNode<T>** root,BNode<T>* p)
{
if(*root==NULL)
{
*root=p;
return;
}
if(p->m_data<(*root)->m_data&&(*root)->lchild==NULL)
{
p->parent=*root;
(*root)->lchild=p;
return;
}
else if(p->m_data>(*root)->m_data&&(*root)->rchild==NULL)
{
p->parent=*root;
(*root)->rchild=p;
return ;
}
if(p->m_data<(*root)->m_data)
{
insert_node(&((*root)->lchild),p);
}
else
{
insert_node(&((*root)->rchild),p);
}
}
/*插入节点*/
void insert(const T& data)
{
BNode<T>* inode=new BNode<T>(data);
insert_node(&m_root,inode);
}
};
- 先序遍历
template<typename T> struct Result
{
T distance,depth;
Result(T dis=0,T dep=0):distance(dis),depth(dep){}
};
template<typename T> struct BNode
{
T m_data;
BNode<T>* rchild;
BNode<T>* lchild;
BNode<T>* parent;
int ltag;
int rtag;
BNode(T data=0):m_data(data),rchild(NULL),lchild(NULL),parent(NULL),ltag(0),rtag(0){}
};
- 中序遍历
/*递归中序遍历*/
void in_order(BNode<T>* node)
{
if(node==NULL)
{
return;
}
in_order(node->lchild);
std::cout<<node->m_data<<" ";
in_order(node->rchild);
}
/*非递归中序遍历*/
void in_order()
{
if(m_root==NULL)
{
return;
}
std::stack<BNode<T>*> s;
BNode<T>* start=m_root;
while(start||!s.empty())
{
while(start)
{
s.push(start);
start=start->lchild;
}
if(!s.empty())
{
start=s.top();
s.pop();
std::cout<<"current data: "<<start->m_data;
std::cout<<" pre: "<<get_pre(start)<<" post: "<<get_suc(start);
if(start->parent)
{
std::cout<<" father node data: "<<start->parent->m_data;
}
std::cout<<std::endl;
start=start->rchild;
}
}
std::cout<<std::endl;
}
- 后序遍历
/*递归后序遍历*/
void post_order(BNode<T>* node)
{
if(node==NULL)
{
return;
}
post_order(node->lchild);
post_order(node->rchild);
std::cout<<node->m_data<<" ";
}
/*非递归后序遍历*/
void post_order()
{
if(m_root==NULL)
{
return;
}
std::stack<BNode<T>*> s;
BNode<T>* start=m_root;
BNode<T>* visit=NULL;
while(start||!s.empty())
{
while(start)
{
s.push(start);
start=start->lchild;
}
if(!s.empty())
{
start=s.top();
if(start->rchild&&(start->rchild)!=visit)//有右孩子先不弹栈,将右孩子压栈然后再遍历才弹栈
{
start=start->rchild;
s.push(start);
start=start->lchild;
}
else //没有右孩子才开始弹栈
{
start=s.top();
s.pop();
visit=start;
std::cout<<"current data: "<<start->m_data;
std::cout<<" pre: "<<get_post_pre(start)<<" post: "<<get_post_suc(start);
if(start->parent)
{
std::cout<<" father node data: "<<start->parent->m_data;
}
std::cout<<std::endl;
start=NULL;
}
}
}
std::cout<<std::endl;
}
- 层次遍历
/*层次遍历*/
void level_order()
{
std::cout<<__func__<<":"<<__LINE__<<std::endl;
std::queue<BNode<T>*> restore;
if(m_root==NULL)
{
return;
}
restore.push(m_root);
while(!restore.empty())
{
BNode<T>* p=restore.front();
restore.pop();
std::cout<<p->m_data<<" ";
if(p->lchild)
{
restore.push(p->lchild);
}
if(p->rchild)
{
restore.push(p->rchild);
}
}
}
/*按行打印二叉树*/
void print_inline()
{
std::cout<<__func__<<":"<<__LINE__<<std::endl;
std::queue<BNode<T>*> restore;
if(m_root==NULL)
{
return;
}
restore.push(m_root);
int nextLevel=0;
int toBePrinted=1;
while(!restore.empty())
{
BNode<T>* p=restore.front();
std::cout<<p->m_data<<" ";
if(p->lchild)
{
restore.push(p->lchild);
nextLevel++;
}
if(p->rchild)
{
restore.push(p->rchild);
nextLevel++;
}
restore.pop();
if(--toBePrinted==0)
{
std::cout<<std::endl;
toBePrinted=nextLevel;
nextLevel=0;
}
}
}