MGraph图(代码、分析、汇编)

目录:

    • 代码:
    • 分析:
    • 汇编:

MGrapth图表示有邻接矩阵的方式构成的图结构。
邻接矩阵用两个数组保存数据,一个一维数组存储图中的顶点信息,一个二维数组存储图中边或弧的信息。

无向图中的二维数组是个对称矩阵
1.0表示无边,1表示有边
2.顶点的度是行内数组之和
3.求取顶点邻接占,将行内元素遍历下

有向图的邻接矩阵(二维数组),
有分入度和出度,行内之和是出度,列内之和是入度

代码:

LinkQueue.h

#ifndef _LINKQUEUE_H_
#define _LINKQUEUE_H_typedef void LinkQueue;LinkQueue* LinkQueue_Create();void LinkQueue_Destroy(LinkQueue* queue);void LinkQueue_Clear(LinkQueue* queue);int LinkQueue_Append(LinkQueue* queue, void* item);void* LinkQueue_Retrieve(LinkQueue* queue);void* LinkQueue_Header(LinkQueue* queue);int LinkQueue_Length(LinkQueue* queue);#endif

LinkQueue.c

#include <malloc.h>
#include <stdio.h>
#include "LinkQueue.h"typedef struct _tag_LinkQueueNode TLinkQueueNode;//定义队列节点类型
struct _tag_LinkQueueNode
{TLinkQueueNode* next;void* item;
};typedef struct _tag_LinkQueue//定义队列类型
{TLinkQueueNode* front;TLinkQueueNode* rear;int length;
} TLinkQueue;LinkQueue* LinkQueue_Create() //定义创建队列函数
{TLinkQueue* ret = (TLinkQueue*)malloc(sizeof(TLinkQueue));if( ret != NULL ){ret->front = NULL;ret->rear = NULL;ret->length = 0;}return ret;
}void LinkQueue_Destroy(LinkQueue* queue) // 定义销毁队列函数
{LinkQueue_Clear(queue);free(queue);
}void LinkQueue_Clear(LinkQueue* queue) // 定义清空队列函数
{while( LinkQueue_Length(queue) > 0 ){LinkQueue_Retrieve(queue);}
}int LinkQueue_Append(LinkQueue* queue, void* item) // 定义进队列函数
{TLinkQueue* sQueue = (TLinkQueue*)queue;//取得队列TLinkQueueNode* node = (TLinkQueueNode*)malloc(sizeof(TLinkQueueNode));//新建节点int ret = (sQueue != NULL ) && (item != NULL) && (node != NULL);if( ret ){node->item = item;//给新建节点保存的数据赋值if( sQueue->length > 0 )//如果长度大于0{sQueue->rear->next = node;//将队列最后一个节点的next指向新建节点sQueue->rear = node;//设新建节点为最后节点 node->next = NULL;}else//否则 表示是第一个节点{sQueue->front = node;//设第一个节点为新建节点sQueue->rear = node;//设最后一个节点为新建节点node->next = NULL;}sQueue->length++;}if( !ret )//条件不成功{free(node);//释放新建节点}return ret;
}void* LinkQueue_Retrieve(LinkQueue* queue) // 定义出队列函数
{TLinkQueue* sQueue = (TLinkQueue*)queue;//取得队列TLinkQueueNode* node = NULL;void* ret = NULL;if( (sQueue != NULL) && (sQueue->length > 0) ){node = sQueue->front;//取得出队列节点sQueue->front = node->next;//将队列第一个节点设为取出节点的下一个ret = node->item;//取得节点保存的数据free(node);//释放出队列节点sQueue->length--;if( sQueue->length == 0 )//如果是最后一个节点{sQueue->front = NULL;//将第一个节点指针清空sQueue->rear = NULL;//将最后一个节点指针清空}}return ret;
}void* LinkQueue_Header(LinkQueue* queue) // 定义获取第一个节点数据函数
{TLinkQueue* sQueue = (TLinkQueue*)queue;void* ret = NULL;if( (sQueue != NULL) && (sQueue->length > 0) ){ret = sQueue->front->item;}return ret;
}int LinkQueue_Length(LinkQueue* queue) // 定义获取队列长度函数
{TLinkQueue* sQueue = (TLinkQueue*)queue;int ret = -1;if( sQueue != NULL ){ret = sQueue->length;}return ret;
}

MGraph.h


