c/c++ 图相关的函数(二维数组法)
c/c++ 图相关的函数(二维数组法)
- 遍历图
- 插入顶点
- 添加顶点间的线
- 删除顶点
- 删除顶点间的线
- 摧毁图
- 取得与v顶点有连线的第一个顶点
- 取得与v1顶点,v1顶点之后的v2顶点的之后的有连线的第一个顶点
graph_mtx.h
#ifndef __graph_mtx__
#define __graph_mtx__
#include <stdio.h>
#include <malloc.h>
#include <assert.h>
#include <memory.h>
#define Default_vertex_size 10
#define T char//dai biao ding dian de lei xing
typedef struct GraphMtx{
int MaxVertices;//zui da ding dian shu liang]
int NumVertices;//shi ji ding dian shu liang
int NumEdges;//bian de shu lian
T* VerticesList;//ding dian list
int** Edge;//bian de lian jie xin xi, bu shi 0 jiu shi 1
}GraphMtx;
//chu shi hua tu
void init_graph(GraphMtx* gm);
//打印二维数组
void show_graph(GraphMtx* gm);
//插入顶点
void insert_vertex(GraphMtx* gm, T v);
//添加顶点间的线
void insert_edge(GraphMtx* gm, T v1, T v2);
//删除顶点
void remove_vertex(GraphMtx* gm, T v);
//删除顶点间的线
void remove_edge(GraphMtx* gm, T v1, T v2);
//摧毁图
void destroy_graph(GraphMtx* gm);
//取得与v顶点有连线的第一个顶点
int getNeighbor(GraphMtx* gm, T v);
//取得与v1顶点,v1顶点之后的v2顶点的之后的有连线的第一个顶点
int getNextNeighbor(GraphMtx* gm, T v1, T v2);
#endif
graph_mtx.c
#include "graph_mtx.h"
void init_graph(GraphMtx* gm){
gm->MaxVertices = Default_vertex_size;
gm->NumEdges = gm->NumVertices = 0;
//kai pi ding dian de nei cun kong jian
gm->VerticesList = (T*)malloc(sizeof(T) * (gm->MaxVertices));
assert(NULL != gm->VerticesList);
//创建二维数组
//让一个int的二级指针,指向一个有8个int一级指针的数组
//开辟一个能存放gm->MaxVertices个int一级指针的内存空间
gm->Edge = (int**)malloc(sizeof(int*) * (gm->MaxVertices));
assert(NULL != gm->Edge);
//开辟gm->MaxVertices组,能存放gm->MaxVertices个int的内存空间
for(int i = 0; i < gm->MaxVertices; ++i){
gm->Edge[i] = (int*)malloc(sizeof(int) * gm->MaxVertices);
}
//初始化二维数组
//让每个顶点之间的边的关系都为不相连的
for(int i = 0; i < gm->MaxVertices; ++i){
for(int j = 0; j < gm->MaxVertices; ++j){
gm->Edge[i][j] = 0;
}
}
}
//打印二维数组
void show_graph(GraphMtx* gm){
printf(" ");
for(int i = 0; i < gm->NumVertices; ++i){
printf("%c ", gm->VerticesList[i]);
}
printf("\n");
for(int i = 0; i < gm->NumVertices; ++i){
//在行首,打印出顶点的名字
printf("%c:", gm->VerticesList[i]);
for(int j = 0; j < gm->NumVertices; ++j){
printf("%d ", gm->Edge[i][j]);
}
printf("\n");
}
printf("\n");
}
//插入顶点
void insert_vertex(GraphMtx* gm, T v){
//顶点空间已满,不能再插入顶点了
if(gm->NumVertices >= gm->MaxVertices){
return;
}
gm->VerticesList[gm->NumVertices++] = v;
}
int getVertexIndex(GraphMtx* gm, T v){
for(int i = 0; i < gm->NumVertices; ++i){
if(gm->VerticesList[i] == v)return i;
}
return -1;
}
//添加顶点间的线
void insert_edge(GraphMtx* gm, T v1, T v2){
if(v1 == v2)return;
//查找2个顶点的下标
int j = getVertexIndex(gm, v1);
int k = getVertexIndex(gm, v2);
//说明找到顶点了,并且点之间还没有线
if(j != -1 && k != -1 && gm->Edge[j][k] != 1){
//因为是无方向,所以更新2个值
gm->Edge[j][k] = gm->Edge[k][j] = 1;
//边数加一
gm->NumEdges++;
}
}
//删除顶点间的线
void remove_edge(GraphMtx* gm, T v1, T v2){
if(v1 == v2)return;
//查找2个顶点的下标
int j = getVertexIndex(gm, v1);
int k = getVertexIndex(gm, v2);
//说明找到顶点了,并且点之间还有线
if(j != -1 && k != -1 && gm->Edge[j][k] == 1){
//因为是无方向,所以更新2个值
gm->Edge[j][k] = gm->Edge[k][j] = 0;
//边数减一
gm->NumEdges--;
}
}
//删除顶点
void remove_vertex(GraphMtx* gm, T v){
int k = getVertexIndex(gm, v);
if(-1 == k)return;
//算出和要删除节点相关的边的数量,并减少。
for(int i = 0; i < gm->NumVertices; ++i){
if(gm->Edge[k][i] == 1){
gm->NumEdges--;
}
}
//如果要删除的顶点不是最后一个顶点
if(k != gm->NumVertices - 1){
//把每一列向左移动一列
for(int i = 0; i < gm->NumVertices; ++i){
//把后面内存里的内容移动到前面,并把最后一个元素设置成0
memmove(&(gm->Edge[i][k]), &(gm->Edge[i][k+1]), sizeof(int) * (gm->NumVertices-1-k));
gm->Edge[i][gm->NumVertices - 1] = 0;
}
//把每一行向上移动一行
for(int i = k; i < gm->NumVertices - 1; ++i){
memmove(gm->Edge[i], gm->Edge[i+1], sizeof(int) * (gm->NumVertices-1));
}
memset(gm->Edge[gm->NumVertices - 1], 0, sizeof(int) * (gm->NumVertices - 1));
//memmove(&(gm->Edge[k]), &(gm->Edge[k+1]), sizeof(int*) * (gm->NumVertices-1-k));
//memset(gm->Edge[gm->NumVertices - 1], 0, sizeof(int) * (gm->NumVertices - 1));
//删除点
memmove(&(gm->VerticesList[k]), &(gm->VerticesList[k+1]), sizeof(T) * (gm->NumVertices-1-k));
}
//如果要删除的顶点是最后一个顶点
else{
for(int i = 0; i < gm->NumVertices; ++i){
gm->Edge[i][k] = gm->Edge[k][i] = 0;
}
}
//节点数目减1
gm->NumVertices--;
}
//摧毁图
void destroy_graph(GraphMtx* gm){
free(gm->VerticesList);
for(int i = 0; i < gm->NumVertices; ++i){
free(gm->Edge[i]);
}
free(gm->Edge);
gm->Edge = NULL;
gm->VerticesList = NULL;
gm->MaxVertices = gm->NumVertices = gm->NumEdges = 0;
}
//取得与某顶点有连线的第一个顶点
int getNeighbor(GraphMtx* gm, T v){
int p = getVertexIndex(gm, v);
if(-1 == p)return -1;
for(int i = 0; i < gm->NumVertices; ++i){
if(gm->Edge[p][i] == 1)
return i;
}
return -1;
}
//取得与v1顶点,v1顶点之后的v2顶点的之后的有连线的第一个顶点
int getNextNeighbor(GraphMtx* gm, T v1, T v2){
if(v1 == v2)return -1;
int p1 = getVertexIndex(gm, v1);
int p2 = getVertexIndex(gm, v2);
if(p1 == -1 || p2 == -1)return -1;
for(int i = p2 + 1; i < gm->NumVertices; ++i){
if(gm->Edge[p1][i] == 1)
return i;
}
return -1;
}
graph_mtxmain.c
#include "graph_mtx.h"
int main(){
GraphMtx gm;
//初始化图
init_graph(&gm);
//插入顶点
insert_vertex(&gm, 'A');
insert_vertex(&gm, 'B');
insert_vertex(&gm, 'C');
insert_vertex(&gm, 'D');
insert_vertex(&gm, 'E');
//添加连线
insert_edge(&gm, 'A', 'B');
insert_edge(&gm, 'A', 'D');
insert_edge(&gm, 'B', 'C');
insert_edge(&gm, 'B', 'E');
insert_edge(&gm, 'C', 'E');
insert_edge(&gm, 'C', 'D');
//打印图
show_graph(&gm);
//删除连线
//remove_edge(&gm, 'A', 'B');
//打印图
//show_graph(&gm);
//删除顶点
remove_vertex(&gm, 'A');
//打印图
show_graph(&gm);
//添加顶点
insert_vertex(&gm, 'F');
//添加线
insert_edge(&gm, 'F', 'B');
insert_edge(&gm, 'F', 'C');
insert_edge(&gm, 'F', 'D');
//打印图
show_graph(&gm);
//删除顶点
remove_vertex(&gm, 'D');
//删除线
remove_edge(&gm, 'F', 'B');
//打印图
show_graph(&gm);
//取得与某顶点有连线的第一个顶点
int p = getNeighbor(&gm, 'F');
printf("%d\n", p);
//取得与v1顶点,v1顶点之后的v2顶点的之后的有连线的第一个顶点
int p1 = getNextNeighbor(&gm, 'E', 'B');
printf("%d\n", p1);
//摧毁图
destroy_graph(&gm);
}
c/c++ 图相关的函数(二维数组法)的更多相关文章
- c/c++ 图的创建(二维数组法)
c/c++ 图的创建(二维数组法) 图的概念 图由点和线组成 知道了图中有多少个点,和哪些点之间有线,就可以把一张图描绘出来 点之间的线,分有方向和无方向 创建图 创建图,实际就是创建出节点,和节点之 ...
- array_column() 函数[二维数组转为一维数组]
array_column() 函数 输出数组中某个键值的集合[二维数组转为一位数组] <?php // 表示由数据库返回的可能记录集的数组 $a = array( array( 'id' =&g ...
- Java基本语法-----java二维数组
由于word里的样式在csdn上调太麻烦了,所以我再次贴图了,后面二维数组那里是文字的,大家将就看吧. 二维数组常见的操作: 1.遍历二维数组 2.对二维数组求和 class Demo { // 定义 ...
- C语言中如何将二维数组作为函数的参数传递
今天写程序的时候要用到二维数组作参数传给一个函数,我发现将二维数组作参数进行传递还不是想象得那么简单里,但是最后我也解决了遇到的问题,所以这篇文章主要介绍如何处理二维数组当作参数传递的情况,希望大家不 ...
- php对二维数组进行相关操作(排序、转换、去空白等)
php对二维数组进行相关操作(排序.转换.去空白等) 投稿:lijiao 字体:[增加 减小] 类型:转载 时间:2015-11-04 这篇文章主要介绍了php对二维数组进行相关操作,包括php对 ...
- C语言学习笔记 (005) - 二维数组作为函数参数传递剖析
前言 很多文章不外乎告诉你下面这几种标准的形式,你如果按照它们来用,准没错: //对于一个2行13列int元素的二维数组 //函数f的形参形式 f(int daytab[2][13]) {...} / ...
- C语言二维数组作为函数参数
设有整型二维数组a[3][4]如下:0 1 2 34 5 6 78 9 10 11 它的定义为: int a[3][4]={{0,1,2,3},{4,5,6,7} ...
- SDUT OJ 图练习-BFS-从起点到目标点的最短步数 (vector二维数组模拟邻接表+bfs , *【模板】 )
图练习-BFS-从起点到目标点的最短步数 Time Limit: 1000ms Memory limit: 65536K 有疑问?点这里^_^ 题目描述 在古老的魔兽传说中,有两个军团,一个叫天 ...
- PHP代码篇(二)-- array_column函数将二维数组格式化成固定格式的一维数组,及优化查询方法
小白因为经常用到多表查询,比如获取一个会员领取的卡卷list,里面当然包含了1“会员优惠券记录表t_coupon_members”主表,然后2“门店优惠券表t_coupon”,和3“门店信息表t_sh ...
随机推荐
- Java并发编程-AbstractQueuedSynchronizer源码分析
简介 提供了一个基于FIFO队列,可以用于构建锁或者其他相关同步装置的基础框架.该同步器(以下简称同步器)利用了一个int来表示状态,期望它能够成为实现大部分同步需求的基础.使用的方法是继承,子类通过 ...
- PHP错误报告级别
error_reporting = E_ALL & ~E_NOTICE ; 错误报告级别是位字段的叠加,推荐使用 E_ALL | E_STRICT ; 1 E_ERROR 致命的运行时错误 ; ...
- spring学习(一) ———— IOC讲解
spring基本就两个核心内容,IOC和AOP.把这两个学会了基本上就会用了. --WH 一.什么是IOC? IOC:控制反转,通俗点讲,将对象的创建权交给spring,我们需要new对象,则由spr ...
- Linux文件权限与属性详解 之 chattr & lsattr
Linux文件权限与属性详解 之 一般权限 Linux文件权限与属性详解 之 ACL Linux文件权限与属性详解 之 SUID.SGID & SBIT Linux文件权限与属性详解 之 ch ...
- 利用aiohttp制作异步爬虫
asyncio可以实现单线程并发IO操作,是Python中常用的异步处理模块.关于asyncio模块的介绍,笔者会在后续的文章中加以介绍,本文将会讲述一个基于asyncio实现的HTTP框架--a ...
- 【微服务No.4】 API网关组件Ocelot+Consul
介绍: Ocelot是一个.NET API网关.该项目针对的是使用.NET运行微服务/面向服务架构的人员,他们需要一个统一的入口进入他们的系统.然而,它可以处理任何说HTTP并在ASP.NET Cor ...
- 正则表达式之 \b
引用网上一段话: \b 是正则表达式规定的一个特殊代码(好吧,某些人叫它元字符,metacharacter),代表着单词的开头或结尾,也就是单词的分界处.虽然通常英文的单词是由空格,标点符号或者换行来 ...
- Spring使用ajax异步上传文件
单文件上传 <!-- 创建文件选择框 --> 文件上传 :<input type="file" id="file" name="fi ...
- JS隐藏号码中间4位
function resetPhone(phone) { var str = String(phone) var len = str.length; var prev,next; if (len &g ...
- 你还在等着用户反馈BUG?
译者按: 等待用户反馈BUG,一切都晚了!实时监控线上应用才是王道. 原文: Why relying on your users to report errors is the dumbest thi ...