<一>深度优先搜索(Depth-First Search—DFS)是指按照深度方向搜索,它类似于树的先根遍历,是树的先根遍历的推广。
深度优先搜索图的基本思想是:
假设图G初态为所有顶点未被访问(visited[i]=false),从G中任选一顶点vi :
⑴、从该顶点vi出发,首先访问vi,并置visited [vi ]=true;
⑵、然后依次搜索vi的每一个邻接点vj ;
⑶、若vj未被访问过,则以vj为新的初始出发点,重复⑴
若vj已被访问过,则返回到vi另一个邻接点,重复⑶
⑷、如果经过⑴、⑵、⑶后,图中仍有未被访问的顶点,再从中任选一顶点,重复⑴、⑵、⑶,直至所有顶点都被访问过,遍历结束。
<二>广度优先搜索遍历图(树的层次遍历的推广)
1. 从图中某顶点v出发,在访问v之后,
2. 依次访问v的各个未曾被访问过的邻接点,
3. 然后分别从这些邻接点出发依次访问它们的邻接点,并使“先被访问的顶点的邻接点”先于“后被访问的顶点的邻接点”被访问,直至图中所有已经被访问的顶点的邻接点都被访问到;
4. 若图中尚有顶点未曾被访问,则另选图中一个未曾被访问的顶点作起始点,访问该顶点,继续过程2、3,直至图中所有顶点都被访问到为止。
(1)为避免重复访问, 需要一个辅助数组 visited[ n],给被访问过的顶点加标记。
(2)为了实现逐层(按顶点的路径长度递增)访问, 算法中需使用了一个队列,以记忆正在访问的这一层和下一层的顶点,以便于向下一层访问。
#include
#include
#define MAX_VERTEX_NUM 20
typedef int InfoType;
typedef int VertexType;
typedef enum{DG,DN,UDG,UDN}GraphKind;
# define MAXQSIZE 100
typedef int QElemType ;//队列
typedef struct//队列
{
QElemType *base; // 动态分配存储空间
int front; // 头指针,指向队列头元素
int rear; // 尾指针,指向 队列尾元素的下一个位置
}SqQueue;
typedef struct ArcNode//图
{
int adjex;//该弧所指向的顶点的位置
struct ArcNode *nextarc;//指向下一条弧的指针
InfoType *info;//该弧相关信息的指针
}ArcNode;
typedef struct VNode
{
VertexType data;//顶点信息
ArcNode *firstarc;//指向第一条依附该顶点的弧的指针
}VNode,AdjList[MAX_VERTEX_NUM];
typedef struct
{
AdjList vertices;//顶点
int vexnum,arcnum;//图的当前顶点数和弧数
GraphKind kind;//图的种类标志
}ALGraph;
int LocateVex(ALGraph G, int v)//确定v在G中位置,即顶点在G.vertices中的序号
{
int i;
for(i=0;i
if (G.vertices[i].data==v) return i;
}
return -1;
}
// ###################生成图G的存储结构-邻接表###############################################
void CreateGraph(ALGraph &G)
{
int k,sv,tv,i,j;
cout<<"请输入图的顶点数(eg:5)";
cin>>G.vexnum;
cout<<"请输入图的弧数(eg:6)";
cin>>G.arcnum;
// cout<<"请输入图的类型(eg:)";
// cin>>G.kind;// 输入顶点数、边数和图类:1
for(k=0;k
cout<<"请输入图的顶点信息";
cin>>G.vertices[k].data;// 输入顶点
G.vertices[k].firstarc=NULL;//初始化链表头指针为"空"
}
cout<<"请输入该图的弧(v1-->v2),例如:(v1=1,v2=3),(v1=2,v2=4)"< for(k=0;k i = LocateVex(G, sv); ArcNode *p; //################有向表的深度优先遍历##################################################################### void DFSTraverse(ALGraph G) //#############广度优先搜索遍历###################################################################### return 0; int EnQueue(SqQueue &Q,QElemType e)// 插入元素e为Q的新的队尾元素 int DeQueue(SqQueue &Q,QElemType &e)// 若队列不空,则删除Q的队头元素,用e返回其值,并返回OK; 否则返回ERROR { void BFSTraverse(ALGraph G) //###############main函数#################
cout<<"请输入第"<
cout<<"请输入第"<
cout<
j = LocateVex(G, tv); // (比较)确定sv和tv在G中位置,即顶点在G.vertices中的序号
while((i<0||i>=G.vexnum)||(j<0||j>=G.vexnum)) //if (sv,tv) illegal,again
{
cout<<"请输入第"<
cout<<"请输入第"<
cout<
j = LocateVex(G, tv); // (比较)确定sv和tv在G中位置,即顶点在G.vertices中的序号
} //while end
p=(ArcNode*)malloc(sizeof(ArcNode));
if(!p)
{
cout<<"Overflow!"; // 存储分配失败
return ;
}
p->adjex=j;// 对弧结点赋邻接点"位置“
p->nextarc=G.vertices[i].firstarc;//头插法,将tv结点插入到第i个单链表中
p->info=NULL;
G.vertices[i].firstarc=p;// 插入链表G.vertices[i]
}
}
void DFS(ALGraph G,int v,int visited[])
{
int w;
ArcNode *p;
cout<
visited[v]=1;
p=G.vertices[v].firstarc;
if(p!=NULL)
w=p->adjex;//w是v的下一个邻接点的位置,即第v+1个顶点的下一个顶点是第w+1个顶点;
if (p!=NULL)//如果有邻接点w
{
if(visited[w]==0)//如果w没访问过
{
DFS(G,w,visited);
}
else//若访问过,则访问v的下一个邻接点,并返回至判断是否存在该邻接点
{
p=p->nextarc;//G.vertices[v].firstarc=G.vertices[v].firstarc->nextarc;
if(p!=NULL) w=p->adjex;//w=G.vertices[v].firstarc->adjex;
}
}
}
{
int v,visted[MAX_VERTEX_NUM];
for (v=0;v
visted[v]=0;
}
for (v=0;v
if(visted[v]==0)
DFS(G,v,visted);
}
}
//~~~~~~~~~~~~辅助队列~~~~~~~~~~~~~~~~~~~~~~~~~
int InitQueue (SqQueue &Q)// 构造一个空队列Q
{
Q.base=(QElemType*)malloc(MAXQSIZE*sizeof(QElemType));
if(!Q.base)
{
cout<
}
Q.front=Q.rear=0;
return 1;
}
{
if ((Q.rear+1)%MAXQSIZE==Q.front)//①判满
{
cout<<"Error ! The SqQeueu is full ! ";
return 0;
}
Q.base[Q.rear]=e;// ②插入队尾
Q.rear=(Q.rear+1)%MAXQSIZE;//③队尾指针后移
return 1;
}
if (Q.rear==Q.front)
{
cout<
}
e=Q.base[Q.front];
Q.front=(Q.front+1)%MAXQSIZE;
return(e);
}
int QueueEmpty(SqQueue Q)
{
if(Q.front==Q.rear)
return (1);
else
return (0);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void BFS(ALGraph G,int v,int visited[],SqQueue &Q)
{
int u,w;
ArcNode *p;
cout<
visited[v]=1;
EnQueue(Q,v);// v入队列
while (!QueueEmpty(Q))
{
DeQueue(Q,u);// 队头元素出队并置为u
p=G.vertices[v].firstarc;
if(p!=NULL)
w=p->adjex;
for (;p!=NULL;)
{
if (visited[w]==0)
{
cout<
visited[w]=1;
EnQueue(Q, w); // 访问的顶点w入队列
}
p=p->nextarc;
if (p!=NULL)
w=p->adjex;
}
}
}
{
SqQueue Q;
int v,visted[MAX_VERTEX_NUM];
for (v=0;v
visted[v]=0;//初始化访问标志
}
InitQueue(Q);// 置空的辅助队列Q
for ( v=0; v
if(visted[v]==0)// v 尚未访问
BFS(G,v,visted,Q);// 调用BFS()
}
}
void main()
{
ALGraph G;
CreateGraph(G);
cout<<"深度优先遍历如下:"<
cout<<"End !"<
cout<<"End !"<