一步一步学数据结构之n--n(图--邻接矩阵法实现)

 

今天我和大家一起来学习图,首先说下图的定义:

 

 

图分为有向图和无向图

 

在这里,来一起了解下度和权的概念:

 

 

这里介绍图的常用操作:

 

l 创建图

l 销毁图

l 清空图的边

l 在图中两个顶点连接起来,并带权

l 删除两个顶点的边,把权返回

l 返回图中某两个顶点之间边的权值

l 返回图中某个顶点的度

l 返回图中顶点数

l 返回图中的边数

l 输出图

 

 

代码总分为三个文件:

       MGraph.h , MGraph.c , Main.c  

 

整体结构图为:

    

 

 

简单说下邻接矩阵:

 

        这里就不再详细介绍图的一些操作细节,因为是用邻接矩阵实现的,也就是用一个二维数组实现的,所以大部分操作都类似于二维数组操作,只要细细阅读代码就会理解的。

 

 

 

OK! 上代码:

 

MGraph.h , 

#ifndef _MGRAPH_H_
#define _MGRAPH_H_

typedef void MGraph;
typedef void MVertex;
typedef void (MGraph_Printf)(MVertex*);

/* 创建并返回有n个顶点的图 */
MGraph* MGraph_Create(MVertex** v, int n);

/* 销毁graph所指向的图 */
void MGraph_Destory(MGraph* graph);

/* 将graph所指图的边集合清空 */
void MGraph_Clear(MGraph* graph);

/* 在graph所指图中的v1和v2之间加上边,且边的权为w */
int MGraph_AddEdge(MGraph* graph, int v1, int v2, int w);

/* 将graph所指图中v1和v2之间的边删除,返回权值 */
int MGraph_RemoveEdge(MGraph* graph, int v1, int v2);

/* 将graph所指图中v1和v2之间的边的权值返回 */
int MGraph_GetEdge(MGraph* graph, int v1, int v2);

/* 将graph所指图中v顶点的度数 */
int MGraph_TD(MGraph* graph, int v);

/* 将graph所指图中的顶点数返回 */
int MGraph_VertexCount(MGraph* graph);

/* 将graph所指图中的边数返回 */
int MGraph_EdgeCount(MGraph* graph);

/* 将graph所指图输出 */
void MGraph_Display(MGraph* graph, MGraph_Printf* pFunc);

#endif


 

MGraph.c , 

#include <malloc.h>
#include <stdio.h>
#include "MGraph.h"

typedef struct _tag_MGraph//定义图 
{
	int count;
	MVertex** v;
	int** matrix;
}TMGraph;

MGraph* MGraph_Create(MVertex** v, int n)
{
	TMGraph* ret = NULL;
	
	if((NULL!=v) && (0<n))
	{
		ret = (TMGraph*)malloc(sizeof(TMGraph));
		
		if(NULL != ret)
		{
			int* p = NULL;
			
			ret->count = n;
			//通过二级指针动态申请一维指针数组 
			ret->v = (MVertex**)malloc(sizeof(MVertex*) * n);
			ret->matrix = (int**)malloc(sizeof(int*) * n);
			
			//通过一级指针申请数据空间
			//calloc函数把申请的数据空间全清0 
			p = (int*)calloc(n * n, sizeof(int));
			
			if((NULL!=ret->v) && (NULL!=ret->matrix) && (NULL!=p))
			{
				int i = 0;
				
				for(i=0; i<n; i++)
				{//把指针数组和数据空间连接起来 
					ret->v[i] = v[i];
					ret->matrix[i] = p + i* n;
				}	
			}
			else
			{
				free(ret->v);
				free(ret->matrix);
				free(p);
				free(ret);
				
				ret = NULL;	
			}	
		}
	}
	
	return ret;
}

void MGraph_Destory(MGraph* graph)
{
	TMGraph* tGraph = (TMGraph*)graph;
	
	if(NULL != tGraph)
	{
		free(tGraph->v);
		//销毁通过一级指针申请的数据空间 
		free(tGraph->matrix[0]);
		//销毁通过二级指针申请的一维指针空间 
		free(tGraph->matrix);
		free(tGraph);
	}
}

void MGraph_Clear(MGraph* graph)
{
	TMGraph* tGraph = (TMGraph*)graph;
	
	if(NULL != tGraph)
	{
		int i = 0;
		int j = 0;
		
		for(i=0; i<tGraph->count; i++)
		{
			for(j=0; j<tGraph->count; j++)
			{//清楚边的信息  保存顶点的信息 
				tGraph->matrix[i][j] = 0;
			}
		}
	}
}

