太原理工大学 数据结构与算法R实验报告(3)

实验名称(图)

一、实验目的和要求

熟悉图的存储结构,掌握有关算法的实现,了解图在计算机科学及其他工程技术中的应用。

二、实验内容和原理

选做第二题

输入:(第一行输入顶点个数,第二行输入邻接矩阵,接下来输入两顶点与查找路径长度)

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、优先搜索一棵子树,然后是另一棵,所以和广搜对比,有着内存需要相对较少的优点

缺点
1、要多次遍历,搜索所有可能路径,标识做了之后还要取消。
2、在深度很大的情况下效率不高

广搜优缺点
优点:
  1、对于解决最短或最少问题特别有效,而且寻找深度小
  2、每个结点只访问一遍,结点总是以最短路径被访问,所以第二次路径确定不会比

第一次短。
缺点:
  内存耗费量大(需要开大量的数组单元用来存储状态)

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值