数据结构c实验十 图

实验十 图

1、实验目的:
(1)理解图的概念
(2)掌握图的常见存储结构。
(3)理解图的常见操作。
2、实验环境与设备:
已安装Visual Studio 2010(或其以上版本)集成开发环境的计算机。
3、实验原理:
(1)图的邻接矩阵存储。
(2)带权无向图(无向网)的最小生成树实现。
4、实验内容:
(1)实现图的邻接矩阵存储
(2)输出显示图的顶点、边和邻接矩阵
(3)求解图的最小生成树。

#include <stdio.h>
#include <stdlib.h>

// 预定义常量
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2

// 预定义类型
typedef int Status;

// 本程序定义常量
#define INFINITY INT_MAX	// 表示最大值无穷大
#define MAX_VERTEX_NUM 20	// 最大顶点个数

// 本程序定义类型
typedef enum{ DG, DN, UDG, UDN } GraphKind;  // 图的种类标记{有向图,有向网,无向图,无向网}
typedef int VRType ;		// 边的类型,对无权图,用1或0表示相邻否;对带权图,则为权值类型
typedef char VertexType ;	// 顶点元素类型
typedef char InfoType ;		// 边信息

typedef struct ArcCell		// 表示一条边
{
	VRType adj;			// 边
	InfoType *info;		// 该边相关信息的指针
}ArcCell, AdjMatrix[ MAX_VERTEX_NUM ][ MAX_VERTEX_NUM ];

typedef struct
{
	VertexType vexs[ MAX_VERTEX_NUM ];// 顶点向量,存储顶点信息
	AdjMatrix arcs;		// 邻接矩阵,存储边
	int vexnum;			// 图的当前顶点数
	int arcnum;			// 图的当前边数
	GraphKind kind;		// 图的种类标记
}MGraph;				// 采用邻接矩阵存储的图

typedef struct	  // 记录从顶点集U到V-U的代价最小的边的辅助数组定义:
{
	VertexType adjvex;	
	VRType lowcost;		

}closedge[ MAX_VERTEX_NUM ];

// 算法7.1 采用数组(邻接矩阵)表示法,构造图G。
Status CreateGraph( MGraph *pG ) {   
	printf( "请输入图的种类(0:有向图;1:有向网;2:无向图;3:无向网):" );
    scanf("%d", &pG->kind);		// 自定义输入函数,读入一个随机值
	
    switch (pG->kind) {
        case  DG: 
			return CreateDG(pG);   // 构造有向图G
        case  DN: 
			return CreateDN(pG);   // 构造有向网G
        case UDG: 
			return CreateUDG(pG);  // 构造无向图G
        case UDN: 
			return CreateUDN(pG);  // 构造无向网G,算法7.2
        default : 
			return ERROR;
    }
} // CreateGraph

// 确定顶点u在G中位置
int LocateVex( MGraph G, VertexType u )
//  算法 7.2,采用数组(邻接矩阵)表示法,构造无向网G。
Status CreateUDN(MGraph *pG)
// 显示网络(包括有向网和无向网)
void DisplayNet( MGraph G )
//在数组minEdge中求非零的最小边
int minimum( closedge minEdge, MGraph G )
// 算法7.9,用普里姆算法从第u个顶点出发构造网G的最小生成树T,输出T的各条边。
void MiniSpanTree_PRIM(MGraph G, VertexType u)
// 主函数
int main( void )
{
	MGraph G ;
	
	printf( "请输入一个无向网:\n" );
	CreateGraph( &G );
    if( G.kind == DG || G.kind == UDG )
		DisplayGraph( G );
	else
		DisplayNet( G );

	printf( "该无向网的最小生成树为:\n" );
	MiniSpanTree_PRIM( G, '1' );	//从1号顶点(即v1)开始使用普里姆算法求最小生成树
	printf( "\n" );	

	return 0;
}

5、实验考核:
1)完成纸质版实验报告
2)提交电子版作业

6、执行结果示例如下:
在这里插入图片描述

构造上述图,程序的参考输入数据如下:
3
6
10

1
2
3
4
5
6

1 2 6
1 3 1
2 3 5
1 4 5
3 4 5
3 6 4
4 6 2
2 5 3
3 5 6
5 6 6

记不清了,代码里好像有bug,只适合这个实验能跑通

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 预定义常量
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2

// 预定义类型
typedef int Status;

// 本程序定义常量
#define INFINITY INT_MAX	// 表示最大值无穷大
#define MAX_VERTEX_NUM 20	// 最大顶点个数

// 本程序定义类型
typedef enum{ DG, DN, UDG, UDN } GraphKind;  // 图的种类标记{DG有向图, DN有向网, UDG无向图, UDN无向网}
typedef int VRType;		// 边的类型,对无权图,用1或0表示相邻否;对带权图,则为权值类型
typedef char VertexType;	// 顶点元素类型
typedef char InfoType;		// 边信息

typedef struct ArcCell		// 表示一条边
{
	VRType adj;			// 边
	InfoType *info;		// 该边相关信息的指针
}ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];

