图及其应用

2022-11-21 11:36:11 浏览数 (1)

第1关:创建采用邻接表存储的无向图

任务描述

本关任务:创建邻接表存储的无向图,并输出图的邻接表。

相关知识

为了完成本关任务,你需要掌握:1.邻接表,2.图的邻接表存储表示。

邻接表

对于图中每个顶点 vi,把所有邻接于 vi的顶点(对有向图是将从vi出发的弧的弧头顶点链接在一起)链接成一个带头结点的单链表,将所有头结点顺序存储在一个一维数组中。 例:下面左图G2对应的邻接表如右边所示。

图的邻接表存储表示

代码语言:javascript复制
#define MAXVEX 20 /*最大顶点数*/
typedef enum{DG,DN,UDG,UDN} GraphKind; /*有向图,有向网,无向图,无向网*/
typedef struct ENode /*表结点类型*/
{
int adjvex;
struct ENode *nextarc;
int weight;
}ENode;
typedef int VexType;
typedef struct VNode /*头结点类型*/
{
VexType vex;
ENode *firstarc;
}VNode, AdjList[MAXVEX]; /*邻接表类型定义*/
typedef struct
{
AdjList vertices; /*用邻接表存储顶点集合及边集合*/
int vexnum,edgenum;
GraphKind kind;
}ALGraph; /*邻接表存储的图的类型定义*/

编程要求

在右侧编辑器中补充代码,完成CreateUDG_ALG函数,以实现图的创建。

测试说明

可在右侧文件夹中查看step1/Main.cpp文件,以便于你的操作。

平台会对你编写的代码进行测试。

输入输出说明: 第一行输入图的类型、图的顶点数和边数。图的类型包括:DG(有向图),DN(有向网),UDG(无向图),UDN(无向网),分别用0-3表示。 第二行输入各条边的两顶点的编号,按顶点编号从小到大的顺序输入。 输出邻接表。 如创建图G2,则 测试输入: 2 5 6 //图的类型为2表示UDG,图的顶点数为5,图的边数为6 0 1 0 3 1 2 1 4 2 3 2 4 //输入各条边的两顶点的编号,按顶点编号从小到大的顺序输入

预期输出: 0->3->1 1->4->2->0 2->4->3->1 3->2->0 4->2->1

开始你的任务吧,祝你成功!

代码语言:javascript复制
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ALGraph.h"

int visited[MAXVEX]; /*设访问标志数组为全局变量*/

void CreateUDG_ALG(ALGraph &g) /*构造无向图的邻接表*/
{
	// 请在这里补充代码,完成本关任务
    /********** Begin *********/
   	int i,j,k;ENode *p;
//printf("请输入图的类型(0-3表示DG,DN,UDG,UDN)、顶点数、边数:n");
scanf("%d%d%d",&g.kind,&g.vexnum,&g.edgenum);
for(i=0;i<g.vexnum;i  ) /*构造头结点数组*/
{
	g.vertices[i].vex=i;
	g.vertices[i].firstarc=NULL; /*初始化头结点指针域为空*/
}
//printf("请按顶点编号从小到大的顺序输入各条边的两顶点:n");
for(k=0;k<g.edgenum;k  ) /*构造邻接表*/
{
	scanf("%d%d",&i,&j); /*输入一条边所依附的两个顶点的编号*/
	/*将顶点Vj插入到第i个单链表的表头,也就是用“头插法”建立一个单链表*/
	p=(ENode *)malloc(sizeof(ENode)); /*生成表结点*/
	p->adjvex=j; p->weight=0;
	p->nextarc=g.vertices[i].firstarc; /*插入表结点*/
	g.vertices[i].firstarc=p;
	/*将顶点Vi插入到第j个单链表的表头,也就是用“头插法”建立一个单链表*/
	p=(ENode *)malloc(sizeof(ENode));
	p->adjvex=i; p->weight=0;
	p->nextarc=g.vertices[j].firstarc;
	g.vertices[j].firstarc=p;
}



    /********** End **********/	
}

void PrintAdjList(ALGraph g) /*输出邻接表*/
{
	int i,w;ENode *p;
	for(i=0;i<g.vexnum;i  )
	{
		printf("%d",g.vertices[i].vex);
		p=g.vertices[i].firstarc;
		while(p)
		{
			w=p->adjvex;printf("->%d",w);p=p->nextarc;
		}
		printf("n");
	}    
}

第2关:图的深度优先遍历

任务描述

本关任务:图的深度优先遍历。

相关知识

为了完成本关任务,你需要掌握:图的深度优先遍历。

图的深度优先遍历