int MGraph_AddEdge(MGraph* graph, int v1, int v2, int w)
{
	TMGraph* tGraph = (TMGraph*)graph;
	
	int ret = (NULL!=tGraph);
	ret = ret && (0 <= v1) && (v1 < tGraph->count);
	ret = ret && (0 <= v2) && (v2 < tGraph->count);
	ret = ret && (0 <= w);
	
	if(ret)
	{//增加连线也就是给描述边的数组相应位置赋值 
		tGraph->matrix[v1][v2] = w;
	}
	
	return ret;
}

int MGraph_RemoveEdge(MGraph* graph, int v1, int v2)
{
	int ret = MGraph_GetEdge(graph, v1, v2);
	
	if(0 != ret)
	{//相应的,删除边的信息也就是给相应位置赋空 
		((TMGraph*)graph)->matrix[v1][v2] = 0;
	}
	
	return ret;
}

int MGraph_GetEdge(MGraph* graph, int v1, int v2)
{
	TMGraph* tGraph = (TMGraph*)graph;
	
	int ret = 0;
	
	int condition = (NULL != tGraph);
	condition = condition && (0 <= v1) && (v1 < tGraph->count);
	condition = condition && (0 <= v2) && (v2 < tGraph->count);
	
	if(condition)
	{//从二维数组相应位置取权值 
		ret = tGraph->matrix[v1][v2];
	}
	
	return ret;
}

int MGraph_TD(MGraph* graph, int v)
{
	TMGraph* tGraph = (TMGraph*)graph;
	
	int ret = 0;
	
	if((NULL != tGraph) && (0 <= v) && (v < tGraph->count))
	{
		int i = 0;
		int j = 0;
		
		for(i=0; i<tGraph->count; i++)
		{//直接返回V所在的行和列顶点的总数也就是  出度+入度 
			if(0 != tGraph->matrix[i][v])
			{
				ret++;
			}
			if(0 != tGraph->matrix[v][i])
			{
				ret++;
			}
		}
	}
	
	return ret;
}

int MGraph_VertexCount(MGraph* graph)
{
	TMGraph* tGraph = (TMGraph*)graph;
	
	int ret = 0;
	
	if(NULL != tGraph)
	{
		ret = tGraph->count;
	}
	
	return ret;
}

int MGraph_EdgeCount(MGraph* graph)
{
	TMGraph* tGraph = (TMGraph*)graph;
	
	int ret = 0;
	
	if(NULL != tGraph)
	{
		int i = 0;
		int j = 0;
		
		for(i=0; i<tGraph->count; i++)
		{
			for(j=0; j<tGraph->count; j++)
			{//返回总边数,也就是判断描述边信息的数组的非0值个数 
				if(0 != tGraph->matrix[i][j])
				{
					ret++;
				}
			}
		}
	}
	
	return ret;
}

void MGraph_Display(MGraph* graph, MGraph_Printf* pFunc)
{
	TMGraph* tGraph = (TMGraph*)graph;
	
	if((NULL != tGraph) && (NULL != pFunc))
	{
		int i = 0;
		int j = 0;
		
		for(i=0; i<tGraph->count; i++)
		{//输出顶点信息 
			printf("%d: ", i+1);
			pFunc(tGraph->v[i]);
			printf(" \n");
		}
		printf("\n");
		
		for(i=0; i<tGraph->count; i++)
		{
			for(j=0; j<tGraph->count; j++)
			{
				if(0 != tGraph->matrix[i][j])
				{//输出边信息 
					printf("<");
					pFunc(tGraph->v[i]);
					printf(", ");
					pFunc(tGraph->v[j]);
					printf(":  %d", tGraph->matrix[i][j]);
					printf(" > \n");
				}
			}
		}
		printf("\n");
	}
}


 

Main.c  

#include <stdio.h>
#include "MGraph.h"

void print_data(MVertex* v)
{
	if(NULL != v)
	{
		printf("%s", (char*)v);
	}
}

int main(void)
{
	MVertex* v[] = {"A", "B", "C", "D", "E", "F"};
	
	MGraph* graph = MGraph_Create(v, 6);
	
	MGraph_AddEdge(graph, 0, 1, 1);
	MGraph_AddEdge(graph, 0, 2, 1);
	MGraph_AddEdge(graph, 0, 3, 1);
	MGraph_AddEdge(graph, 1, 5, 1);
	MGraph_AddEdge(graph, 1, 4, 1);
	MGraph_AddEdge(graph, 2, 1, 1);
	MGraph_AddEdge(graph, 3, 4, 1);
	MGraph_AddEdge(graph, 4, 2, 1);
	
	MGraph_Display(graph, print_data);
	
	printf("2 TD  : %d\n", MGraph_TD(graph, 2));
	printf("Vertex: %d\n", MGraph_VertexCount(graph));
	printf("Edge  : %d\n", MGraph_EdgeCount(graph));
	
	MGraph_Destory(graph);
	
	return 0;
}


 

 

 

 

转载于:https://www.cnblogs.com/bbsno1/p/3260679.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值