typedef struct
{
	VertexType vexs[MAX_VERTEX_NUM];// 顶点向量,存储顶点信息
	AdjMatrix arcs;		// 邻接矩阵,存储边
	int vexnum;			// 图的当前顶点数
	int arcnum;			// 图的当前边数
	GraphKind kind;		// 图的种类标记
}MGraph;				// 采用邻接矩阵存储的图

// 确定顶点u在G中位置
int LocateVex(MGraph G, VertexType u){
	int i;
	for (i = 0; i < G.vexnum; i++)
	{
		if (G.vexs[i] == u)
			return i;
	}
	return -1;
}

typedef struct	  // 记录从顶点集U到V-U的代价最小的边的辅助数组定义:
{
	VertexType adjvex;
	VRType lowcost;

}closedge[MAX_VERTEX_NUM];

//创建有向图
Status CreateDG(MGraph *pG){
	pG->kind = DG;
	printf("有向图的点数:"); scanf_s("%d", &pG->vexnum);
	printf("有向图的边数:"); scanf_s("%d", &pG->arcnum);
	for (int i = 0; i < pG->vexnum; i++){ printf("G.vexs[%d]:", i); scanf_s("%d", &pG->vexs[i]); }
	//初始化图的距离
	for (int i = 0; i < pG->vexnum; i++)
	for (int j = 0; j < pG->vexnum; j++)
		pG->arcs[i][j].adj = INFINITY;
	for (int i = 0; i < pG->arcnum; i++)
	{
		printf("\nv1 <char>, v2 <char>:");
		int q, w;
		scanf_s("%d %d", &q, &w);
		q = LocateVex(*pG, q);
		w = LocateVex(*pG, w);
		pG->arcs[q][w].adj = 1;
	}
	return OK;
}
//创建有向网
Status CreateDN(MGraph *pG){
	pG->kind = DG;
	printf("有向网的点数:"); scanf_s("%d", &pG->vexnum);
	printf("有向网的边数:"); scanf_s("%d", &pG->arcnum);
	for (int i = 0; i < pG->vexnum; i++){ printf("G.vexs[%d]:", i); scanf_s("%d", &pG->vexs[i]); }
	//初始化图的距离
	for (int i = 0; i < pG->vexnum; i++)
	for (int j = 0; j < pG->vexnum; j++)
		pG->arcs[i][j].adj = INFINITY;
	for (int i = 0; i < pG->arcnum; i++)
	{
		printf("\nv1 <char>, v2 <char>, v <int>:");
		int q, w, e;
		scanf_s("%d %d %d", &q, &w, &e);
		q = LocateVex(*pG, q);
		w = LocateVex(*pG, w);
		pG->arcs[q][w].adj = e;
	}
	return OK;
}
//创建无向图
Status CreateUDG(MGraph *pG){
	printf("无向图的点数:"); scanf_s("%d", &pG->vexnum);
	printf("无向图的边数:"); scanf_s("%d", &pG->arcnum);
	for (int i = 0; i < pG->vexnum; i++){ printf("G.vexs[%d]:", i); scanf_s("%d", &pG->vexs[i]); }
	//初始化网的距离
	for (int i = 0; i < pG->vexnum; i++)
	for (int j = 0; j < pG->vexnum; j++)
		pG->arcs[i][j].adj = 0;
	for (int i = 0; i < pG->arcnum; i++)
	{
		printf("v1 <char>, v2 <char>:");
		int q, w;
		scanf_s("%d %d", &q, &w);
		q = LocateVex(*pG, q);
		w = LocateVex(*pG, w);
		pG->arcs[q][w].adj = 1;
	}
	return OK;
}
//创建无向网
//  算法 7.2,采用数组(邻接矩阵)表示法,构造无向网G。
Status CreateUDN(MGraph *pG){
	printf("无向网的点数:"); scanf_s("%d", &pG->vexnum);
	printf("无向网的边数:"); scanf_s("%d", &pG->arcnum);
	for (int i = 0; i < pG->vexnum; i++){ printf("G.vexs[%d]:", i); scanf_s("%d", &pG->vexs[i]); }
	//初始化网的距离
	for (int i = 0; i < pG->vexnum; i++)
	for (int j = 0; j < pG->vexnum; j++)
		pG->arcs[i][j].adj = INFINITY;
	for (int i = 0; i < pG->arcnum; i++)
	{
		printf("v1 <char>, v2 <char>, v <int>:");
		int q, w, e;
		scanf_s("%d %d %d", &q, &w, &e);
		q = LocateVex(*pG, q);
		w = LocateVex(*pG, w);
		pG->arcs[q][w].adj = e;
		pG->arcs[w][q].adj = e;
	}
	return OK;
}
// 算法7.1 采用数组(邻接矩阵)表示法,构造图G。
Status CreateGraph(MGraph *pG) {
	printf("请输入图的种类(0:有向图;1:有向网;2:无向图;3:无向网):");
	scanf_s("%d", &pG->kind);		// 自定义输入函数,读入一个随机值

	switch (pG->kind) {
	case  DG:
		return CreateDG(pG);   // 构造有向图G
	case  DN:
		return CreateDN(pG);   // 构造有向网G
	case UDG:
		return CreateUDG(pG);  // 构造无向图G
	case UDN:
		return CreateUDN(pG);  // 构造无向网G,算法7.2
	default:
		return ERROR;
	}
} // CreateGraph