设初始时,图中所有顶点未曾被访问过: ● 从图中某个顶点 v 出发,访问此顶点; ● 依次从 v 的未被访问的邻接点出发深度优先遍历图,直至图中所有和顶点 v 有路径相通的顶点都被访问到; ● 如果此时图中还有尚未访问的顶点,则另选一个尚未访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。 如:下图从V0出发,可以得到一个深度优先遍历序列为{ V0 ,V1 ,V3 ,V7 ,V4 ,V2 ,V5 ,V6 }。

编程要求

在右侧编辑器中补充代码,完成DFS函数,实现图的深度优先遍历。具体要求如下:

* DFS:从未被访问的顶点Vi出发深度优先遍历图。

测试说明

可在右侧文件夹中查看step2/Main.cpp文件,以便于你的操作。

平台会对你编写的代码进行测试。

输入输出说明: 第一行输入图的类型、图的顶点数和边数。 第二行输入各条边的两顶点的编号,按顶点编号从小到大的顺序输入。 输出深度优先遍历的结果。 如图G2,

测试输入: 2 5 6 0 1 0 3 1 2 1 4 2 3 2 4

预期输出: 0 3 2 4 1 //深度优先遍历的结果

开始你的任务吧,祝你成功!

代码语言:javascript复制
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ALGraph.h"

int visited[MAXVEX]; /*设访问标志数组为全局变量*/

void DFSTraverse(ALGraph  g)/*深度优先遍历以邻接表存储的图g*/ 
{
	int i;
	for(i=0;i<g.vexnum;i  ) /*访问标志数组初始化*/
		visited[i]=0;
	for(i=0;i<g.vexnum;i  )
		if(!visited[i]) DFS(g,i); /*对尚未访问的顶点调用DFS函数*/
}
void DFS(ALGraph  g, int i)/*从未被访问的顶点Vi出发深度优先遍历图g*/ 
{
	// 请在这里补充代码,完成本关任务
    /********** Begin *********/
 ENode *p;
printf("%d ",g.vertices[i].vex);
visited[i]=1;
p=g.vertices[i].firstarc;
while(p)
{
	if(!visited[p->adjvex])
		DFS(g,p->adjvex);
	p=p->nextarc;
}


    /********** End **********/		
}
void CreateUDG_ALG(ALGraph &g) /*构造无向图的邻接表*/
{
	
	int i,j,k;ENode *p;
	//printf("请输入图的类型(0-3表示DG,DN,UDG,UDN)、顶点数、边数:n");
	scanf("%d%d%d",&g.kind,&g.vexnum,&g.edgenum);
	for(i=0;i<g.vexnum;i  ) /*构造头结点数组*/
	{
		g.vertices[i].vex=i;
		g.vertices[i].firstarc=NULL; /*初始化头结点指针域为空*/
	}
	//printf("请按顶点编号从小到大的顺序输入各条边的两顶点:n");
	for(k=0;k<g.edgenum;k  ) /*构造邻接表*/
	{
		scanf("%d%d",&i,&j); /*输入一条边所依附的两个顶点的编号*/
		/*将顶点Vj插入到第i个单链表的表头,也就是用“头插法”建立一个单链表*/
		p=(ENode *)malloc(sizeof(ENode)); /*生成表结点*/
		p->adjvex=j; p->weight=0;
		p->nextarc=g.vertices[i].firstarc; /*插入表结点*/
		g.vertices[i].firstarc=p;
		/*将顶点Vi插入到第j个单链表的表头,也就是用“头插法”建立一个单链表*/
		p=(ENode *)malloc(sizeof(ENode));
		p->adjvex=i; p->weight=0;
		p->nextarc=g.vertices[j].firstarc;
		g.vertices[j].firstarc=p;
	}
}

第3关:图的广度优先遍历

任务描述

本关任务:图的广度优先遍历。

相关知识

为了完成本关任务,你需要掌握:图的广度优先遍历。

图的广度优先遍历

设初始时,图中所有顶点未曾被访问过: ● 从图中某个顶点 v 出发,访问此顶点; ● 依次访问 v 的各个未被访问的多个邻接点; ● 分别从这些邻接点出发依次访问它们的邻接点,并使 “先被访问顶点的邻接点” 先于 “后被访问顶点的邻接点” 被访问,直至图中所有已被访问的顶点的邻接点都被访问到; ● 如果此时还有未被访问的顶点,则另选一个未被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。 如:下图从V0出发,可以得到一个广度优先遍历序列为{ V0 ,V1 ,V2 ,V3 ,V4 ,V5 ,V6 ,V7 }

编程要求

在右侧编辑器中补充代码,完成BFSTraverse函数,实现图的深度优先遍历。具体要求如下:

