如对于上图二叉树:
前序遍历:ABDECFG
中序遍历:DBEAFCG
后序遍历:DEBFGCA
深度遍历:ABDECFG
广度遍历:ABCDEFG
前序遍历:先父节点,再左右节点
递归算法:
void inorder(treenode<T>*root){
if(root==NULL)return;
else{<pre name="code" class="cpp">
cout<<root->ele<<" ";
inorder(root->left);inorder(root->right);}}//递归后序
非递归算法:
非递归算法一般引入堆栈,较递归算法比较复杂,分析如下:
void preorder(treenode<T>*root){
if(root==NULL)return;
stack<treenode<T>* >ss;
while(root!=NULL||!ss.empty()){
if(root!=NULL){
cout<<root->ele<<" ";
ss.push(root);
root=root->left;}
else{
root=ss.top();
ss.pop();
root=root->right;}}}//前序遍历
中序遍历:先左子树再父节点再右子树
递归算法:
void inorder(treenode<T>*root){
if(root==NULL)return;
else{
inorder(root->left);
cout<<root->ele<<" ";
inorder(root->right);}}//递归中序
非递归:也是引入堆栈。算法分析:
void norder(treenode<T>*root){
if(root==NULL)return;
stack<treenode<T>*> heapin;
while(root!=NULL||!heapin.empty()){
if(root!=NULL){heapin.push(root);
root=root->left;}
else{
root=heapin.top();
heapin.pop();
cout<<root->ele<<" ";
root=root->right;}
}
}//中序遍历
//代码段(ii)当root为空时,说明已经到达左子树最下边,这时需要出栈了
//进入右子树,开始新的一轮左子树遍历(这是递归的自我实现)
假设,你面前有一棵二叉树,现要求你写出它的中序遍历序列。如果你对中序遍历理解透彻的话,你肯定先找到左子树的最下边的节点。那么下面的代就是理所当然的:
中序代码段(i)
stack<treenode<T>*> s;
//STL中的栈
//一直遍历到左子树最下边,边遍历边保存根节点到栈中
while
(root)
{
s.push(root);
root
= root->lchild;
}
保存一路走过的根节点的理由是:中序遍历的需要,遍历完左子树后,需要借助根节点进入右子树。代码走到这里,指针p为空,此时无非两种情况:a
当前保存的根节点是叶子节点: b当前保存的根节点无左子树但非叶节点
对于情况b:
由于没有左孩子,根节点就是中序序列中第一个,然后直接是进入右子树:p=p->rchild;在右子树中,又会新一轮的代码段(i)、代码段(ii)……直到栈空且p空。
root=heapin.top();
heapin.pop();
cout<<root->ele<<" ";
root=root->right;
对于a包含叶节点,所以:
a接下来的代码段(ii)这样的:
root=heapin.top();
heapin.pop();
cout<<root->ele<<" ";
<pre name="code" class="cpp"> root=heapin.top();
heapin.pop();
cout<<root->ele<<" ";
a的代码段(ii)也可写成b的理由是:由于是叶子节点,p=-=p->rchild;之后p肯定为空。为空,还需经过新一轮的代码段(i)吗?显然不需。(因为不满足循环条件)那就直接进入代码段(ii)。
所以统一一下
中序代码段(ii)
root=heapin.top();
heapin.pop();
cout<<root->ele<<" ";
root=root->right;
递归:
void postorder(treenode<T>*root){
if(root==NULL)return;
else{
postorder(root->left);
postorder(root->right);
cout<<root->ele<<" ";}}//递归后序
void postorder(treenode<T>*root){
if(root==NULL) return;
treenode<T>*p=NULL;
stack<treenode<T>*>s;
treenode<T>*cu;
s.push(root);
while(!s.empty()){
cu=s.top();
if((cu->left==NULL&&cu->right==NULL)||
(p!=NULL&&(p==cu->left||p==cu->right)))
{
cout<<cu->ele<<" "; //如果当前结点没有孩子结点或者孩子节点都已被访问过
s.pop();
p=cu;
}
else
{
if(cu->right!=NULL)
s.push(cu->right);
if(cu->left!=NULL)
s.push(cu->left);
}}
}//后序
深度遍历算法:
//深度优先遍历
void depthFirstSearch(treenode<T>*root){
stack<treenode<T> *> nodeStack; //使用C++的STL标准模板库
nodeStack.push(root);
treenode<T> *node;
while(!nodeStack.empty()){
node = nodeStack.top();
cout<<node->ele<<" "; //遍历根结点
nodeStack.pop();
if(node->right){
nodeStack.push(node->right); //先将右子树压栈
}
if(node->left){
nodeStack.push(node->left); //再将左子树压栈
}
}
}
广度优先算法:
void breadthFirstSearch(treenode<T>* root){
queue<treenode<T> *> nodeQueue; //使用C++的STL标准模板库
nodeQueue.push(root);
treenode<T> *node;
while(!nodeQueue.empty()){
node = nodeQueue.front();
nodeQueue.pop();
cout<<node->ele<<" ";
if(node->left){
nodeQueue.push(node->left); //先将左子树入队
}
if(node->right){
nodeQueue.push(node->right); //再将右子树入队
}
}
}