数据结构试验-试验9-图及其应用

图的基本操作,为了便于信息即可显示,在函数内部输出了数据,可后修改来实现更接近封装程序。

程序包可在次下载:http://download.csdn.net/detail/decting/4850581

GraphTestApp.c内容:

#include <stdio.h>
#include "M_AL_Graph.h"
int main()
{
	int i,j,n,m,x,y,w;
	Mgraph A;	//定义邻接矩阵,
	Graph* G=CreateGraph();	//定义图并创建图
	//输入图信息,文件方式,可注释掉来手动输入
	freopen("Input.txt","r",stdin);	
	
	scanf("%d%d",&n,&m);	//输入节点数和边数
	for(i=0; i<m; i++)
	{
		scanf("%d%d%d",&x,&y,&w);
		AddGraphEdge(G,x,y,w);	//无向图正反两遍加入边
		AddGraphEdge(G,y,x,w);
	}
	AdjGraphMatrix(G,A);	//得到邻接矩阵,以0填充无关边
	//测试1、输出邻接矩阵
	printf("1、\n邻接矩阵如下:\n");
	for(i=1;i<=n;i++)
	{
		for(j=1;j<=n;j++)
			printf("%2d ",A[i][j]);
		printf("\n");
	}
	//测试2、输出邻接表
	printf("2、\n邻接表如下:\n");
	DisplayGraph(G);
	//测试3、输出深度和宽度遍历
	printf("3、\n深度遍历如下:\n");
	GraphDeepthTraversal(G);
	printf("\n宽度遍历如下:\n");
	GraphBreadthTraversal(G);
	//测试4、输出prim算法生成的最小生成树,个边和总权值
	printf("\n4、\n最小生成树的各边分别为:");
	printf("\n最小生成树总权值为:%d\n",GraphPrim(G));
	return 0;
}
/*
--------------------------------------
测试图数据1    |   测试图数据2
6 10           |   6 10
1 6 21         |   1 2 6
1 5 19         |   1 3 1
1 2 10         |   1 4 5
2 6 11         |   2 3 5
5 6 33         |   3 4 5
4 6 14         |   2 5 3
4 5 18         |   3 5 6
3 4 6          |   3 6 4
2 4 6          |   5 6 6
2 3 5          |   4 6 2
--------------------------------------
*/
/*测试图数据1的结果:
--------------------------------------
1、
邻接矩阵如下:
 0 10  0  0 19 21
10  0  5  6  0 11
 0  5  0  6  0  0
 0  6  6  0 18 14
19  0  0 18  0 33
21 11  0 14 33  0
2、
邻接表如下:
 1:  2  5  6
 2:  1  3  4  6
 3:  2  4
 4:  2  3  5  6
 5:  1  4  6
 6:  1  2  4  5
3、
深度遍历如下:
1 2 3 4 5 6
宽度遍历如下:
1 2 5 6 3 4
4、
最小生成树的各边分别为:10 5 6 11 18
最小生成树总权值为:50
Press any key to continue
--------------------------------------
*/
M_AL_Graph.h的内容:
/****
*	每个图会有一个图的头部,定义时如下
*	Graph* G;
*	CreateGraphHead(&G);
*	或者如下定义
*	Graph* G=CreateGraph();
*	Mgraph 是邻接矩阵的定义类型
*	定义时,Mgraph A;等价于WeightType A[MAXNODE][MAXNODE];
*	WeightType是int型
*	GraphDeepthTraversal(Graph*)和GraphBreadthTraversal(Graph*)
*	分别是深度和宽度优先遍历的调用函数,直接调用
*	GraphPrim(Graph*)为prim生成最小生成树,又返回值,为生成树总权值
*******/

#ifndef _M_AL_GRAPH_H_
#define _M_AL_GRAPH_H_
#include <memory.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#define MAXWEIGHT 0x7FFFFFFF
#define MAXNODE 300		//定义最大节点数

typedef int NodeType;	//节点类型
typedef int WeightType;
//定义邻接矩阵,Graph是二维数组的标示
typedef WeightType Mgraph[MAXNODE][MAXNODE];	

typedef struct GNODE
{//定义图中每个节点的信息,节点信息和连接的节点
	NodeType data;
	WeightType weight;
	struct GNODE* link;
}GraphNode;

typedef struct GRAPH
{//定义图类型
	GraphNode *node;
	struct GRAPH* next;
}Graph;

Graph* CreateGraph();
void CreateGraphHead(Graph**);
void CreateGraphNode(GraphNode**);
void AddGraphNode(Graph*,NodeType);
void DisplayGraphNode(Graph*);
void AddGraphEdge(Graph*,NodeType,NodeType,WeightType);
void AdjGraphMatrix(Graph*,Mgraph);
void DisplayGraph(Graph*);
GraphNode* FindGraphNode(Graph*,NodeType);
void GraphDeapth(Graph*,GraphNode*,WeightType*);
void GraphDeepthTraversal(Graph*);
void GraphBreadthTraversal(Graph*);
WeightType GraphPrim(Graph*);