* BFSTraverse:广度优先遍历邻接表存储的图,需借助队列实现。

测试说明

可在右侧文件夹中查看step3/Main.cpp文件,以便于你的操作。

平台会对你编写的代码进行测试。

输入输出说明: 第一行输入图的类型、图的顶点数和边数。 第二行输入各条边的两顶点的编号,按顶点编号从小到大的顺序输入。 输出广度优先遍历的结果。 如图G2,

测试输入: 2 5 6 0 1 0 3 1 2 1 4 2 3 2 4

预期输出: 0 3 1 2 4 //广度优先遍历的结果

开始你的任务吧,祝你成功!

代码语言:javascript复制
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ALGraph.h"

int visited[MAXVEX]; /*设访问标志数组为全局变量*/

void BFSTraverse(ALGraph  g) 
{/*广度优先遍历以邻接表存储的图g,由于BFS要求”先被访问的顶点的邻接点也先被访问”,故需借助队列Q实现*/
	// 请在这里补充代码,完成本关任务
    /********** Begin *********/
   	int i;  
SeqQueue Q;   //创建队列

for (i=0; i<g.vexnum;   i){   /*访问标志数组初始化*/
    visited[i] = 0; 
} 
InitQueue(Q);      //队列的初始化

for (i=0; i<g.vexnum;   i){  
    if(!visited[i]){     //如果第i个结点没有被访问
        visited[i] = 1;  
        printf("%d ", g.vertices[i].vex);  
        EnQueue(Q, i);       //将元素x入队

        while (Q.len!=0){    //当队列不为空时,或者 Q.front != Q.rear
            DeQueue(Q, i);     //将队头元素出队
            ENode *p = g.vertices[i].firstarc;  
            while (p){  
                if (!visited[p->adjvex]){  
                    visited[p->adjvex] = 1;  
                    printf("%d ", g.vertices[p->adjvex].vex);  
                    EnQueue(Q, p->adjvex);     //将元素x入队
                }  
                p = p->nextarc;  
            }
        }
    }  
}    

    /********** End **********/		
}  

void InitQueue(SeqQueue &q)//队列的初始化
{
	q.front=q.rear=0;q.len=0;
}
int QueueEmpty(SeqQueue q)//判队空
{
	if(q.len==0)return 1;
	else return 0; 
}
void EnQueue(SeqQueue &q, datatype x)//将元素x入队
{
	if(q.len==MAXSIZE)//判队满
	{
		printf("Queue is fulln");return;
	}
	q.data[q.rear]=x; q.rear=(q.rear 1)%MAXSIZE;
	q.len  ;
}
void DeQueue(SeqQueue &q, datatype &x)//将队头元素出队
{
	if(q.len==0)//判队空
	{
		printf("Queue is emptyn");return;
	}
	x=q.data[q.front]; q.front=(q.front 1)%MAXSIZE;
	q.len--;
}

void CreateUDG_ALG(ALGraph &g) /*构造无向图的邻接表*/
{
	
	int i,j,k;ENode *p;
	//printf("请输入图的类型(0-3表示DG,DN,UDG,UDN)、顶点数、边数:n");
	scanf("%d%d%d",&g.kind,&g.vexnum,&g.edgenum);
	for(i=0;i<g.vexnum;i  ) /*构造头结点数组*/
	{
		g.vertices[i].vex=i;
		g.vertices[i].firstarc=NULL; /*初始化头结点指针域为空*/
	}
	//printf("请按顶点编号从小到大的顺序输入各条边的两顶点:n");
	for(k=0;k<g.edgenum;k  ) /*构造邻接表*/
	{
		scanf("%d%d",&i,&j); /*输入一条边所依附的两个顶点的编号*/
		/*将顶点Vj插入到第i个单链表的表头,也就是用“头插法”建立一个单链表*/
		p=(ENode *)malloc(sizeof(ENode)); /*生成表结点*/
		p->adjvex=j; p->weight=0;
		p->nextarc=g.vertices[i].firstarc; /*插入表结点*/
		g.vertices[i].firstarc=p;
		/*将顶点Vi插入到第j个单链表的表头,也就是用“头插法”建立一个单链表*/
		p=(ENode *)malloc(sizeof(ENode));
		p->adjvex=i; p->weight=0;
		p->nextarc=g.vertices[j].firstarc;
		g.vertices[j].firstarc=p;
	}
}

附其余头文件:

ALGraph.h

代码语言:javascript复制
#include"stdio.h"
#include"stdlib.h"
#define MAXVEX 20 /*最大顶点数*/
#define MAXSIZE MAXVEX /*队列最大容量*/