// 显示网络(包括有向网和无向网)
void DisplayNet(MGraph G){
	int i, j;
	for (i = 0; i < G.vexnum; i++)
	{
		printf("\t%d", G.vexs[i]);
	}
	for (i = 0; i < G.vexnum; i++)
	{
		printf("\n%d", G.vexs[i]);
		for (j = 0; j < G.vexnum; j++)
		{
			if (G.arcs[i][j].adj < INFINITY)
			{
				printf("\t%d", G.arcs[i][j].adj);
			}
			else
				printf("\t∞");
		}
	}
	printf("\n");
}
//在数组minEdge中求非零的最小边
int minimum(closedge minEdge, MGraph G){
	int i = 0, j, k, min;
	while (!minEdge[i].lowcost)
		i++;
	min = minEdge[i].lowcost; // 第一个不为0的值 
	k = i;
	for (j = i + 1; j<G.vexnum; j++)
	if (minEdge[j].lowcost>0)
	if (min > minEdge[j].lowcost)
	{
		min = minEdge[j].lowcost;
		k = j;
	}
	return k;
}



//// 算法7.9,用普里姆算法从第u个顶点出发构造网G的最小生成树T,输出T的各条边。
//void MiniSpanTree_PRIM(MGraph G, VertexType u){
//	int i, j, k;
//	closedge minedge;
//	k = LocateVex(G, u);
//	for (j = 0; j<G.vexnum; ++j) // 辅助数组初始化 
//	{
//		if (j != k)
//		{
//			strcpy_s(&minedge[j].adjvex, 20, &u);
//			minedge[j].lowcost = G.arcs[k][j].adj;
//		}
//	}
//	minedge[k].lowcost = 0; // 初始,U={u} 
//	printf("最小代价生成树的各条边为:\n");
//	for (i = 1; i<G.vexnum; ++i)
//	{ // 选择其余G.vexnum-1个顶点 
//		k = minimum(minedge, G); // 求出T的下一个结点:第K顶点 
//		printf("(%s-%d)\n", minedge[k].adjvex, G.vexs[k]); // 输出生成树的边 
//		minedge[k].lowcost = 0; // 第K顶点并入U集 
//		for (j = 0; j<G.vexnum; ++j)
//		if (G.arcs[k][j].adj<minedge[j].lowcost)
//		{
//			// 新顶点并入U集后重新选择最小边 
//			strcpy_s(&minedge[j].adjvex, 20, &G.vexs[k]);
//			minedge[j].lowcost = G.arcs[k][j].adj;
//		}
//	}
//
//}

void MiniSpanTree_PRIM(MGraph G, int u)
{
	closedge minedge;

	int i, j, k,quan=0;
	for (j = 0; j < G.vexnum; ++j)        //辅助数组初始化  
	if (j != u)
	{
		minedge[j].adjvex = G.vexs[u];
		minedge[j].lowcost = G.arcs[u][j].adj;
	}
	minedge[u].lowcost = 0;        //初始化U={u}  
	for (i = 0; i < G.vexnum; ++i)
	{
		int min = INT_MAX;
		k = -1;
		for (j = 0; j<G.vexnum; ++j)    //求出最小生成树的下一个顶点k  
		if (minedge[j].lowcost >0 && minedge[j].lowcost < min)
		{
			k = j;
			min = minedge[j].lowcost;
		}//if  
		if (k < 0){
		printf("\n该最小生成树的代价:%d\n", quan);
		return;
	    }

		printf("<%d,%d>", minedge[k].adjvex, G.vexs[k]); //输出生成树的边  
		quan += minedge[k].lowcost;

		minedge[k].lowcost = 0;                    //第k顶点并入U集  
		for (j = 0; j < G.vexnum; ++j)
		if (G.arcs[k][j].adj < minedge[j].lowcost)   //新顶点并入U后,重新选择最小边  
		{
			minedge[j].adjvex = G.vexs[k];
			minedge[j].lowcost = G.arcs[k][j].adj;
		}
	}
	
}//MiniSpanTree_PRIM  

// 主函数
int main(void)
{
	MGraph G;

	printf("请输入一个无向网:\n");
	CreateGraph(&G);
	if (G.kind == DG || G.kind == UDG)
		//DisplayGraph(G);
		return 0;
	else
		DisplayNet(G);

	printf("该无向网的最小生成树为:\n");
	MiniSpanTree_PRIM(G, 0);	//从1号顶点(即v1)开始使用普里姆算法求最小生成树
	printf("\n");
	system("pause");
	return 0;
}

在这里插入图片描述

发布了15 篇原创文章 · 获赞 0 · 访问量 240

猜你喜欢

转载自blog.csdn.net/qq_44796882/article/details/105464865