数据结构——图的操作算法(二)

一、实验目的及要求

  1. 熟悉各种图的存储结构(邻接矩阵和邻接表)。
  2. 掌握图的深度优先和广度优先遍历算法。
  3. 掌握克鲁斯卡尔算法生成最小生成树的方法。
  4. 掌握狄克斯特拉算法计算最短路径和最短路径长度的方法。

二、实验内容(或实验原理、实验拓扑)

  1. 编写一个程序,输出下面带权有向图的邻接表,并根据该邻接表,实现图的深度优先遍历算法,具体要求如下:
    (1)从顶点0开始的深度优先遍历序列(递归算法)
    (2)从顶点0开始的深度优先遍历序列(非递归算法)

三、实验设计方案(包括实验步骤、设计思想、算法描述或开发流程等)

(一)在graph.h中创建图的邻接表存储结构:
1.首先定义邻接表类型中的边结点类型ArcNode;
2.然后定义邻接表头结点类型VNode;
3.接着定义完整的图邻接表类型AdjGraph。
(二)在main.cpp中完成图的基本运算算法:
1. 创建图的邻接表CreateAdj(AdjGraph *&G,int A[MAXV][MAXV],int n,int e);
2. 输出邻接表G DispAdj(AdjGraph G);
3. 销毁图的邻接表DestroyAdj(AdjGraph *&G);
4.定义全局函数visited[MAXV];
5. 递归深度优先算法(AdjGraph *G,int v);
6. 非递归深度优先算法DFS1(AdjGraph *G,int v);
5.主函数 main()根据问题依次调用基本操作函数并编写通俗易懂的语句输出。

四、实验结果(包括设计效果、测试数据、运行结果等)

运行结果如下:

五、实验小结(包括收获、心得体会、注意事项、存在问题及解决办法、建议等)

从给定图中任意指定的顶点(称为初始点)出发,按照某种搜索方法沿着图的边访问图中的所有顶点,使每个顶点仅被访问一次,这个过程为图的遍历。深度优先搜索遍历的过程是:从图中某个初始顶点v出发,首先访问初始顶点v。然后选择一个与顶点v相邻且没被访问过的顶点w为初始顶点,再从w出发进行深度优先搜索,直到图中与当前顶点v邻接的所有顶点都被访问过为止。

六、附录(包括作品、流程图、源程序及命令清单等)

graph.h:
//图的邻接表存储结构
#define INF 32767				//定义∞
#define	MAXV 100				//最大顶点个数
typedef char InfoType;
//以下定义邻接表类型
typedef struct ANode
{	int adjvex;					//该边的邻接点编号
	struct ANode *nextarc;		//指向下一条边的指针
	int weight;					//该边的相关信息,如权值(用整型表示)
} ArcNode;						//边结点类型
typedef struct Vnode
{	InfoType info;				//顶点其他信息
	int count;					//存放顶点入度,仅仅用于拓扑排序
	ArcNode *firstarc;			//指向第一条边
} VNode;						//邻接表头结点类型
typedef struct 
{	VNode adjlist[MAXV];		//邻接表头结点数组
	int n,e;					//图中顶点数n和边数e
} AdjGraph;						//完整的图邻接表类型

main.cpp:
#include <stdio.h>
#include <malloc.h>
#include "graph.h"
//----创建图的邻接表G----------------------------------
void CreateAdj(AdjGraph *&G,int A[MAXV][MAXV],int n,int e) //创建图的邻接表
{
	int i,j;
	ArcNode *p;
	G=(AdjGraph *)malloc(sizeof(AdjGraph));
	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 (A[i][j]!=0 && A[i][j]!=INF)			//存在一条边
			{	p=(ArcNode *)malloc(sizeof(ArcNode));	//创建一个结点p
				p->adjvex=j;
				p->weight=A[i][j];
				p->nextarc=G->adjlist[i].firstarc;	//采用头插法插入结点p
				G->adjlist[i].firstarc=p;
			}
	G->n=n; G->e=n;
}
//----输出邻接表G----------------------------------
void DispAdj(AdjGraph *G)
{
	int i;
	ArcNode *p;
	for (i=0;i<G->n;i++)
	{
		p=G->adjlist[i].firstarc;
		printf("%3d: ",i);
		while (p!=NULL)
		{
			printf("%3d[%d]→",p->adjvex,p->weight);
			p=p->nextarc;
		}
		printf("∧\n");
	}
}
//----销毁图的邻接表----------------------------------
void DestroyAdj(AdjGraph *&G)
{	int i;
	ArcNode *pre,*p;
	for (i=0;i<G->n;i++)			//扫描所有的单链表
	{	pre=G->adjlist[i].firstarc;	//p指向第i个单链表的首结点
		if (pre!=NULL)
		{	p=pre->nextarc;
			while (p!=NULL)			//释放第i个单链表的所有边结点
			{	free(pre);
				pre=p; p=p->nextarc;
			}
			free(pre);
		}
	}
	free(G);						//释放头结点数组
}
//----深度优先递归算法----------------------------------
int visited[MAXV];						//全局数组
void DFS(AdjGraph *G,int v)   //递归深度优先算法
{
	ArcNode *p;
	visited[v]=1;                   	//置已访问标记
	printf("%3d",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的下一条弧的弧头结点
	}
}
//----深度优先非递归算法----------------------------------
void DFS1(AdjGraph *G,int v)   //非递归深度优先算法
{
	ArcNode *p;
	ArcNode *St[MAXV];
	int top=-1,w,i;
    for (i=0;i<G->n;i++)
		visited[i]=0;		//顶点访问标志均置成0
	printf("%3d",v);        //访问顶点v
	visited[v]=1;
	top++;                  //将顶点v的第一个相邻顶点进栈
	St[top]=G->adjlist[v].firstarc;
	while (top>-1)          //栈不空循环
	{
		p=St[top]; top--;   //出栈一个顶点作为当前顶点
		while (p!=NULL)     //查找当前顶点的第一个未访问的顶点
		{
			w=p->adjvex;
			if (visited[w]==0)
			{
				printf("%3d",w); //访问w
				visited[w]=1;
				top++;           //将顶点w的第一个顶点进栈
				St[top]=G->adjlist[w].firstarc;
				break;           //退出循环
			}
			p=p->nextarc;        //找下一个相邻顶点
		}
	}
	printf("\n");
}
int main()
{
	AdjGraph *G;
	int A[MAXV][MAXV]={
		{0,5,INF,7,INF,INF},
		{INF,0,4,INF,INF,INF},
		{8,INF,0,INF,INF,9},
		{INF,INF,5,0,INF,6},
		{INF,INF,INF,5,0,INF},
		{3,INF,INF,INF,1,0}};
	int n=6, e=10;
	CreateAdj(G,A,n,e);             //建立实验讲义中的邻接表
	printf("图G的邻接表:\n");
	DispAdj(G);                     //输出邻接表
	printf("从顶点0开始的DFS(递归算法):\n");
	DFS(G,0);printf("\n");
	printf("从顶点0开始的DFS(非递归算法):\n");
	DFS1(G,0);
}
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值