#endif //_M_AL_GRAPH_H_
M_AL_Graph.c的内容:
#include "M_AL_Graph.h"
Graph* CreateGraph(void)
{//返回式创建图节点
	Graph* Temp_G;
	CreateGraphHead(&Temp_G);
	return Temp_G;
}
void CreateGraphHead(Graph** G)
{//调用式创建图头部节点
	*G=(Graph*)malloc(sizeof(Graph));
	(*G)->next=NULL;
	CreateGraphNode(&(*G)->node);
}
void CreateGraphNode(GraphNode** N)
{//创建节点
	*N=(GraphNode*)malloc(sizeof(GraphNode));
	(*N)->weight=(*N)->data=0;
	(*N)->link=NULL;
}
void AddGraphNode(Graph* G,NodeType N)
{//增加节点,向图中增加节点,会按照从小到大的顺序排列
	Graph* Temp_G=CreateGraph();
	while(G->next!=NULL&&G->next->node->data<=N) G=G->next;
	if(G->node->data==N) return;
	Temp_G->next=G->next;
	Temp_G->node->data=N;
	G->next=Temp_G;
}
void DisplayGraphNode(Graph* G)
{//临时的图节点输出,便于调试,查看
	while(G->next!=NULL)
	{
		G=G->next;
		printf("%d ",G->node->data);
	}
}
void AddGraphEdge(Graph* G,NodeType N1,NodeType N2,WeightType W)
{//加入边,N1到N2的权值为W
	GraphNode *Temp_N,*N;
	CreateGraphNode(&Temp_N);	//先创建个节点
	AddGraphNode(G,N1);	//保证N1在图中
	AddGraphNode(G,N2);	//保证N2在图中
	while(G->next->node->data!=N1) G=G->next;//寻找N1节点的位置
	N=G->next->node;
	Temp_N->data=N2;
	Temp_N->weight=W;
	while(N->link!=NULL&&N->link->data<=N2) N=N->link;//寻找N2该插入的位置
	Temp_N->link=N->link;
	N->link=Temp_N;
}
void AdjGraphMatrix(Graph* G,Mgraph A)
{//Adjacent Matrix, 得到图G的邻接矩阵A
	GraphNode *N;
	NodeType X;
	//初始化A内权值为0,表示不相连接
	memset(A,0,MAXNODE*MAXNODE*sizeof(WeightType));
	while(G->next!=NULL)
	{
		G=G->next; N=G->node;
		X=N->data;
		while(N->link!=NULL)
		{
			N=N->link;
			A[X][N->data]=N->weight;
		}
	}
}
void DisplayGraph(Graph* G)
{//以邻接矩阵的形式输出G
	GraphNode *N;
	while(G->next!=NULL)
	{
		G=G->next; N=G->node;
		printf("%2d: ",N->data);
		while(N->link!=NULL)
		{
			N=N->link;
			printf("%2d ",N->data);
		}
		printf("\n");
	}
}
GraphNode* FindGraphNode(Graph* G,NodeType N)
{//根据N节点,寻找并返回结构体节点指针
	while(G->next!=NULL&&G->next->node->data!=N)
		G=G->next;
	return G->next->node;
}
void GraphDeapth(Graph* G,GraphNode* N,WeightType* Visited)
{//深度优先遍历Deeth First Traversal,过程函数
	GraphNode *Temp_N=FindGraphNode(G,N->data);
	if(Temp_N==NULL||Visited[Temp_N->data]) return;
	printf("%d ",Temp_N->data);
	Visited[Temp_N->data]=1;
	while(Temp_N->link!=NULL)
	{
		Temp_N=Temp_N->link;
		GraphDeapth(G,Temp_N,Visited);
	}
}
void GraphDeepthTraversal(Graph* G)
{//深度优先遍历operator调用函数
	int Visited[MAXNODE]={0};//访问点表示数组
	if(G->next==NULL) return;
	GraphDeapth(G,G->next->node,Visited);
}
void GraphBreadthTraversal(Graph* G)
{//宽度优先遍历Breadth First Traversal,使用循环队列实现
	int front=0,rear=0,Visited[MAXNODE]={0};
	GraphNode **GraphQueue,*N;//定义循环队列头
	if(G->next==NULL) return;
	GraphQueue=(GraphNode*)malloc(MAXNODE*sizeof(GraphNode));
	GraphQueue[rear++]=G->next->node;//初始第一个成员为G图中的第一个
	while(front!=rear)
	{
		N=FindGraphNode(G,GraphQueue[front++]->data);
		if(Visited[N->data]) continue;
		printf("%d ",N->data);
		Visited[N->data]=1;
		while(N->link!=NULL)
		{
			N=N->link;
			GraphQueue[rear++]=N;
		}
	}
}
WeightType GraphPrim(Graph* G)
{//prim算法实现的最小生成树,各边的weight直接在函数内部
 //输出,返回最小生成树的总权值
	Mgraph A;
	GraphNode* N;
	int n=0,Visited[MAXNODE]={0};
	WeightType M[MAXNODE]={MAXWEIGHT},STree=0;
	if(G->next==NULL) return;
	AdjGraphMatrix(G,A);
	N=G->next->node;
	Visited[N->data]=1;
	while(G->next!=NULL)G=G->next,n++;
	while(N->link!=NULL)N=N->link,M[N->data]=N->weight;
	while(1)
	{
		int i,k=0;
		for(i=1; i<=n; i++)
			if(!Visited[i]&&(M[k]>M[i]&&M[i])) k=i;
		if(!k) break;
		printf("%d ",M[k]);
		Visited[k]=1;
		STree+=M[k];
		for(i=1; i<=n; i++)
		   if(!Visited[i]&&(M[i]>A[k][i]||!M[i])&&A[k][i])
			   M[i]=A[k][i];
	}
	return STree;
}
附加文件Input.txt:
6 10
1 6 21
1 5 19
1 2 10
2 6 11
5 6 33
4 6 14
4 5 18
3 4 6
2 4 6
2 3 5



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值