图的深度优先遍历
图的深度遍历原则:
1 如果有可能,访问一个领接的未访问的节点,标记它,并把它放入栈中。
2 当不能执行规则 1 时,如果栈不为空,则从栈中弹出一个元素。
3 如果不能执行规则 1 和规则 2 时,则完成了遍历。
设x是当前被访问顶点,在对x做过访问标记后,选择一条从x出发的未检测过的边(x,y)。若发现顶点y已访问过,则重新
选择另一条从x出发的未检测过的边,否则沿边(x,y)到达未曾访问过的y,对y访问并将其标记为已访问过;然后从y开始搜
索,直到搜索完从y出发的所有路径,即访问完所有从y出发可达的顶点之后,才回溯到顶点x,并且再选择一条从x出发的未检
测过的边。上述过程直至从x出发的所有边都已检测过为止。
邻接表及逆邻接表的存储方法
(1)定义
邻接表是图的一种链式存储结构。类似于树的孩子链表表示法。在邻接表中为图中每个顶点建立一个单链表,用单链表中的一个结点表示依附于该顶点的一条边(或表示以该顶点为弧尾的一条弧),称为边(或弧)结点。特征如下:
1) 为每个顶点建立一个单链表,
2) 第i个单链表中包含顶点Vi的所有邻接顶点。
把同一个顶点发出的边链接在同一个边链表中,链表的每一个结点代表一条边,叫做表结点(边结点),邻接点域adjvex保存与该边相关联的另一顶点的顶点下标 , 链域nextarc存放指向同一链表中下一个表结点的指针 ,数据域info存放边的权。边链表的表头指针存放在头结点中。头结点以顺序结构存储,其数据域data存放顶点信息,链域firstarc指向链表中第一个顶点。
带权图的边结点中info保存该边上的权值。
顶点 Vi 的边链表的头结点存放在下标为 i 的顶点数组中。
在邻接表的边链表中,各个边结点的链入顺序任意,视边结点输入次序而定。
设图中有 n 个顶点,e 条边,则用邻接表表示无向图时,需要 n 个顶点结点,2e 个边结点;用邻接表表示有向图时,若不考虑逆邻接表,只需 n 个顶点结点,e 个边结点。
建立邻接表的时间复杂度为O(n*e)。若顶点信息即为顶点的下标,则时间复杂度为O(n+e)。
(2)邻接表的示例及逆邻接表
在有向图的邻接表中,第 i 个链表中结点的个数是顶点Vi的出度,表结点的adjvex存储的是以当前头结点为弧尾的弦。在所有链表中其邻接点域的值为i的结点的个数是顶点vi的入度。
在有向图的逆邻接表中,第 i 个链表中结点的个数是顶点Vi 的入度,表结点的adjvex存储的是以当前头结点为弧首的弦。
如下为带权图的邻接表:
深度优先遍历代码实现:
#include<iostream>
using namespace std;
int book[101],sum,n,e[101][101],l=0;
void dfs(int cur)
{
int i;
if(l==0) printf("%d",cur),l=1;
else printf(" %d",cur);
sum++;
if(sum==n) return ;
for(i=1;i<=n;i++)
{
if(e[cur][i]==1&&book[i]==0)
{
book[i]=1;
dfs(i);
}
}
}
int main()
{
int i,j,m,a,b;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(i==j) e[i][j]=0;
else e[i][j]=99999999;
for(i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
e[a][b]=1;
e[b][a]=1;
}
book[1]=1;
dfs(1);
}


