图的遍历(邻接矩阵和邻接表)

图的存储常见的两种方式: 邻接矩阵、邻接表

邻接矩阵的定义:

//邻接矩阵 
typedef struct 
{
	char vertex[MAXVEX];//顶点表
	int arc[MAXVEX][MAXVEX];//邻接矩阵
	int numVertexes, numEdges;//图中当前顶点数和边数
}MGraph;

基于邻接矩阵创建一个图:

//建立无向网的邻接矩阵
void  CreateGraph(MGraph *G)
{
	int i, j,k,w;
	//设置顶点个数
	printf("请输入图的顶点数,边数:\n");
	scanf("%d %d", &G->numVertexes, &G->numEdges);
	//getchar();//清空缓冲区(主要是回车)
	setbuf(stdin, NULL);//设置输入缓冲区 为空缓冲区
	
	//设置结点存储值
	for (i = 0; i < G->numVertexes; i++)
	{
		printf("\n请输入第%d个顶点存储的值:",i);
		scanf("%c", &G->vertex[i]);
		setbuf(stdin, NULL);//设置输入缓冲区 为空缓冲区(每次输入一个回车,这里会造成 \n字符存在缓冲区)
	}
	for (i = 0; i < G->numVertexes; i++)
	{
		for (j = 0; j < G->numVertexes; j++)
		{
			G->arc[i][j] = INFINITY;//初始化邻接矩阵(权为INFINITY无穷大表示没有弧)
		}
	}
	for (k = 0; k < G->numEdges; k++)
	{
		printf("请输入边(vi,vj)的下标i,下标j对应的权w:");
		scanf("%d %d %d", &i, &j, &w);
		G->arc[i][j] = w;//设置对应的权
		G->arc[j][i] = G->arc[i][j];//无向网,对称矩阵
	}
}

邻接表的定义:

typedef struct EdgeNode /* 边表结点  */
{
	int adjvex;    /* 邻接点域,存储该顶点对应的下标 */
//	EdgeType info;		/* 用于存储权值,对于非网图可以不需要 */
	struct EdgeNode *next; /* 链域,指向下一个邻接点 */
}EdgeNode;

typedef struct VertexNode /* 顶点表结点 */
{
	char data; /* 顶点域,存储顶点信息 */
	EdgeNode *firstedge;/* 边表头指针 */
}VertexNode, AdjList[MAXVEX];

基于邻接表创建一个图:

void  CreateALGraph(GraphAdjList *G)
{
	int i,j,k;
	EdgeNode *e;
	printf("输入顶点数和边数:\n");
	scanf("%d %d",&G->numNodes,&G->numEdges); /* 输入顶点数和边数 */
	for(i = 0;i < G->numNodes;i++) /* 读入顶点信息,建立顶点表 */
	{
		printf("请输入顶点信息\n");
		scanf("%s",&G->adjList[i].data); 	/* 输入顶点信息 */
		G->adjList[i].firstedge=NULL; 	/* 将边表置为空表 */
	}
	
	
	for(k = 0;k < G->numEdges;k++)/* 建立边表 */
	{
		printf("输入边(vi,vj)上的顶点序号:\n");
		scanf("%d %d",&i,&j); /* 输入边(vi,vj)上的顶点序号 */
		e=(EdgeNode *)malloc(sizeof(EdgeNode)); /* 向内存申请空间,生成边表结点 */
		e->adjvex=j;					/* 邻接序号为j */                         
		e->next=G->adjList[i].firstedge;	/* 将e的指针指向当前顶点上指向的结点 */
		G->adjList[i].firstedge=e;		/* 将当前顶点的指针指向e */               
		
		e=(EdgeNode *)malloc(sizeof(EdgeNode)); /* 向内存申请空间,生成边表结点 */
		e->adjvex=i;					/* 邻接序号为i */                         
		e->next=G->adjList[j].firstedge;	/* 将e的指针指向当前顶点上指向的结点 */
		G->adjList[j].firstedge=e;		/* 将当前顶点的指针指向e */               
	}
}

基于邻接矩阵的广度优先遍历(BFS):

void BFS(MGraph *G,int i){
	int j;
	int Q[MAXVEX];int front=0;int rear=0;//定义一个队列,并初始化
	Q[rear++]=i;
	printf("%c",G->vertex[i]);
	visited[i]=true;//设置标记数组 
	while(rear!=front){//队列不为空 
		i=Q[front++];//出队
		for(j=0;j<G->numVertexes;j++)
			if(G->arc[i][j]!=0&&G->arc[i][j]!=INFINITY&&!visited[j]){
				Q[rear++]=j;//入队 
				printf("%c",G->vertex[j]);//访问
				visited[j]=true;//修改标志 
			}		
	}
	
}

void BFSTraver(MGraph *G){
	int i;
	for(i=0;i<G->numVertexes;i++)
		visited[i]=false;//初始化
	for(i=0;i<G->numVertexes;i++)
		if(!visited[i])
			BFS(G,i);	
}

深度优先遍历(DFS):

void DFS(MGraph *G,int i){
	int j;
	printf("%c",G->vertex[i]);
	visited[i]=true;
	for(j=0;j<G->numVertexes;j++){
		if(G->arc[i][j]!=0&&G->arc[i][j]!=INFINITY&&!visited[i])
			DFS(G,j);
	}
} 

void DFSTraver(MGraph *G){
	int i;
	for(int i;i<G->numVertexes;i++)
		visited[i]=false;	//初始化
	for(i=0;i<G->numVertexes;i++){
		if(!visited[i])
			DFS(G,i);
	}
	
}

基于邻接表的广度优先遍历(BFS):

void BFS(GraphAdjList *G,int v0){
	int Q[MAXVEX];int front=0;int rear=0;
	Q[rear++]=v0;			//入队 
	visit(G,v0);
	visited[v0]=true;
	while(front!=rear){
		int v=Q[front++]; 			//入队 
		EdgeNode *p=G->adjList[v].firstedge;
		while(p!=NULL){
			if(!visited[p->adjvex]){
				visit(G,p->adjvex);
				visited[p->adjvex]=true;
				Q[rear++]=p->adjvex;
			}
			p=p->next;	//
		}
	}	
}


void BFSTraver(GraphAdjList *G){
	int i;
	for(i=0;i<G->numNodes;i++){
		visited[i]=false;
	}
	
	for(i=0;i<G->numNodes;i++){
		if(!visited[i])
			BFS(G,i);
	}
}

深度优先遍历(DFS):

void DFS(GraphAdjList *G,int v0){
	visit(G,v0);
	visited[v0]=true;
	EdgeNode *p=G->adjList[v0].firstedge;
	while(p!=NULL){
		if(!visited[p->adjvex]){
			DFS(G,p->adjvex);
		}
		p=p->next;	
	}
}


void DFSTraver(GraphAdjList *G){
	int i;
	for(i=0;i<G->numNodes;i++)
		visited[i]=false;//初始化
	for(i=0;i<G->numNodes;i++)
		if(!visited[i])
			DFS(G,i);
}

 

  • 5
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值