0.PTA得分截图
1.本周学习总结
图存储结构
邻接矩阵
-
简单来讲使用二维数组进行存储,设位edge[M][N]。其中,M,N代表两个顶点,edge[M][N]可代表是否连通或者权值。
邻接矩阵的特点: -
若图为无向图,则矩阵是沿对角线是对称的。
可以直接访问顶点M,N间边的关系以及权值。
缺点: -
存储的图为稀疏图时,浪费的空间较多,n个顶点所需空间至少为n^2。
结构体定义
typedef struct //图的定义
{ int edges[MAXV][MAXV]; //邻接矩阵
int n,e; //顶点数,边数
} MGraph;
-
邻接表
采用结构体数组跟链表结合,存储每个顶点的临边
特点: -
存储的图为无向图时,遍历顶点数组每个临边即可遍历整张图
相比于邻接矩阵更节省空间
缺点 -
无法直接知道任一两个顶点之间的关系。
存储的图为有向图时,同一条边会生成两条链。
定义如下
typedef struct ANode
{
int adjvex; //该边的终点编号
struct ANode *nextarc; //指向下一条边的指针
int info; //该边的相关信息,如权重
} ArcNode; //边表节点类型
typedef int Vertex;
typedef struct Vnode
{
Vertex data; //顶点信息
ArcNode *firstarc; //指向第一条边
} VNode; //邻接表头节点类型
typedef VNode AdjList[MAXV]; //头结点数组
typedef struct
{
AdjList adjlist; //邻接表
int n,e; //图中顶点数n和边数e
} AdjGraph;
图遍历及应用
- 首先要了解图遍历,就要先清楚:什么是图遍历
从给定的图中任意一个顶点开始,按照某种搜索方法(DFS、BFS)沿着图的边访问图中的所有顶点,并且要注意,每个顶点只能被访问一次,,这个过程就叫做图遍历。 - 图的遍历相对于树的遍历来说更加复杂,因为对于树来说,从树的根部到树中任意几点只有唯一的一条路径,但是,对于图来说,从图的初始点到图的任意一个顶点,大概率都会存在多条路径,即当沿着图中的一条路径访问过某一顶点后,还可能会沿着另一条路径回到初始顶点,也就是我们说的回路。所以为了避免同一个顶点被访问多次,就引入了一个访问标记数组visited,若顶点被访问过则将visited的值置为1,否则置为0.
深度优先遍历
- 深度优先遍历的过程是从图中的某个点v出发,然后选择一个与顶点v相邻且没有被访问过的顶点w,然后再以w为顶点,重复上述操作,直到所有顶点都被访问为止。(采用递归的方法)
int visited[MAX]={0};
//全局数组
void DFS(AdjGraph * G,int v)
//深度优先遍历算法
ArcNode * p;
visited[v]=1;
//置已访问标记
printf("%d ",v);
//输出被访问顶点的编号
p=G-> adjlist[v]. firstarc;
//p指向顶点v的第一个邻接点
while (p!= NULL)
{ if (visited[p-> adjvex]==0) //若p-> adjvex顶点未被访问, 递归访问它
DFS(G,p-> adjvex);
P=P- > nextarc;
//p指向顶点v的下一个邻接点
}
广度优先遍历
广度优先遍历和深度优先遍历稍有不同,广度优先遍历的过程是首先访问初始点v,接着访问v的所有未被访问过的邻接点,v1,v2,v3....,访问完毕后再按照v1,v2,v3...,的顺序访问所有顶点每一个未被访问过的邻接点,以此类推,直到图中所有顶点都被访问过一次为止。
void BFS( AdjGraph*G, int v)
int w, i;ArcNode*p;
//定义环形队列指针
SqQueue*qu;
InitQueue(qu);
//初始化队列
int visited[MAXV];
//定义顶点访问标记数组
for (i=0;i<G-> n;i++) visited[i]=0;
//访问标记数组初始化
printf("%2d",v);
//输出被访问顶点的编号
visited[v]=1;
//置已访问标记
enQueue(qu, v);
while (!QueueEmpty(qu))
//队不空循环
{ deQueue(qu, w);
//出队一个顶点w
非连通图
对于无向图来说,若是连通图,则一次遍历就能访问到所有的节点,但是如果无向图是非连通图,则只能访问到初始点所在的连通分量中的所有顶点,其他连通分量中的顶点是不能访问到的,所有要再次从其他的连通分量中寻找初始点再次进行遍历,这样才能访问到图中的所有顶点
采用深度优先遍历非连通图无向图的算法如下:
DFS1(AdjGraph * G)
int i;
for (i=0;i<G-> n;i++ )
if (visited[i]==0) DFS(G,i);
采用广度优先遍历非连通图无向图的算法如下:
BFSI(AdjGraph *G)
int 1;
for (i=0;i<G-> n;i十十)
if (visitedli」==0) BFS(G,i);
判断无向图是否连通
bool Connect(AdjGraph *G)
//判断无向图G的连通性
(int i;
bool flag= true;
for (i=0;i<G->n;i++)
//visited数组置初值
visited[i]=0;
DFS(G, 0);
//调用前面的中DSF算法,从顶点0开始深度优先遍历
for (i=0;i<G-> n;i十十)if (visited[i]==0)
//若有顶点没有被访问到,说明是不连通的
flag= false;
break;
return flag;
查找顶点间是否存在简单路径
即再深度遍历的基础上增加两个形参,其中一个判断两顶点间是否有路径,若有则返回true
void ExistPath( AdjGraph *G, int u,int v,bool &.has){ //has表示u到v是否有路径,初值为false
int w; ArcNode * p;
visited[u]=1;
//置已访问标记
if (u==v)
//找到了一条路径
has= true;
//置has为true并返回
return ;
p=G- -> adjlist[u]. firstarc;
//p指向顶点u的第一个邻接点
while (p!= NULL)
w=p- > adjvex;
//w为顶点u的邻接点
if (visited[w]==0)
//若w顶点未访问,递归访问它
ExistPath(G, w,v, has);
P=p- > nextarc;
//p指向顶点u的下一个邻接点
}
输出一条两顶点之间的简单路径
void FindaPath(AdjiGraph *G,intu,int v,intpathC],int dy(//d表示path中的路径长度,初始为-1
int w,i;ArcNode* p;
visited[u]= 1;
d++; path[d]=u;
//路径长度d增1.顶点0加人到路径中
if (u==v)
( for (i=0;i<=d;i++)
//找到一条路径后输出并返回
printf("%d ",path[i);
printf("
");
return ;
p=G - > adjlist[u]. firstarc;
//p指向顶点u的第一个邻接点
while (p!= NULL)
{w=p - -> adjvex;
//邻接点的编号为w
if (visited[w]==0)
FindaPath( G, w, V, path,d);p=p - > nextarc;
//p指向顶点u的下一个邻接点
}
寻找两顶点间的最短路径
- 即求距离顶点u到顶点v的边数最少的顶点序列。利用广度优先遍历算法,从u出发一层一层的向外拓展
结构体定义如下:
typedef struct{int data;
//顶点编号
1nt parent;
//前一个顶点的位置
} QUERE;
//非环形队列类型
void FindaPath AdjGraph* G, int
( //d表示 path中的路径长度,u,int v,intpathC].int d
int w,i;ArcNode *P;
初始为一1
visited[u]=1;
d++; path[d]=u;
/路径长度d增1.顶点0加人河路径中
if (u==v)
{ for (i=0;i<=d:i+H //找到一 条路径后输 出并返回
printf("%d”.,path[i]);
printf("
");
return;
}
p=G -> adjlist[u] . firstare;
//p指向顶点u的第一个邻接点
while (p!= NULL)
w=p- > adjvex;
//邻接点的编号为w
if (visited[w]==0)
FindaPath( G, w, v, path,d);
p=p- > nextarc;
//p指向顶点u的下一个邻接点
}
}
while (p!= NULL)
{ if (visited[p-> adjvex]==0)
{visited[p-> adjvex]=1;
rear++ ;
//将w的未访问过的邻接点进队
qu[ rear].data=p- > adjvex;
qu[ rear」. parent= front;
p=P一> nextarc;
//找w的下一个邻接点
最小生成树
- 生成树:一个连通图的生成树是一个极小
图存储结构
最小生成树相关算法及应用
最短路径相关算法及应用,可适当拓展最短路径算法
拓扑排序、关键路径
上面要求是必须完成,但是完成时候需要根据实际所学再展开。内容简单应付,0分。注意每个知识点务必要举例,图形等说明。
这块内容是总结复习,所有操作、代码清自己写代码或伪代码演示,不得复制课件代码或PPT
1.2.谈谈你对图的认识及学习体会。
本块内容必须用自己语言总结所学及图的相关应用。
2.阅读代码(0--5分)
找3份优秀代码,理解代码功能,并讲出你所选代码优点及可以学习地方。主要找以下类型代码:
考研题
PAT天梯赛题目
ACM题解
leecode--图1
leecode--图2
题目集可能有和图无关题目,但是阅读代码必须选择和图相关题目
注意:不能选教师布置在PTA的题目。完成内容如下。
2.1 题目及解题代码
可截图,或复制代码,需要用代码符号渲染。题目截图后一定要清晰。
2.1.1 该题的设计思路
链表题目,请用图形方式展示解决方法。同时分析该题的算法时间复杂度和空间复杂度。
2.1.2 该题的伪代码
文字+代码简要介绍本题思路
2.1.3 运行结果
网上题解给的答案不一定能跑,请把代码复制自己运行完成,并截图。
2.1.4分析该题目解题优势及难点