实验名称(图) |
一、实验目的和要求 熟悉图的存储结构,掌握有关算法的实现,了解图在计算机科学及其他工程技术中的应用。 |
二、实验内容和原理 选做第二题 输入:(第一行输入顶点个数,第二行输入邻接矩阵,接下来输入两顶点与查找路径长度) 3 0 1 1 1 0 1 1 1 0 0 2 2 输出: 给定的两个顶点0,2之间存在长度为2的简单路径. 所有路径为:0 1 2 存储结构:邻接矩阵和邻接表 算法思想: 将邻接矩阵转换为邻接表 图 G 的邻接矩阵: 0 1 1 0 0 0 0 0 1 0 0 1 1 0 0 0 1 0 0 0 0 1 1 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 0 1 0 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 1 1 0 0 0 将 g 转换为邻接表 G 图 G 的邻接表: 0: 1→2 1: 0→3→4 2: 0→5→6 3: 1→7 4: 1→7 5: 2→6 6: 2→5 7: 3→4 深度优先搜索算法思想: 深度优先遍历图的方法是,从图中某顶点v出发: (1)访问顶点v; (2)依次从v的未被访问的邻接点出发,对图进行深度优先遍历;直至图中和v有路径相通的顶点都被访问; (3)若此时图中尚有顶点未被访问,则从一个未被访问的顶点出发,重新进行深度优先遍历,直到图中所有顶点均被访问过为止 |
三、主要仪器设备 惠普笔记本,win10环境,皆在cpp文件运行,请同样以cpp形式打开 |
四、操作方法与实验步骤 第二题: |
#include<stdio.h>
#include<windows.h>
#define MAXV 100
static int s1=0;
/*
1.首先要输入图,我采用输入邻接矩阵的方式来输入图
2.进行邻接矩阵转换为邻接表,MatToList()
3.进行起点与终点输入,并输入查找的路径长度
4.进行路径查找与输出 DFSFind()
*/
typedef struct{//邻接矩阵存储结构
int no;
int info;
}VertexType;
typedef struct{ //图的定义
int edges[MAXV][MAXV];
int n,e;
VertexType vexs[MAXV];
}MGraph;
typedef struct ANode{ //邻接表存储结构
int adjvex;
struct ANode *nextarc;//指向下一条弧的指针
int info;
}ArcNode;
typedef struct Vnode{//顶点表头结点的定义
int data;
ArcNode *firstarc;//指向第一条弧
}VNode;
typedef VNode AdjList[MAXV];//AdjList是邻接表类型,将大表转换为几个小的连接在一起
typedef struct{
AdjList adjlist;//邻接表
int n,e;//顶点数,边数
}ALGraph;
typedef struct node{
int data;
struct node *next;
}List;
void DFSFind(ALGraph *G,int x,int l,int k,int visited[],int path[],int d);//深度优先搜索路径并以给定路径长度给出路径
void MatToList(MGraph g,ALGraph *&G);//邻接矩阵转换为邻接表
int main(){
int path[MAXV],visited[MAXV],A[MAXV][MAXV],i,j,m,l,k;
MGraph g;
ALGraph *G;
printf("请输入顶点个数:");
scanf("%d",&g.n);
g.e=0;
printf("请输入邻接矩阵:(%d*%d)\n",g.n,g.n );
for(i=0;i<g.n;i++){
for(j=0;j<g.n;j++)
scanf("%d",&A[i][j]);
getchar();
}
for(i=0;i<g.n;i++)
for(j=0;j<g.n;j++){
g.edges[i][j]=A[i][j];
if(A[i][j]==1) g.e++;
}
MatToList(g,G);
printf("\n请选择起始顶点(0~%d):",g.n-1);
scanf("%d",&m);
printf("\n请选择到达顶点(0~%d):",g.n-1);
scanf("%d",&l);
printf("\n请选择路径长度:");
scanf("%d",&k);
for(i=0;i<G->n;i++)
visited[i]=0;
DFSFind(G,m,l,k,visited,path,-1);
system("pause");
return 0;
}
void MatToList(MGraph g,ALGraph *&G){
int i,j,n=g.n;
ArcNode *p;
G=(ALGraph *)malloc(sizeof(ALGraph));
for(i=0;i<n;i++)
G->adjlist[i].firstarc=NULL;
for(i=0;i<n;i++)
for(j=n-1;j>=0;j--)
if(g.edges[i][j]!=0){
p=(ArcNode *)malloc(sizeof(ArcNode));
p->adjvex=j;
p->nextarc=G->adjlist[i].firstarc;
G->adjlist[i].firstarc=p;
}
G->n=n;
G->e=g.e;
}
void DFSFind(ALGraph *G,int x,int l,int k,int visited[],int path[],int d){
int i,node;
ArcNode *r;
visited[x]=1;//第一个点设为已访问点,接下来以该点进行深度优先遍历
d++;
path[d]=x;
if(x==l&&d==k){
s1++;
if(s1==1)
printf("\n给定的两个顶点%d,%d之间存在长度为%d的简单路径.\n所有路径为:\n",path[0],l,k);
else
printf("无该路径");
for(i=0;i<=k;i++)
printf("%d ",path[i]);
printf("\n");
}
r=G->adjlist[x].firstarc;
while(r!=NULL){
node=r->adjvex;
if(visited[node]==0)
DFSFind(G,node,l,k,visited,path,d);
r=r->nextarc;
}
visited[x]=0;
d--;
}
五、实验数据记录和处理
第二题:
六、实验结果与分析 优点: 能找出所有解决方案 缺点: 要多次遍历,搜索所有可能路径,标识做了之后还要取消。 DFS复杂度分析 DFS算法是一一个递归算法,需要借助一个递归工作栈,故它的空问复杂度为O(V)。 遍历图的过程实质上是对每个顶点查找其邻接点的过程,其耗费的时间取决于所采用结构。 邻接表表示时,查找所有顶点的邻接点所需时间为O(E),访问顶点的邻接点所花时间为O(V),此时,总的时间复杂度为O(V+E) 采用深度优先搜索,有利于解决查找路径问题和迷宫问题,同时我也学习了广度优先搜索。并对比两者不同,从而采用更加合适的算法。 |
七、讨论、心得 深搜优缺点 优点 1、能找出所有解决方案 2、优先搜索一棵子树,然后是另一棵,所以和广搜对比,有着内存需要相对较少的优点 缺点 广搜优缺点 第一次短。 |