typedef enum{DG,DN,UDG,UDN} GraphKind; /*有向图,有向网,无向图,无向网*/
typedef struct ENode /*表结点类型*/
{
	int adjvex;
	struct ENode *nextarc;
	int weight;
}ENode;
typedef int VexType;
typedef struct VNode /*头结点类型*/
{
	VexType vex;
	ENode *firstarc;
}VNode, AdjList[MAXVEX]; /*邻接表类型定义*/
typedef struct
{
	AdjList vertices; /*用邻接表存储顶点集合及边集合*/
	int vexnum,edgenum;
	GraphKind kind;
}ALGraph; /*邻接表存储的图的类型定义*/

typedef int datatype;
typedef  struct
{
	datatype  data[MAXSIZE]; /*存放顶点编号*/
	int  front;  
	int  rear;  //队尾指针,指向队尾元素的下一个位置
	int  len;  
 }SeqQueue;    //循环顺序队列的类型定义

/*******函数声明*******/

void CreateUDG_ALG(ALGraph &g); /*构造无向图的邻接表*/
void PrintAdjList(ALGraph g); /*输出邻接表*/
void DFSTraverse(ALGraph  g); /*深度优先遍历以邻接表存储的图g*/
void DFS(ALGraph  g, int i); /*从未被访问的顶点Vi出发深度优先遍历图g*/ 
void BFSTraverse(ALGraph  g); /*广度优先遍历以邻接表存储的图g*/
void InitQueue(SeqQueue &q); /*队列初始化*/
int QueueEmpty(SeqQueue q); /*判队空*/
void EnQueue(SeqQueue &q, datatype x); /*入队*/
void DeQueue(SeqQueue &q, datatype &x); /*出队*/

第一关main.cpp

代码语言:javascript复制
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ALGraph.h"
//#include "ALGraph.cpp"

int main()
{
    ALGraph g;
	CreateUDG_ALG(g); /*创建邻接表存储的无向图*/
	//printf("n图的邻接表:n");
	PrintAdjList(g);  /*输出邻接表*/
	return 0;
}

第二关: 

ALGraph.h

代码语言:javascript复制
#include"stdio.h"
#include"stdlib.h"
#define MAXVEX 20 /*最大顶点数*/
#define MAXSIZE MAXVEX /*队列最大容量*/

typedef enum{DG,DN,UDG,UDN} GraphKind; /*有向图,有向网,无向图,无向网*/
typedef struct ENode /*表结点类型*/
{
	int adjvex;
	struct ENode *nextarc;
	int weight;
}ENode;
typedef int VexType;
typedef struct VNode /*头结点类型*/
{
	VexType vex;
	ENode *firstarc;
}VNode, AdjList[MAXVEX]; /*邻接表类型定义*/
typedef struct
{
	AdjList vertices; /*用邻接表存储顶点集合及边集合*/
	int vexnum,edgenum;
	GraphKind kind;
}ALGraph; /*邻接表存储的图的类型定义*/


typedef int datatype;
typedef  struct
{
	datatype  data[MAXSIZE]; /*存放顶点编号*/
	int  front;  
	int  rear;  //队尾指针,指向队尾元素的下一个位置
	int  len;  
 }SeqQueue;    //循环顺序队列的类型定义

/*******函数声明*******/

void CreateUDG_ALG(ALGraph &g); /*构造无向图的邻接表*/
void PrintAdjList(ALGraph g); /*输出邻接表*/
void DFSTraverse(ALGraph  g); /*深度优先遍历以邻接表存储的图g*/
void DFS(ALGraph  g, int i); /*从未被访问的顶点Vi出发深度优先遍历图g*/ 
void BFSTraverse(ALGraph  g); /*广度优先遍历以邻接表存储的图g*/
void InitQueue(SeqQueue &q); /*队列初始化*/
int QueueEmpty(SeqQueue q); /*判队空*/
void EnQueue(SeqQueue &q, datatype x); /*入队*/
void DeQueue(SeqQueue &q, datatype &x); /*出队*/
代码语言:javascript复制
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ALGraph.h"
//#include "ALGraph.cpp"

int main()
{
    ALGraph g;
	CreateUDG_ALG(g); /*创建邻接表存储的无向图*/
	DFSTraverse(g); /*深度优先遍历*/
	return 0;
}

第三关:

代码语言:javascript复制
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ALGraph.h"
//#include "ALGraph.cpp"

int main()
{
    ALGraph g;
	CreateUDG_ALG(g); /*创建邻接表存储的无向图*/
	BFSTraverse(g);  /*广度优先遍历*/
	return 0;
}

0 人点赞