#ifndef _MGRAPH_H_
#define _MGRAPH_H_typedef void MGraph;//定义图类型
typedef void MVertex;//定义顶点类型
typedef void (MGraph_Printf)(MVertex*);//定义有一个顶点类型指针参数并且无返回值的函数类型MGraph* MGraph_Create(MVertex** v, int n);//声明创建图函数void MGraph_Destroy(MGraph* graph);//声明销毁图函数void MGraph_Clear(MGraph* graph);//声明清空图函数int MGraph_AddEdge(MGraph* graph, int v1, int v2, int w);//声明添加边函数int MGraph_RemoveEdge(MGraph* graph, int v1, int v2);//声明移除边函数int MGraph_GetEdge(MGraph* graph, int v1, int v2);//声明获取边函数int MGraph_TD(MGraph* graph, int v);//声明以一个数作为行与列检测不等于0的值的数量函数int MGraph_VertexCount(MGraph* graph);//声明获取顶点数量函数int MGraph_EdgeCount(MGraph* graph);//声明获取边数量函数void MGraph_DFS(MGraph* graph, int v, MGraph_Printf* pFunc);//声明void MGraph_BFS(MGraph* graph, int v, MGraph_Printf* pFunc);//声明void MGraph_Display(MGraph* graph, MGraph_Printf* pFunc);//声明#endif

MGraph.c

#include <malloc.h>
#include <stdio.h>
#include "MGraph.h"
#include "LinkQueue.h"typedef struct _tag_MGraph//定义实际使用图类型
{int count;//数量MVertex** v;//指向顶点指针的指针变量int** matrix;//指向整型指针的指针变量
} TMGraph;//递归遍历矩阵函数 
static void recursive_dfs(TMGraph* graph, int v, int visited[], MGraph_Printf* pFunc)
{int i = 0;pFunc(graph->v[v]);visited[v] = 1;printf(", ");for(i=0; i<graph->count; i++){if( (graph->matrix[v][i] != 0) && !visited[i] ){recursive_dfs(graph, i, visited, pFunc);}}
}
//用队列遍历矩阵
static void bfs(TMGraph* graph, int v, int visited[], MGraph_Printf* pFunc)
{LinkQueue* queue = LinkQueue_Create();//创建队列if( queue != NULL )//创建成功{LinkQueue_Append(queue, graph->v + v);//将顶点信息存进队列visited[v] = 1;//将对应行记录为已查看while( LinkQueue_Length(queue) > 0 ){int i = 0;v = (MVertex**)LinkQueue_Retrieve(queue) - graph->v;pFunc(graph->v[v]);printf(", ");for(i=0; i<graph->count; i++){if( (graph->matrix[v][i] != 0) && !visited[i] ){LinkQueue_Append(queue, graph->v + i);visited[i] = 1;}}}}LinkQueue_Destroy(queue);
}MGraph* MGraph_Create(MVertex** v, int n)  // 定义创建图函数
{TMGraph* ret = NULL;if( (v != NULL ) && (n > 0) ){ret = (TMGraph*)malloc(sizeof(TMGraph));//新建图if( ret != NULL )//新建成功{int* p = NULL;ret->count = n;//设置数量ret->v = (MVertex**)malloc(sizeof(MVertex*) * n);//创建n个顶点指针类型的空间,v指向第一个ret->matrix = (int**)malloc(sizeof(int*) * n);//创建n个整型指针类型的空间,matrix指向第一个p = (int*)calloc(n * n, sizeof(int));//创建n*n个int 类型空间,p指向第一个if( (ret->v != NULL) && (ret->matrix != NULL) && (p != NULL) )//全部创建成功{int i = 0;for(i=0; i<n; i++){ret->v[i] = v[i];//将传来的顶点信息给新建的图中的顶点赋值ret->matrix[i] = p + i * n;//将新建图中的矩阵指向p创建的地址(0,6,12,18,24,30)}}else//如果创建失败,将申请的空间全部释放{free(p);free(ret->matrix);free(ret->v);free(ret);ret = NULL;//返回空}}}return ret;
}void MGraph_Destroy(MGraph* graph) //定义销毁图函数
{TMGraph* tGraph = (TMGraph*)graph;//取得图if( tGraph != NULL )//图不为空,将空间全部释放{free(tGraph->v);free(tGraph->matrix[0]);free(tGraph->matrix);free(tGraph);}
}void MGraph_Clear(MGraph* graph) // 定义清空图函数
{TMGraph* tGraph = (TMGraph*)graph;//取得图if( tGraph != NULL )//图不为空{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;//将矩阵数值全设0}}}
}int MGraph_AddEdge(MGraph* graph, int v1, int v2, int w) // 定义添加边函数
{TMGraph* tGraph = (TMGraph*)graph;//取得图int ret = (tGraph != NULL);//判断是否为空ret = ret && (0 <= v1) && (v1 < tGraph->count);//判断行数是否正常ret = ret && (0 <= v2) && (v2 < tGraph->count);//判断列数是否正常ret = ret && (0 <= w);//判断添加的值是否大于等于0if( 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( ret != 0 )//图不为空{((TMGraph*)graph)->matrix[v1][v2] = 0;//将对应行列值重置0}return ret;//返回移除值
}int MGraph_GetEdge(MGraph* graph, int v1, int v2) // 定义获取边函数
{TMGraph* tGraph = (TMGraph*)graph;//获取图int condition = (tGraph != NULL);//判断图不为空int ret = 0;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) // 定义以一个数作为行与列检测不等于0的值的数量函数
{TMGraph* tGraph = (TMGraph*)graph;//取得图int condition = (tGraph != NULL);//判断图不为空int ret = 0;condition = condition && (0 <= v) && (v < tGraph->count);//判断v是否在范围内if( condition ){int i = 0;for(i=0; i<tGraph->count; i++)//如果一个位置的数值有效在行列交叉处会增加两次{if( tGraph->matrix[v][i] != 0 )//如果以v作为行数将对应行列的值不等于0{ret++;//数量增加}if( tGraph->matrix[i][v] != 0 )//如果以v作为列数将对应行列的值不等于0{ret++;//数量增加}}}return ret;//返回总数
}int MGraph_VertexCount(MGraph* graph) //定义获取顶点数量
{TMGraph* tGraph = (TMGraph*)graph;int ret = 0;if( tGraph != NULL ){ret = tGraph->count;//取得数量}return ret;
}int MGraph_EdgeCount(MGraph* graph) //定义获取边数函数
{TMGraph* tGraph = (TMGraph*)graph;int ret = 0;if( tGraph != NULL ){int i = 0;int j = 0;for(i=0; i<tGraph->count; i++){for(j=0; j<tGraph->count; j++){if( tGraph->matrix[i][j] != 0 )//如果不等于0{ret++;//数量增加}}}}return ret;//返回总数
}//从v行开始遍历矩阵,visited记录查看过的行。输出v行顶点信息,从v行i列开始,只要i列不等于0并且用i值作为行检测
//i值行没有看过。就跳到i行查看,此时i作为新v行又从v行i列开始检测。循环检测完矩阵每个元素
void MGraph_DFS(MGraph* graph, int v, MGraph_Printf* pFunc)
{TMGraph* tGraph = (TMGraph*)graph;//取得图int* visited = NULL;int condition = (tGraph != NULL);//图不为空condition = condition && (0 <= v) && (v < tGraph->count);//v是否在范围内condition = condition && (pFunc != NULL);//函数指针不为空//判断新申请的count个int类型是否成功condition = condition && ((visited = (int*)calloc(tGraph->count, sizeof(int))) != NULL);if( condition ){int i = 0;recursive_dfs(tGraph, v, visited, pFunc);//调用递归检测for(i=0; i<tGraph->count; i++)//如果还有行没遍历的,再从该行开始遍历{if( !visited[i] ){recursive_dfs(tGraph, i, visited, pFunc);}}printf("\n");}free(visited);//释放用于记录查看行状态的空间
}
//从v行开始遍历,visited记录查看过的行
//将v行对应顶点信息存进队列,表示从该行开始遍历,将v行记录为已查看,输出v行顶点信息
//然后从出队列的行开始遍历,如果v行i列不等于0并且将i作为行检测是否查看过
//如果没有将i作为要遍历的行进队列,当前v行检测完,再从队列取元素循环同样操作
void MGraph_BFS(MGraph* graph, int v, MGraph_Printf* pFunc)
{TMGraph* tGraph = (TMGraph*)graph;//取得图int* visited = NULL;int condition = (tGraph != NULL);condition = condition && (0 <= v) && (v < tGraph->count);condition = condition && (pFunc != NULL);condition = condition && ((visited = (int*)calloc(tGraph->count, sizeof(int))) != NULL);if( condition ){int i = 0;bfs(tGraph, v, visited, pFunc);for(i=0; i<tGraph->count; i++)//如果还有行没遍历的,再从该行开始遍历{if( !visited[i] ){bfs(tGraph, i, visited, pFunc);}}printf("\n");}free(visited);//释放用于记录查看行状态的空间
}
//将矩阵中不为0的数值,将其坐标与数值输出
void MGraph_Display(MGraph* graph, MGraph_Printf* pFunc) // O(n*n)
{TMGraph* tGraph = (TMGraph*)graph;//取得图if( (tGraph != NULL) && (pFunc != NULL) )//图与函数指针不为空{int i = 0;int j = 0;for(i=0; i<tGraph->count; i++)//输出所有顶点信息{printf("%d:", i);pFunc(tGraph->v[i]);printf(" ");}printf("\n");for(i=0; i<tGraph->count; i++){for(j=0; j<tGraph->count; j++){if( tGraph->matrix[i][j] != 0 )//将矩阵中不等于0的坐标与数据输出{printf("<");pFunc(tGraph->v[i]);//输出行printf(", ");pFunc(tGraph->v[j]);//输出列printf(", %d", tGraph->matrix[i][j]);//输出对应数据printf(">");printf(" ");}}}printf("\n");}
}

main.c

#include <stdio.h>
#include <stdlib.h>
#include "MGraph.h"void print_data(MVertex* v)
{printf("%s", (char*)v);
}int main(int argc, char *argv[])
{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);MGraph_DFS(graph, 0, print_data);//输出:A,B,E,C,F,DMGraph_BFS(graph, 0, print_data);//输出:A,B,C,D,E,FMGraph_Destroy(graph);getchar();return 0;
}

分析:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

汇编:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/379151.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java: 程序包lombok不存在_Java开发神器:Lombok 学习指南

点击上方“Java知音”&#xff0c;选择“置顶公众号”技术文章第一时间送达&#xff01;作者&#xff1a;semlinkerwww.segmentfault.com/a/1190000020864572一、Lombok 简介Lombok 是一款 Java 开发插件&#xff0c;使得 Java 开发者可以通过其定义的一些注解来消除业务工程中…

Python---编程检查并判断密码字符串的安全强度

编程检查并判断密码字符串的安全强度 passwordinput("请输入你的密码&#xff1a;") plist(password) x0 for i in p:if i " ":x1 if x1:print("密码格式不对")#密码中不能包含空格 elif password.isdigit()True or password.isalpha()True:#全…

CFUpdate上传控件的使用

一同事找的这个控件&#xff0c;觉得挺不错的&#xff0c;到官方(http://www.access2008.cn/)下载源码后稍加修改 html页面代码&#xff1a; <html xmlns"http://www.w3.org/1999/xhtml" xml:lang"zh_cn" lang"zh_cn"> <head> <m…

observable_Java Observable addObserver()方法与示例

observable可观察的类addObserver()方法 (Observable Class addObserver() method) addObserver() method is available in java.util package. addObserver()方法在java.util包中可用。 addObserver() method is used to insert the given observer (obs) to the bundles of o…

AAC ADTS格式分析

AAC ADTS格式分析&#xff1a; 没有详细的参数说明&#xff0c;只有格式分析。可以查询文档查看详细参数说明。 ADTS的全称是Audio Data Transport Stream。是AAC音频的传输流格 式。AAC音频格式在MPEG-2&#xff08;ISO-13318-7 2003&#xff09;中有定义。AAC后来 又被采用到…

新知道的几个东西

nginx&#xff08;发音同engine x&#xff09;是一款由俄罗斯程序设计师Igor Sysoev所开发轻量级的网页服务器、反向代理服务器以及电子邮件&#xff08;IMAP/POP3&#xff09;代理服务器。起初是供俄国大型的入口网站及搜寻引擎Rambler&#xff08;俄文&#xff1a;Рамбл…

台达plc控制伺服电机编程实例_PLC控制伺服电机:控制脉冲的相关计算

伺服电机PLC通过脉冲的方式控制伺服电机时&#xff0c;其输出脉冲与伺服电机的配置应具有一定的对应关系。如&#xff0c;PLC输出多少个脉冲电机旋转一圈&#xff1f;电机旋转一圈移动的距离(或角度)是多少&#xff1f;这里我们以某伺服电机为例进行举例说明&#xff1a;完成对…

linux rm命令详解

用户可以用rm命令删除不需要的文件。该命令的功能为删除一个目录中的一个或多个文件或目录&#xff0c;它也可以将某个目录及其下的所有文件及子目录均删除。对于链接文件&#xff0c;只是断开了链接&#xff0c;原文件保持不变。 rm命令的一般形式为&#xff1a;rm [选项] 文件…

rotateright_Java Long类rotateRight()方法的示例

rotateright长类rotateRight()方法 (Long class rotateRight() method) rotateRight() method is available in java.lang package. rotationRight()方法在java.lang包中可用。 rotateRight() method is used to returns the value generated by rotating the binary 2’s comp…

实验四 Windows程序设计

1&#xff0c;创建Windows窗体应用程序&#xff0c;实现用户登录功能&#xff0c;当输入正确与错误时均给出相应的提示信息&#xff0c;规定用户输入错误次数不能超过3次。&#xff08;源代码运行界面&#xff09; 这里的口令有个小常识&#xff0c;就是显示*&#xff0c;在口令…

最小连通-(代码、分析、汇编)

目录&#xff1a;介绍&#xff1a;代码&#xff1a;分析&#xff1a;汇编&#xff1a;介绍&#xff1a; 一个有 n 个结点的连通图的生成树是原图的极小连通子图&#xff0c;且包含原图中的所有 n 个结点&#xff0c; 并且有保持图连通的最少的边。 最小生成树可以用kruskal&am…

toad dba for oracle 10.5

http://worlddownloads.quest.com.edgesuite.net/Repository/support.quest.com/Toad%20for%20Oracle/10.5/Software/Toad%20DBA%20Suite%20for%20Oracle%2010.5%20Commercial.exe转载于:https://www.cnblogs.com/devbar/archive/2010/07/01/1768986.html

c++ 怎样连接两个链表_LeetCode | 链表的入口,一文帮你搞定“环形链表”(python版,最简单解析)...

链表节点的定义链表作为一种数据结构&#xff0c;由链表节点互相连接构成。链表节点包含自身的数据和一个指向下一节点的指针。""" Definition of ListNode """ class ListNode(object):def __init__(self, val, nextNone):self.val valself.ne…

QI实例-改变空间参考

学习AE一段时间了&#xff0c;总是对QI不是很理解&#xff0c;今天一晚上写了QI实例&#xff0c;尝试理解下。 首先想到的是→改变空间参考→alter、SpatialReference→alterSpatialReference&#xff0c;输入到帮助文档里。  查看是IGeoDatasetSchemaEdit接口的方法&#xf…

VeryCD 的资料库

呵呵&#xff0c;刚才看了下VeryCD的资料库&#xff0c;恍然间才明白为什么VeryCD以前花大量时间和精力开发电驴&#xff0c;又为什么不久前突然取消了KAD网络和ED2k网络的搜索功能。呵呵&#xff0c;天下没有免费的午餐哈&#xff0c;VeryCD先用电驴软件聚集客户群&#xff08…

Java IdentityHashMap keySet()方法及示例

IdentityHashMap类keySet()方法 (IdentityHashMap Class keySet() method) keySet() method is available in java.util package. keySet()方法在java.util包中可用。 keySet() method is used to get a set of all the existing keys in this IdenityHashMap to be viewed in …

C#省市二级联动(王者荣耀挑选英雄为例)

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms;namespace beyond_联动_ {public partial clas…

二叉排序树(Binary Sort Tree) 又称为二叉查找树(Binary Search Tree) - (代码、分析)

目录&#xff1a;代码&#xff1a;分析&#xff1a;代码&#xff1a; BSTree.h #ifndef _BSTREE_H_ #define _BSTREE_H_typedef void BSTree;//定义二叉树类型 typedef void BSKey;//定义节点的键值类型&#xff08;用于节点排序&#xff09;typedef struct _tag_BSTreeNode …

springboot tomcat默认线程数_记一次JAVA线程池的错误用法

最近项目一个项目要结项了&#xff0c;但客户要求 TPS 能达到上千&#xff0c;而用我写的代码再怎么弄成只能达到 30 的 TPS&#xff0c;然后我又将代码中能缓存的都缓存了&#xff0c;能拆分的也都拆分了&#xff0c;拆分时用的线程池来实现的&#xff1b;其实现的代码主要为…

引以为鉴-ARM开发板连线注意事项

前些日子把实验室的三台机子放到一个工位上&#xff0c;非常拥挤&#xff0c;做实验也很不方便。因此&#xff0c;想把ARM开发板的环境重新搭建到自己的电脑上。说完就做&#xff0c;上午就开始忙活起来。把开发板上的USB线、串口线、JTAT接口、还有电源线一一插好。接着就开始…