1.学习总结(2分)

1.1图的思维导图

1.2 图结构学习体会

(1)深度遍历算法:距离初始顶点越远越优先访问

  深度优先遍历过程:

   1)从图中某个初始顶点v出发,首先访问初始顶点v。
  (2)选择一个与顶点v相邻且没被访问过的顶点w,再从w出发进行深度优先搜索,直到图中与当前顶点v邻接的所有顶点都被访问过为止。

  算法设计思路:

  (1)深度优先遍历的过程体现出后进先出的特点:用栈或递归方式实现。

  (2)设置一个visited[] 全局数组, visited[i]=0表示顶点i没有访问; visited[i]=1表示顶点i已经访问过。

(2)广度遍历算法:距离初始顶点越近越优先访问

  广度优先遍历的过程:

  (1)访问初始点v,接着访问v的所有未被访问过的邻接点v1,v2,…,vt。
  (2)按照v1,v2,…,vt的次序,访问每一个顶点的所有未被访问过的邻接点。   
  (3)依次类推,直到图中所有和初始点v有路径相通的顶点都被访问过为止。

  算法设计思路:

  (1)广度优先搜索遍历体现先进先出的特点,用队列实现

  (2)设置一个visited[] 数组, visited[i]=0表示顶点i没有访问; visited[i]=1表示顶点i已经访问过。

(3)Prim和Kruscal算法

  Prim算法

  (1)初始化U={v}。v到其他顶点的所有边为候选边;
       (2)重复以下步骤n-1次,使得其他n-1个顶点被加入到U中:
           从候选边中挑选权值最小的边输出,设该边在V-U中的顶点是k,将k加入U中;
           考察当前V-U中的所有顶点j,修改候选边:若(j,k)的权值小于原来和顶点k关联的候选边,则用(k,j)取代后者作为候选边。

  Kruscal算法

  (1)置U的初值等于V(即包含有G中的全部顶点),TE的初值为空集(即图T中每一个顶点都构成一个连通分量)。
      (2)将图G中的边按权值从小到大的顺序依次选取:
             若选取的边未使生成树T形成回路,则加入TE;
             否则舍弃,直到TE中包含(n-1)条边为止。

(4)Dijkstra算法

  算法特点:

  (1)不适用于求最长路径

  (2)不适用于带负权值的带权图求单源最短路径

  求解思路:

  第1组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径v,… ,u,就将u加入到集合S中,直到全部顶点都加入到S中,算法就结束了)。
  第2组为其余未求出最短路径的顶点集合(用U表示)。

(5)拓扑排序算法

  (1)从有向图中选择一个没有前驱(即入度为0)的顶点并且输出它。
       (2)从图中删去该顶点,并且删去从该顶点发出的全部有向边。
       (3)重复上述两步,直到剩余的图中不再存在没有前驱的顶点为止。

2.PTA实验作业(4分)


2.1 题目1:图着色问题

2.2 设计思路

 while(n--)

{ 

  输入无向图的顶点数、边数、以及颜色数

  一条边的两个端点的编号

  待检查的颜色分配方案的个数

  V个顶点的颜色(第i个数字表示第i个顶点的颜色)

  是图着色问题的一个解则输出Yes

  否则输出No

}

2.3 代码截图

2.4 PTA提交列表说明。

 

  最大图的测试点没有过主要是一开始无向图的顶点数、边数、以及颜色数的定义不对,因为题目中说了无向图顶点数V大于0小于等于500

所以在数组定义中也认为是500,数组下标是从0开始的,把数组定义中最大界改为501就行,并且规定初始点。

题目2:排座位

2.2 设计思路

 for

{

  如果两位宾客之间是朋友,且没有敌对关系

  输出No problem

  如果他们之间并不是朋友,但也不敌对

  输出OK

  如果他们之间有敌对,然而也有共同的朋友

  输出OK but...

  如果他们之间只有敌对关系

  输出No way

}

2.3 代码截图

 

2.4 PTA提交列表说明

 这题有两个测试点没过,一个是乱序重复的四种情况,也就是朋友和敌对关系这两个关系的四种乱序重复另一种是最大N,最小M,全查询的情况。

如果他们之间有敌对,然而也有共同的朋友,输出OK but...;如果他们之间只有敌对关系,输出No way这两个情况时没有写上maps[x][y]==-1,

