您的位置:首页 > 其它

广度优先搜索,图的遍历

2013-03-14 22:00 405 查看
1、 队列
(1) 定义
队列也是一种运算受限的线性表。在这种线性表上,插入限定在表的某一端进行,删除限定在表的另一端进行。允许插入的一端称为队尾,允许删除的一端称为队头。

特点:队列中数据元素的入队和出队过程是按照“先进先出”
的原则进行的。因此,队列又称为“先进先出”的线性表,简称FIFO表。

(2) 实现-链队列
队列的链式存储结构简称为链队。它实际上是一个同时带有首指针和尾指针的单链表。头指针指向表头结点,而尾指针则指向队尾元素。从队尾插入,从队首删除。空的链队对列的判决条件是头指针和尾指针均指向头结点。



链队运算指针变化情况:










2、 广度优先搜索的算法思想
广度优先搜索遍历类似于树的按层次遍历。
对于无向连通图,广度优先搜索是从图的某个顶点v0出发,在访问v0之后,依次搜索访问v0的各个未被访问过的邻接点w1,w2,…。然后顺序搜索访问w1的各未被访问过的邻接点,w2的各未被访问过的邻接点,…。即从v0开始,由近至远,按层次依次访问与v0有路径相通且路径长度分别为1,2,…的顶点,直至连通图中所有顶点都被访问一次。

广度优先搜索的顺序不是唯一的。
具体描述如下:
设图G的初态是所有顶点均未访问,在G中任选一顶点i作为初始点,则广度优先搜索的基本思想是:
(1)从图中的某个顶点V出发,访问之;并将其访问标志置为已被访问,即visited[i]=1;
(2)依次访问顶点V的各个未被访问过的邻接
点,将V的全部邻接点都访问到;
(3)分别从这些邻接点出发,依次访问它们的未被访问过的邻接点,并使“先被访问的顶
点的邻接点”先于“后被访问的顶点的邻接点”被访问,直到图中所有已被访问过的顶
点的邻接点都被访问到。

依此类推,直到图中所有顶点都被访问完为止。
广度优先搜索在搜索访问一层时,需要记住已被访问的顶点,以便在访问下层顶点时,从已被访问的顶点出发搜索访问其邻接点。所以在广度优先搜索中需要设置一个队列Queue,使已被访问的顶点顺序由队尾进入队列。在搜索访问下层顶点时,先从队首取出一个已被访问的上层顶点,再从该顶点出发搜索访问它的各个邻接点。
如下图(c)中为对图(a)的遍历:



按照广度优先算法,其遍历顺序为:




3、 广度优先搜索算法的C语言描述








4、 广度优先搜索算法的C语言实现
#include"stdio.h"

#define MAX_VERTEX_NUM 20

#include "conio.h"

#include "stdlib.h"

typedef char VertexType;

//我们依然用邻接表来作图的存储结构

typedef struct ArcNode{

intadjvex;

structArcNode *nextarc;

intinfo;

}ArcNode; //表结点类型

typedef struct VNode{

VertexTypedata;

ArcNode*firstarc;

}VNode,AdjList[MAX_VERTEX_NUM]; //头结点

typedef struct{

AdjListvertices;
//邻接表

intvexnum,arcnum;

}ALGraph;

typedef struct Qnode{
//链队结点的类型

int data;

struct Qnode *next;

}Qnode,*QueuePtr;

typedef struct

{ //链队指针类型

QueuePtr front;

QueuePtr rear;

}LinkQueue;

int visited[MAX_VERTEX_NUM];

int LocateVex(ALGraph G,char u)

{

int i;

for (i=0;i<G.vexnum;i++)

{if(u==G.vertices[i].data) return i; }

if(i==G.vexnum) {printf("Error u!\n");exit(1);}

return0;

}

void InitQueue(LinkQueue &Q)

{

Q.front=Q.rear=(QueuePtr)malloc(sizeof(Qnode));

if(!Q.front) exit(1); //存储分配失败

Q.front->next=NULL;

}

void EnQueue(LinkQueue &Q,int e)

{ QueuePtr p;

p=(QueuePtr)malloc(sizeof(Qnode));

p->data=e;

p->next=NULL;

Q.rear->next=p;

Q.rear=p;

}

int QueueEmpty(LinkQueue &Q)

{

return(Q.front==Q.rear?1:0);

}

void DeQueue(LinkQueue &Q,int &e)

{ QueuePtr p;

if(QueueEmpty(Q))

{

printf("\n Queue is free!");

exit(1);

}//if

p=Q.front->next;

e=p->data;

Q.front->next=p->next;

if(Q.front->next==NULL) Q.rear=Q.front;

free(p);

}

void CreateALGraph_adjlist(ALGraph &G)

{

int i,j,k,w;

char v1,v2,enter;

ArcNode *p;

printf("Input vexnum &arcnum:\n");

scanf("%d",&G.vexnum);

scanf("%d",&G.arcnum);

printf("Input Vertices(以回车隔开各个数据):\n");

for (i=0;i<G.vexnum;i++)

{ scanf("%c%c",&enter,&G.vertices[i].data);//注意点,解说

G.vertices[i].firstarc=NULL;

}//for

printf("Input Arcs(v1,v2,w)以回车分开各个数据:\n");

for (k=0;k<G.arcnum;k++)

{

scanf("%c%c",&enter,&v1);

scanf("%c%c",&enter,&v2);

//scanf("%d",&w);

i=LocateVex(G,v1);

j=LocateVex(G,v2);

p=(ArcNode*)malloc(sizeof(ArcNode));

p->adjvex=j;

//p->info= w;

p->nextarc=G.vertices[i].firstarc;//前插法,即每次都插入到头结点的后面

G.vertices[i].firstarc=p;

printf("Next\n");

}//for

return;

}//CreateALGraph_adjlist

void BFSTraverse(ALGraph &G)

{

LinkQueue Q;

for(int v=0;v<G.vexnum;++v)visited[v]=false;

InitQueue(Q);

for(int v=0;v<G.vexnum;++v)

if(!visited[v])

{

EnQueue(Q,v);

while(!QueueEmpty(Q))

{

intu;

DeQueue(Q,u);

visited[u]=true;

printf("->%c",G.vertices[u].data);//visit一下

for(ArcNode*w=G.vertices[u].firstarc;w;w=w->nextarc)

if(!visited[w->adjvex])EnQueue(Q,w->adjvex);

}//while

}//if

}//BFSTraverse

int main()

{

ALGraph G;

CreateALGraph_adjlist(G);

BFSTraverse(G);

}

5、 广度优先搜索和深度优先搜索
深度优先搜索算法涉及的是堆栈,广度优先搜索涉及的是队列。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: