zoukankan      html  css  js  c++  java
  • 一步一步学数据结构之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(" 
    ");
    		}
    		printf("
    ");
    		
    		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(" > 
    ");
    				}
    			}
    		}
    		printf("
    ");
    	}
    }
    


     

    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
    ", MGraph_TD(graph, 2));
    	printf("Vertex: %d
    ", MGraph_VertexCount(graph));
    	printf("Edge  : %d
    ", MGraph_EdgeCount(graph));
    	
    	MGraph_Destory(graph);
    	
    	return 0;
    }


     

  • 相关阅读:
    Qt Creator 5.0 发布
    Qt编写可视化大屏电子看板系统19-横向柱状图
    Qt开发经验小技巧166-170
    Qt编写安防视频监控系统62-子模块6预置位
    Qt编写可视化大屏电子看板系统18-柱状分组图
    Qt编写安防视频监控系统61-子模块5设备控制
    如果对golang的gin框架中的handler做单元测试
    samba
    内存溢出
    动态规划面试题
  • 原文地址:https://www.cnblogs.com/bbsno1/p/3260679.html
Copyright © 2011-2022 走看看