尤其是后一种情况,加上就没问题了。

题目3:公路村村通

2.2 设计思路

  城镇数目正整数N和候选道路数目M

  M行对应M条道路

  该条道路直接连通的两个城镇的编号以及该道路改建的预算成本

  如果输入数据不足以保证畅通,则输出1

2.3 代码截图

 

 

2.4 PTA提交列表说明。

 五个测试点有三个测试点没过,M<N-1,不可能有生成树;M到达N-1,但是图不连通;最大N和M,不连通;这三种情况。

其实最重要的还是在g[i][j]=g[j][i]=999999;之前写的是99999,其实不是很懂为什么会是这里出问题了,修改之后,三个测

试点就都能通过了。

3.截图本周题目集的PTA最后排名(3分)

3.1 PTA排名(截图带自己名字的排名)

 

3.2 我的总分:110

4. 阅读代码

采用邻接矩阵或邻接表作为存储结构,完成有向图和无向图的DFS和BFS操作

#include<string.h>
#include<ctype.h>
#include<malloc.h> 
#include<limits.h>
#include<stdio.h> 
#include<stdlib.h> 
#include<io.h> 
#include<math.h> 
#include<process.h> 

//函数结果状态代码
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1

//#define OVERFLOW -2 因为在math.h 中已定义OVERFLOW 的值为3,故去掉此行
typedef int Status; //Status 是函数的类型,其值是函数结果状态代码,如OK 等
typedef int Boolean;// Boolean 是布尔类型,其值是TRUE 或FALSE 


#define MAX_VERTEX_NUM 20
typedef enumGraphKind; 
typedef struct ArcNode
{
	int adjvex; /* 该弧所指向的顶点的位置*/
	struct ArcNode *nextarc; /* 指向下一条弧的指针*/
	InfoType *info; /* 网的权值指针) */
}ArcNode; /* 表结点*/

typedef struct
{
	VertexType data; /* 顶点信息*/
	ArcNode *firstarc; /* 第一个表结点的地址,指向第一条依附该顶点的弧的指针*/
}VNode,AdjList[MAX_VERTEX_NUM]; /* 头结点*/
	
	typedef struct
	{
	AdjList vertices;
	int vexnum,arcnum; /* 图的当前顶点数和弧数*/
	int kind; /* 图的种类标志*/
}ALGraph;

/*ALGraphAlgo.cpp 图的邻接表存储(存储结构由ALGraphDef.h 定义)的基本操作*/
int LocateVex(ALGraph G,VertexType u)
{ 	/* 初始条件: 图G 存在,u 和G 中顶点有相同特征*/
	/* 操作结果: 若G 中存在顶点u,则返回该顶点在图中位置;否则返回-1 */
	int i;
	for(i=0;i<G.vexnum;++i)
	if(strcmp(u,G.vertices[i].data)==0)
	return i;
	return -1;
}

Status CreateGraph(ALGraph &G)
{ 	/* 采用邻接表存储结构,构造没有相关信息的图G(用一个函数构造4 种图) */
	int i,j,k;
	int w; /* 权值*/
	VertexType va,vb;
	ArcNode *p;
	printf("请输入图的类型(有向图:0,有向网:1,无向图:2,无向网:3): ");
	scanf("%d",&(G.kind));
	printf("请输入图的顶点数,边数: ");
	scanf("%d,%d",&(G.vexnum),&(G.arcnum));
	printf("请输入%d 个顶点的值(<%d 个字符):\n",G.vexnum,MAX_NAME);
	for(i=0;i<G.vexnum;++i) /* 构造顶点向量*/
	{
		scanf("%s",G.vertices[i].data);
		G.vertices[i].firstarc=NULL;
	}
	if(G.kind==1||G.kind==3) /* 网*/
		printf("请顺序输入每条弧(边)的权值、弧尾和弧头(以空格作为间隔):\n");
	else /* 图*/
		printf("请顺序输入每条弧(边)的弧尾和弧头(以空格作为间隔):\n");
	for(k=0;k<G.arcnum;++k) /* 构造表结点链表*/
	{
		if(G.kind==1||G.kind==3) /* 网*/
			scanf("%d%s%s",&w,va,vb);
		else /* 图*/
			scanf("%s%s",va,vb);
		i=LocateVex(G,va); /* 弧尾*/
		j=LocateVex(G,vb); /* 弧头*/
		p=(ArcNode*)malloc(sizeof(ArcNode));
		p->adjvex=j;
		if(G.kind==1||G.kind==3) /* 网*/
		{
			p->info=(int *)malloc(sizeof(int));
			*(p->info)=w;
		}
		else
			p->info=NULL; /* 图*/
			p->nextarc=G.vertices[i].firstarc; /* 插在表头*/
			G.vertices[i].firstarc=p;
		if(G.kind>=2) /* 无向图或网,产生第二个表结点*/
		{
			p=(ArcNode*)malloc(sizeof(ArcNode));
			p->adjvex=i;
			if(G.kind==3) /* 无向网*/
			{
				p->info=(int*)malloc(sizeof(int));
				*(p->info)=w;
			}
		else
			p->info=NULL; /* 无向图*/
			p->nextarc=G.vertices[j].firstarc; /* 插在表头*/
			G.vertices[j].firstarc=p;
		}
	}
	return OK;
}

