基本概念
图的遍历定义:
从已给的连通图中某一顶点出发,沿着一些边访遍图中所有的顶点,且使每个顶点仅被访问一次,就叫做图的遍历,它是图的基本运算。
遍历实质:找每个顶点的邻接点的过程。
图的特点:
图中可能存在回路,且图的任一顶点都可能与其它顶点想通,在访问完某个顶点之后可能会沿着某些边又回到了曾经访问过的顶点
如何避免重复访问?
设置辅助数组visited [n],用来标记每个被访问过的顶点。初始为0,被访问过就是1
深度优先搜索
深度优先搜索的遍历类似于树的先序遍历,及根左右的方式遍历,图的深度优先是树的先序遍历的推广
广度优先搜索
从图的某一结点出发,首先一次访问该结点的所有邻接点,再按这些顶点被访问的先后顺序访问与他们相邻接的所有未被访问的顶点,重复此过程。
其实类似于树的顺序遍历。
连通图的广度遍历:
遍历顺序:
非连通图的广度遍历:
DFS与BFS算法效率比较
- 空间复杂度相同,都是O(n)(DFS运用递归,BFS接用队列)
- 时间复杂度只与存储结构(邻接矩阵或邻接表)有关,而与搜索路径无关,邻接矩阵复杂的为O(n ^ n),邻接表时间复杂读为O(n + e)
邻接矩阵的深搜与广搜
代码实现:
#include <iostream>
#include <queue>
using namespace std;
#define MaxInt 0 //表示极大值,即无穷
#define MVNum 100 //最大顶点数
typedef char VerTexType; //设顶点的数据类型为字符型
typedef int ArcType; //假设边的权值类型为整形
bool visited[15];
typedef struct{
VerTexType vexs[MVNum]; //顶点表
ArcType arcs[MVNum][MVNum]; //邻接矩阵
int vexnum,arcnum; //图的当前点数和边数
}AMGraph;//Adjacency Matrix Graph
//在图中查找顶点
int LocateVex(AMGraph G,int u){
//在图G中查找顶点u,存在则返回顶点表中的下标;否则返回-1
int i;
for(i = 1;i<=G.vexnum;i++)
if(u==G.vexs[i])
return i;
return -1;
}
//采用邻接矩阵表示法,创建无向网G
bool CreateUDN(AMGraph &G)
{
char v1,v2;
int w,i,j,k;
cout<<"分别输入总顶点数、总边数:"<<endl;
cin>>G.vexnum>>G.arcnum; //输入总顶点数,总边数
cout<<"输入点的信息:"<<endl;
for(i=1;i<=G.vexnum;i++)//依次输入点的信息
cin>>G.vexs[i];
for(i=1;i<=G.vexnum;i++)
for(j=1;j<=G.vexnum;j++)
G.arcs[i][j]=MaxInt;//初始化邻接矩阵,边的权值均置为极大值MAXInt
cout<<"请输入一条边所依附的两个顶点、权值:"<<endl;
for(k=1;k<=G.arcnum;k++){//构造邻接矩阵
cin>>v1>>v2>>w;//输入一条边所依附的顶点及边的权值
int i=LocateVex(G,v1);
int j=LocateVex(G,v2);//确定v1和v2在G中的位置,即顶点数组的下标
G.arcs[i][j]=w; //边<v1,v2>权值置为w
G.arcs[j][i]=G.arcs[i][j];
//边<v1,v2>的对称边<v2,v1>的权值为w
}//for
return true;
}//CreateUDN
void DFS(AMGraph G, int v)
{
cout << v << " ";
visited[v] = true;
for(int w = 1; w <= G.vexnum; w ++ )
if( (G.arcs[v][w] != 0 ) && (!visited[w]))
DFS(G, w);
//w是v的邻接点,如果w未访问,则递归调用DFS
}
void BFS(AMGraph G, int v)
{
for(int i = 1; i <= G.vexnum; i ++)
visited[i] = false;
cout << v << " ";
visited[v] = true;
queue<int> Q;
Q.push(v);
while(!Q.empty())
{
int t = Q.front();
Q.pop();
for(int w = 1; w <= G.vexnum; w ++ )
{
if(G.arcs[t][w] == 1 && visited[w] == false)
{
visited[w] = true;
cout << w << " ";
Q.push(w);
}
}
}
}
int main()
{
AMGraph G;
CreateUDN(G);
cout<<"邻接矩阵为:"<<endl;
for(int i = 1; i <= G.vexnum;i ++)
{
for(int j = 1; j <= G.vexnum; j ++){
cout<<G.arcs[i][j]<<" ";
}
cout << endl;
}//for
cout << "DFS遍历邻接矩阵结果为:" << endl;
DFS(G, 2);
cout << endl;
cout << "BFS遍历邻接矩阵结果为: " <<endl;
BFS(G, 1);
a
return 0;
}
邻接表的深搜与广搜
#include<iostream>
#include<queue>
using namespace std;
#define MVNum 100 //最大顶点数
bool visited[15];
typedef struct ArcNode{
int adjvex; //该边所指向的顶点的位置
struct ArcNode *nextarc;//指向下一条边的指针
}ArcNode;
//顶点的结点结构
typedef struct VNode{
char data;//顶点信息、
ArcNode *firstarc;//指向第一条依附该顶点的边的指针
}VNode,AdjList[MVNum];//AdjList表示邻接表类型
//图的结构定义
typedef struct{
AdjList vertices; //定义一个数组vertices,是vertex的复数形式
int vexnum,arcnum; //图的当前顶点数和弧数
}ALGraph;
int LocateVex(ALGraph G,int u){
//在图G中查找顶点u,存在则返回顶点表中的下标;否则返回-1
int i;
for(i=1;i<=G.vexnum;i++)
if(u == G.vertices[i].data)
return i;
return -1;
}
//创建无向图G
bool CreateUDG(ALGraph &G){
cout << "请输入总结点数和总边数:" << endl;
cin>>G.vexnum>>G.arcnum;//输入总顶点数,总边数
cout << " 输入各顶点值: " << endl;
for(int i = 1;i <= G.vexnum;i++)
{//输入各顶点,构造表头结点表
cin>>G.vertices[i].data;//输入顶点值
G.vertices[i].firstarc=NULL;//初始化表头结点的指针域
}//for
getchar();
//输入各边,构造邻接表
cout << "输入一条边依附的两个顶点值"<<endl;
for(int k=1;k<=G.arcnum;k++){
char v1,v2;
cin>>v1>>v2; //输入一条边依附的两个顶点
getchar();
int i=LocateVex(G,v1);
int j=LocateVex(G,v2); //确定顶点在G.vertices中的序号
ArcNode *p1=new ArcNode; //生成一个新的边结点*p1
p1->adjvex=j; //邻接点序号为j
//头插法将新结点*p1插入顶点vi的边表头部
p1->nextarc=G.vertices[i].firstarc;
G.vertices[i].firstarc=p1;
ArcNode *p2=new ArcNode;
p2->adjvex=i; //邻接点序号为i
//头插法插入p2 ,因为是无向网,所以是两条
p2->nextarc=G.vertices[j].firstarc;
G.vertices[j].firstarc=p2;
}//for
return true;
}//CreateUDG
void DFS(ALGraph G, int v)
{
ArcNode *p;
p = new ArcNode;
cout << v << " ";
visited[v] = true;
p = G.vertices[v].firstarc;
while(p != NULL)
{
int w = p->adjvex;
if(!visited[w])
DFS(G, w);
p = p->nextarc;
}
}
void BFS(ALGraph G, int v)
{
int i = 0;
for(int i = 1; i <= G.vexnum; i++)
visited[i] = false;
cout << v << " ";
visited[v] = true;
queue<int> Q;
Q.push(v);
ArcNode *p;
p = new ArcNode;
while(!Q.empty())
{
int t = Q.front();
Q.pop();
for(p = G.vertices[t].firstarc; p != NULL;p = p->nextarc)
{
if(! visited[p->adjvex])
{
cout << p->adjvex << " ";
visited[p->adjvex] = true;
Q.push(p->adjvex);
}
}
}
}
int main()
{
ALGraph G;
ArcNode *p;
CreateUDG(G);
cout << "输出邻接表: " <<endl;
for(int i = 1; i<= G.vexnum; i++)
{
cout << G.vertices[i].data;
for(p = G.vertices[i].firstarc; p != NULL; p = p->nextarc)
printf("->%d", p->adjvex);
cout << endl;
}
cout << endl;
cout << "DFS遍历结果:" << endl;
DFS(G, 2);
cout << endl;
cout << " BFS遍历结果:" << endl;
BFS(G, 1);
return 0;
}