[转】二叉树与图的深度优先和广度优先遍历

图的深度优先搜索法是树的先根遍历的推广,它的基本思想是:从图G的某个顶点v0出发,访问v0,然后选择一个与v0相邻且没被访问过的顶点vi访 问,再从vi出发选择一个与vi相邻且未被访问的顶点vj进行访问,依次继续。如果当前被访问过的顶点的所有邻接顶点都已被访问,则退回到已被访问的顶点 序列中最后一个拥有未被访问的相邻顶点的顶点w,从w出发按同样的方法向前遍历,直到图中所有顶点都被访问。

图的广度优先搜索是树的按层次遍历的推广,它的基本思想是:首先访问初始点vi,并将其标记为已访问过,接着访问vi的所有未被访问过的邻接点 vi1,vi2, …, vi t,并均标记已访问过,然后再按照vi1,vi2, …, vi t的次序,访问每一个顶点的所有未被访问过的邻接点,并均标记为已访问过,依次类推,直到图中所有和初始点vi有路径相通的顶点都被访问过为止。

二叉树的深度优先遍历的非递归的通用做法是采用栈,广度优先遍历的非递归的通用做法是采用队列。

深度优先遍历分为三种:前序,中序,后序。

 

首先我们知道,前序遍历的规则是:

根结点→左子结点→右子结点
中序遍历是:左子结点→根结点→右子结点
后序遍历是:左子结点→右子结点→根结点

已知某二叉树的前序是abdgcefh,中序dgbaechf,则后序是?
那么,对于一棵二叉树,前序遍历的第一个结点一定是这棵树的根结点,即根结点是a。
在中序遍历的顺序dgbaechf中,以a分成左、右两边,左边是dgb,右边是echf。

所以,这棵树现在可以确定如下:
a
/ /
dgb echf

接下来再分别对左子树和右子树进行类似的操作。
对于左子树dgb来说,在前序遍历abdgcefh中找到bdg,证明这子树的根是b,那么现在可以确定的树结构如下:
a
/ /
b echf
/
dg

再看dg,前序遍历中的顺序为dg,所以d是dg这部分子树的根,那么又因为中序遍历的dg顺序也是dg,所以g是右子结点。
即:
a
/ /
b echf
/
d
/
g

现在看echf这部分子树,前序中顺序是cefh,所以子树根结点是c,那么左子结点是e,右子树是hf:
得到:
a
/ /
b c
/ / /
d e hf
/
g

最后只剩下hf部分了,前序遍历中是fh,所以根是f,那么h就是左子结点。
现在得到了整棵树:
a
/ /
b c
/ / /
d e f
/ /
g h

对这棵树再进行后序遍历就行了,结果就是:DGEBHFCA

 

         A

B         C

D        E         F

G          H

 

 

二叉树的排序的阅读方式:

http://www.cnblogs.com/songQQ/archive/2009/10/20/1587126.html

 

图的广度优先遍历

图的广度优先遍历BFS算法是一个分层搜索的过程,和树的层序遍历算法类同,它也需要一个队列以保持遍历过的顶点顺序,以便按出队的顺序再去访问这些顶点的邻接顶点。
1.连通图的广度优先遍历算法思想。
(1)顶点v入队列。
(2)当队列非空时则继续执行,否则算法结束。
(3)出队列取得队头顶点v;访问顶点v并标记顶点v已被访问。
(4)查找顶点v的第一个邻接顶点col。
(5)若v的邻接顶点col未被访问过的,则col入队列。
(6)继续查找顶点v的另一个新的邻接顶点col,转到步骤(5)。直到顶点v的所有未被访问过的邻接点处理完。转到步骤(2)。
【例】下面以图( a )为例说明广度优先搜索的过程。首先从起点 v 1 出发访问 v 1 。 v 1 有两个未曾访问的邻接点 v 2 和 v 3 。先访问 v 2 ,再访问 v 3 。然后再先访问 v 2 的未曾访问过的邻接点 v 4 、 v 5 及 v 3 的未曾访问过的邻接 v 6 和 v 7 ,最后访问 v 4 的未曾访问过的邻接点 v 8 。至此图中所有顶点均已被访问过。得到的顶点访问序列为:
《[转】二叉树与图的深度优先和广度优先遍历》
《[转】二叉树与图的深度优先和广度优先遍历》

2.广度优先遍历算法

(1)邻接矩阵的广度优先遍历算法:
【算法7.1】
void AdjMWGraph::Depth(int v,int visited[])
{  sqQueue<  int>q;        //定义队列queue
q.EnQueue(v);        //顶点v入队列
while(!q.IsEmpty())        //当队列非空时循环
{  v=q.DeQueue();        //出队列得到队头顶点u
cout<<endl<<“顶点”<<v+1<<“权值:”<<Vertices[col];          //访问顶点v
visited[col]=1;//标记顶点v已访问
for(int col=0;col<numV;col++)
if(Edge[v][col]>0;&&Edge[v][col]<MaxWeight&&visite[col]==0)
q.EnQueue(col);
}
cout<<endl<<“end!”<<“endl;
};
邻接矩阵表示图时,搜索一个顶点的所有邻接点需花费O(n)时间,则从n个顶点出发搜索的时间应为O(n2),即BFS算法的时间复杂度是(n2)。

(2)邻接链表的深度优先遍历算法:
【算法7.2】
void AdjTWGraph::BroadFirst(int v, int visited[])
{   int vj;   Edge *p;   SqQueue <int> Q; Q.EnQueue(v);
while(!Q.IsEmpty())               //队列不空,循环
{   v=Q.DeQueue();         //出队并且访问顶点v
cout<<Vertices[v].data<<” “;   visited[v]=1;
p=Vertices[v].adj;             //取v的邻接边结点
while(p!=NULL)   { vj=p->dest;     //取v的邻接点编号vj
if(visited[vj]==0) Q.EnQueue(vj);             //vj未访问,入队
p=p->next;             //取下一个邻接边结点
}
}
}
使用邻接链表来表示图时,其 BFS 算法的时间复杂度为 O(n+e) ,此处 e 为无向图中边的数目或有向图中弧的数目。

    原文作者:数据结构之图
    原文地址: https://blog.csdn.net/higirle_zhao/article/details/5403661
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