void DestroyGraph(ALGraph &G)
{ 	/* 初始条件: 图G 存在。操作结果: 销毁图G */
	int i;
	ArcNode *p,*q;
	G.vexnum=0;
	G.arcnum=0;
	for(i=0;i<G.vexnum;++i)
	{
		p=G.vertices[i].firstarc;
		while(p)
		{
			q=p->nextarc;
			if(G.kind%2) /* 网*/
				free(p->info);
			free(p);
			p=q;
		}
	}
}

VertexType* GetVex(ALGraph G,int v)
{ 	/* 初始条件: 图G 存在,v 是G 中某个顶点的序号。操作结果: 返回v 的值*/
	if(v>=G.vexnum||v<0)
		exit(ERROR);
	return &G.vertices[v].data;
}

int FirstAdjVex(ALGraph G,VertexType v)
{ 	/* 初始条件: 图G 存在,v 是G 中某个顶点*/
	/* 操作结果: 返回v 的第一个邻接顶点的序号。若顶点在G 中没有邻接顶点,则返回-1 */
	ArcNode *p;
	int v1;
	v1=LocateVex(G,v); /* v1 为顶点v 在图G 中的序号*/
	p=G.vertices[v1].firstarc;
	if(p)
		return p->adjvex;
	else
		return -1;
}

int NextAdjVex(ALGraph G,VertexType v,VertexType w)
{ 	/* 初始条件: 图G 存在,v 是G 中某个顶点,w 是v 的邻接顶点*/
	/* 操作结果: 返回v 的(相对于w 的)下一个邻接顶点的序号。*/
	/* 若w 是v 的最后一个邻接点,则返回-1 */
	ArcNode *p;
	int v1,w1;
	v1=LocateVex(G,v); /* v1 为顶点v 在图G 中的序号*/
	w1=LocateVex(G,w); /* w1 为顶点w 在图G 中的序号*/
	p=G.vertices[v1].firstarc;
	while(p&&p->adjvex!=w1) /* 指针p 不空且所指表结点不是w */
		p=p->nextarc;
	if(!p||!p->nextarc) /* 没找到w 或w 是最后一个邻接点*/
		return -1;
	else /* p->adjvex==w */
		return p->nextarc->adjvex; /* 返回v 的(相对于w 的)下一个邻接顶点的序号*/
}

Boolean visited[MAX_VERTEX_NUM]; /* 访问标志数组(全局量) */
void(*VisitFunc)(char* v); /* 函数变量(全局量) */
void DFS(ALGraph G,int v)
{ /* 从第v 个顶点出发递归地深度优先遍历图G。算法7.5 */
	int w;
	VertexType v1,w1;
	strcpy(v1,*GetVex(G,v));
	visited[v]=TRUE; /* 设置访问标志为TRUE(已访问) */
	VisitFunc(G.vertices[v].data); /* 访问第v 个顶点*/
	for(w=FirstAdjVex(G,v1);w>=0;w=NextAdjVex(G,v1,strcpy(w1,*GetVex(G,w))))
		if(!visited[w])
			DFS(G,w); /* 对v 的尚未访问的邻接点w 递归调用DFS */
}
void DFSTraverse(ALGraph G,void(*Visit)(char*))
{ /* 对图G 作深度优先遍历。算法7.4 */
	int v;
	VisitFunc=Visit; /* 使用全局变量VisitFunc,使DFS 不必设函数指针参数*/
	for(v=0;v<G.vexnum;v++)
		visited[v]=FALSE; /* 访问标志数组初始化*/
	for(v=0;v<G.vexnum;v++)
		if(!visited[v])
			DFS(G,v); /* 对尚未访问的顶点调用DFS */
	printf("\n");
}

