图——广度优先遍历

对比图的深度优先遍历与广度优先遍历算法,它们在时间复杂度上是一样的,不同之处在于对顶点访问顺序不同。可见二者在全图遍历上是没有优劣之分的,只是视不同的情况选择不同的算法。深度优先更适合目标比较明确,以找到目标为主要目的的情况,而广度优先更适合在不断扩大遍历范围时找到相对最优的情况。对于深度优先遍历和广度优先遍历而言,已经不是简单的算法实现问题,完全上升到方法论的角度。

#include<iostream>
using namespace std;
#define TRUE 1
#define FALSE 0
#define MaxVex 100  //定义最大顶点数
#define Inf 65535  //定义无穷大
typedef char VertexType;  //定义顶点数据类型
typedef int EdgeType;  //定义边上权值数据类型
typedef int Status;
int visited[MaxVex];  //访问标志数组,1表示访问过,0表示还未访问

typedef struct{
	int data[MaxVex];
	int front;
	int rear;
}Queue;
//初始化一个空队列Q
Status Init(Queue *Q)
{
	Q->front=0;
	Q->rear=0;
	return TRUE;
}
//返回队列的长度
int QueueLength(Queue Q)
{
	return (Q.rear-Q.front+MaxVex)%MaxVex;
}
//入队列操作,向队列插入元素e到Q的队尾
Status EnterQueue(Queue *Q,int e)
{
	if((Q->rear+1)%MaxVex==Q->front)
		return FALSE;
	Q->data[Q->rear]=e;
	Q->rear=(Q->rear+1)%MaxVex;
	return TRUE;
}
//出队列操作,将队列队头元素出队列并返回给e
Status DeleteQueue(Queue *Q,int *e)
{
	if(Q->front==Q->rear)
		return FALSE;
	*e=Q->data[Q->front];
	Q->front=(Q->front+1)%MaxVex;
	return TRUE;
}

//邻接矩阵存储图的结构
typedef struct Graph
{
	VertexType vex[MaxVex];  //一维数组存储顶点信息
	EdgeType arc[MaxVex][MaxVex];  //二维数组存储边的权值信息,也就是邻接矩阵
	int numVex,numArc;  //记录图中当前顶点数、边数
}MatrixGraph;
//建立无向网图的邻接矩阵表示
void CreateMatrixGraph(MatrixGraph *G)
{
	int i,j,k,weight;
	//输入顶点数和边数
	cin>>G->numVex>>G->numArc;
	//输入顶点信息,建立顶点表
	for(i=0;i<G->numVex;i++)
		cin>>G->vex[i];
	//初始化邻接矩阵
	for(i=0;i<G->numVex;i++)
		for(j=0;j<G->numVex;j++)
			G->arc[i][j]=Inf;
	//输入边信息,建立邻接矩阵
	for(k=0;k<G->numArc;k++)
	{
		cin>>i>>j>>weight;
		G->arc[i][j]=weight;
		G->arc[j][i]=G->arc[i][j];  //无向图,矩阵对称
	}
}
//邻接矩阵的广度遍历算法
void BFSTraverse(MatrixGraph G)
{
    int i,j;
	Queue Q;
	for(i=0;i<G.numVex;i++)
		visited[i]=FALSE;  //初始所有顶点状态为未访问过
	Init(&Q);
	for(i=0;i<G.numVex;i++)  //对每一个顶点循环逐一判断访问
	{
		if(visited[i]==0)
		{
			visited[i]=TRUE;
			cout<<G.vex[i];
			EnterQueue(&Q,i);  //将访问过的顶点入队列
			while(QueueLength(Q)!=0)
			{
				DeleteQueue(&Q,&i);  //队中元素出队列
				for(j=0;j<G.numVex;j++)
				{
					if(G.arc[i][j]==1 && visited[j]==0)  //判断邻接顶点是否访问过
					{
						visited[j]=TRUE;
						cout<<G.vex[j];
						EnterQueue(&Q,j);  //将访问过的顶点入队列
					}
				}
			}
		}
	}	
}
/*
*
*
*
*
*/
//邻接表存储图的结构
//边结点
typedef struct EdgeNode
{
	int vex;  //邻接点域,存储边另一个连接顶点对应的下标
	EdgeType weight;  //边的权值
	struct EdgeNode *next;  //指向下一个邻接点
}EdgeNode;
//顶点结点
typedef struct VexNode
{
	VertexType data;  //顶点域,存储顶点信息
	EdgeNode *firstEdge;  //边的头指针
}VexNode;
//邻接表存储所有顶点结点
typedef struct  
{
	VexNode adjList[MaxVex];  //adjList数组存储顶点结点
	int numVex,numArc;  //记录图中当前顶点数、边数
}AdjListGraph;
//建立无向图的邻接表结构
void CreateAdjListGraph(AdjListGraph *G)
{
	int i,j,k,w;
	EdgeNode *e;
	//输入顶点数和边数
	cin>>G->numVex>>G->numArc;
	//输入顶点信息,建立顶点表
	for(i=0;i<G->numVex;i++)
	{
		cin>>G->adjList[i].data;  //输入顶点信息
		G->adjList[i].firstEdge=NULL;  //将边表置为空表
	}
	//输入边信息,建立边表
	for(k=0;k<G->numArc;k++)
	{
		cin>>i>>j>>w;
		e=(EdgeNode*)malloc(sizeof(EdgeNode));
		e->vex=j;
		e->weight=w;
		//头插法链表插入边信息
		e->next=G->adjList[i].firstEdge;
		G->adjList[i].firstEdge=e;

		//无向图,另一个顶点同样的操作
		e=(EdgeNode*)malloc(sizeof(EdgeNode));
		e->vex=i;
		e->weight=w;
		//头插法链表插入边信息
		e->next=G->adjList[j].firstEdge;
		G->adjList[j].firstEdge=e;
	}
}
//邻接表的广度遍历算法
void BFSTraverse_AdjListGraph(AdjListGraph G)
{
	int i;
	EdgeNode *p;
	Queue Q;
	for(i=0;i<G.numVex;i++)
		visited[i]=FALSE;  //初始所有顶点状态为未访问过
	Init(&Q);
	for(i=0;i<G.numVex;i++)  //对每一个顶点循环逐一判断访问
	{
		if(visited[i]==0)
		{
			visited[i]=TRUE;
			cout<<G.adjList[i].data;
			EnterQueue(&Q,i);  //将访问过的顶点入队列
			while(QueueLength(Q)!=0)
			{
				DeleteQueue(&Q,&i);   //队中元素出队列
				p=G.adjList[i].firstEdge;
				while(p!=NULL)
				{
					if(visited[p->vex]==0)  //若邻接顶点访问未被访问,对顶点指向的邻接顶点访问
					{
						visited[p->vex]=TRUE;
						cout<<G.adjList[p->vex].data;
						EnterQueue(&Q,p->vex);  //将访问过的顶点入队列
					}
					p=p->next;
				}
			}
		}
	}
}
int main()
{
	//邻接矩阵法创建图并广度优先搜索图
	MatrixGraph G1;
	CreateMatrixGraph(&G1);
	BFSTraverse(G1);
	//邻接表法创建图并广度优先搜索图
	AdjListGraph G2;
	CreateAdjListGraph(&G2);
	BFSTraverse_AdjListGraph(G2);
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值