typedef int QElemType; /* 队列类型*/
#include"LinkQueueDef.h"
#include"LinkQueueAlgo.h"
void BFSTraverse(ALGraph G,void(*Visit)(char*))
{	/*按广度优先非递归遍历图G。使用辅助队列Q 和访问标志数组visited。算法7.6 */
	int v,u,w;
	VertexType u1,w1;
	LinkQueue Q;
	for(v=0;v<G.vexnum;++v)
		visited[v]=FALSE; /* 置初值*/
	InitQueue(Q); /* 置空的辅助队列Q */
	for(v=0;v<G.vexnum;v++) /* 如果是连通图,只v=0 就遍历全图*/
		if(!visited[v]) /* v 尚未访问*/
		{
			visited[v]=TRUE;
			Visit(G.vertices[v].data);
			EnQueue(Q,v); /* v 入队列*/
			while(!QueueEmpty(Q)) /* 队列不空*/
			{
				DeQueue(Q,u); /* 队头元素出队并置为u */
				strcpy(u1,*GetVex(G,u));
				for(w=FirstAdjVex(G,u1);w>=0;w=NextAdjVex(G,u1,strcpy(w1,*GetVex(G,w))))
				if(!visited[w]) /* w 为u 的尚未访问的邻接顶点*/
				{
					visited[w]=TRUE;
					Visit(G.vertices[w].data);
					EnQueue(Q,w); /* w 入队*/
				}
			}
		}
	printf("\n");
}

void Display(ALGraph G)
{	 /* 输出图的邻接矩阵G */
	int i;
	ArcNode *p;
	switch(G.kind)
	{ 	case DG: printf("有向图\n"); break;
		case DN: printf("有向网\n"); break;
		case AG: printf("无向图\n"); break;
		case AN: printf("无向网\n");
	}
	printf("%d 个顶点:\n",G.vexnum);
	for(i=0;i<G.vexnum;++i)
		printf("%s ",G.vertices[i].data);
	printf("\n%d 条弧(边):\n",G.arcnum);
	for(i=0;i<G.vexnum;i++)
	{
		p=G.vertices[i].firstarc;
		while(p)
		{
				if(G.kind<=1) /* 有向*/
				{
					printf("%s→%s ",G.vertices[i].data,G.vertices[p->adjvex].data);
					if(G.kind==DN) /* 网*/
						printf(":%d ",*(p->info));
				}
			else /* 无向(避免输出两次) */
			{
				if(i<p->adjvex)
				{
					printf("%s-%s ",G.vertices[i].data,G.vertices[p->adjvex].data);
					if(G.kind==AN) /* 网*/
						printf(":%d ",*(p->info));
				}
			}
			p=p->nextarc;
		}
		printf("\n");
	}
}
	
	
#include "pubuse.h"
#define MAX_NAME 3 /* 顶点字符串的最大长度+1 */
typedef int InfoType; /* 存放网的权值*/
typedef char VertexType[MAX_NAME]; /* 字符串类型*/
#include"ALGraphDef.h"
#include"ALGraphAlgo.h"
void print(char *i)
{
    printf("%s ",i);
}

void main()
{
	int i,j,k,n;
	ALGraph g;
	VertexType v1,v2;
	printf("请选择有向图\n");
	CreateGraph(g);
	Display(g);
	printf("深度优先搜索的结果:\n");
	DFSTraverse(g,print);
	printf("广度优先搜索的结果:\n");
	BFSTraverse(g,print);
	DestroyGraph(g); /* 销毁图*/
}

  

posted @ 2018-06-18 16:51  pumpkin15  阅读(222)  评论(0编辑  收藏  举报