数据结构学习记录——如何建立图(邻接矩阵、邻接表-图节点的结构、创建并初始化、插入变、完整图的建立)

news2024/11/25 1:06:14

目录

邻接矩阵

图节点的结构

创建并初始化

插入边

完整的图的建立 

邻接表

图节点的结构

创建并初始化

插入边 

完整的图的建立 


邻接矩阵

图节点的结构

G[ i ] [ j ] = \left\{\begin{matrix} 1, &\textbf{if}<v_{i},v_{j}>\textbf{is an edge in G} & \\ 0, &\textbf{else} & \end{matrix}\right.

#include <stdio.h>
#include <stdlib.h>

#define MaxVertexNum 100 // 最大顶点数

typedef int WeightType; // 边的权重类型

typedef struct GNode* PtrToGNode;

struct GNode 
{
	int Nv; // 顶点数
	int Ne; // 边数
	WeightType G[MaxVertexNum][MaxVertexNum]; // 邻接矩阵
	/* DataType Data[MaxVertexNum]; 存储顶点的数据 */
};

typedef PtrToGNode MGraph; // 以邻接矩阵存储的图类型

定义结构体GNode,其中包含以下成员变量:

  • Nv:表示图中的顶点数。
  • Ne:表示图中的边数。

二维数组表示图的邻接矩阵。它的大小是MaxVertexNum × MaxVertexNum,用于存储顶点之间边的权重或者存在的情况。(无权重且存在边用1表示,无权重且不存在边则用0表示;有权重且存在边用其权重表示,有权重且不存在边则用一个极大值表示。)

其中,DataType Data[MaxVertexNum],可以用来存储与每个顶点相关的其他数据。例如:如果图表示一个社交网络,则可以存储每个顶点的个人资料信息(姓名、性别、年龄等),故而它的类型可以是整型,也可以是结构体类型。

创建并初始化

typedef int Vertex; /* 用顶点下标表示顶点,为整型 */

MGraph CreateGraph(int VertexNum) 
{
	Vertex V, W;
	MGraph Graph;
	Graph = (MGraph)malloc(sizeof(struct GNode));
	Graph->Nv = VertexNum;
	Graph->Ne = 0;

	/* 注意:这里默认顶点编号从0开始,到 Nv-1 */
	for (V = 0; V < Graph->Nv; V++) 
        {
		for (W = 0; W < Graph->Nv; W++) 
                {
			Graph->G[V][W] = 0; /* 如果是有权图,则设为INFINITY */
		}
	}

	return Graph;
}

变量V和W用于遍历图的顶点,Graph用于指向创建的图对象。

随后进入循环将图对象的邻接矩阵中顶点V和顶点W之间的权重(或标记)设置为0,表示它们之间没有边。注意,如果是有权图,则可以将该值设置为无穷大。

最后返回创建的图对象的指针。

插入边

typedef struct ENode* PtrToENode;
struct ENode 
{
	Vertex V1, V2; /* 有向边<V1,V2  >*/
	WeightType Weight; /* 权重  */
};
typedef PtrToENode Edge;

void InsertEdge(MGraph Graph, Edge E)
{
	/* 插入边<V1,V2> */
	Graph->G[E->V1][E->V2] = E->Weight;

	/* 如果是无向图,还要插入边<V2,V1> */
	Graph->G[E->V2][E->V1] = E->Weight;
}

这个函数用于将对应位置的邻接矩阵元素设置为权重值(无权重值则标记为1)。如果是无向图,则还需要将对称位置的元素设置为相同的权重值,以表示双向的边。

完整的图的建立 

输入格式:

\begin{matrix} Nv &Ne & \\ V1 &V2 &Weight \\ ... &... &... \end{matrix}

MGraph BuildGraph()
{
	MGraph Graph;
	Edge E;
	Vertex V;
	int Nv, i;

	scanf("%d", &Nv);
	Graph = CreateGraph(Nv);
	scanf("%d", &(Graph->Ne));
	if (Graph->Ne != 0)
	{
		E = (Edge)malloc(sizeof(struct ENode));
		for (i = 0; i < Graph->Ne; i++)
		{
			scanf("%d %d %d", &E->V1, &E->V2, &E->Weight);
			InsertEdge(Graph, E);
		}
	}

	/* 如果顶点有数据的话,读入数据 */
	for (V = 0; V < Graph->Nv; V++)
	{
		scanf("%c", &(Graph->Data[V]));
	}
	return Graph;
}

先输入顶点数,然后去创建并初始化一个无边的图;再输入边数,如果没有边数则图建立完毕(如果顶点有数据就需要另外读入数据),可以直接返回图;如果有边数,则先开辟一个临时的变量,读入边的信息及权重存储在这个临时变量中,然后调用插入边的函数。最后返回构建好的图。

如果是为了考试,或者说需要在很短的时间内完成的话,可以改成以下的简化版:

#define MAXN 100
int G[MAXN][MAXN], Nv, Ne;
void BuildGraph_()
{
	int i, j, v1, v2, w;

	scanf("%d", &Nv);
	/* CreateGraph */
	for (i = 0; i < Nv; i++)
	{
		for (j = 0; j < Nv; j++)
		{
			G[i][j] = 0; /* 或INFINITY */
		}
	}
	scanf("%d", &Ne);
	for (i = 0; i < Ne; i++)
	{
		scanf("%d %d %d", &v1, &v2, &w);
		/* InsertEdge */
		G[v1][v2] = w;
		G[v2][v1] = w;
	}
}

邻接表

图节点的结构

#include <stdio.h>
#include <stdlib.h>
#define MaxVertexNum 100 // 最大顶点数
typedef int Vertex;  /* 用顶点下标表示顶点,为整型 */
typedef float DataType;

typedef int WeightType; // 边的权重类型
// 定义指向图节点的指针类型 PtrToGNode
typedef struct GNode* PtrToGNode;

// 图节点结构体定义
struct GNode {
	int Nv;            // 顶点数
	int Ne;            // 边数
	AdjList G;         // 邻接表
};

// 图类型别名定义
typedef PtrToGNode LGraph;


// 邻接表节点结构体定义
typedef struct Vnode {
	PtrToAdjVNode FirstEdge;  // 指向第一个邻接点的指针
	DataType Data;            // 存储顶点的数据
} AdjList[MaxVertexNum];      // 邻接表类型定义


// 邻接表节点指针类型别名定义
typedef struct AdjVNode* PtrToAdjVNode;

// 邻接点结构体定义
struct AdjVNode {
	Vertex AdjV;             // 邻接点下标
	WeightType Weight;       // 边权重
	PtrToAdjVNode Next;      // 指向下一个邻接点的指针
};

创建并初始化

LGraph CreateGraph(int VertexNum)
{
	Vertex V, W;
	LGraph Graph;

	Graph = (LGraph)malloc(sizeof(struct GNode));
	Graph->Nv = VertexNum;
	Graph->Ne = 0;

	for (V = 0; V < Graph->Nv; V++)
	{
		Graph->G[V].FirstEdge = NULL;
	}
	return Graph;
}

这里的初始化要注意的一点是:“Graph->G[V].FirstEdge = NULL;”将当前顶点的邻接表的第一个邻接点指针FirstEdge设置为NULL,表示当前顶点暂时没有邻接点。

插入边 

typedef PtrToENode Edge;

void InsertEdge(LGraph Graph, Edge E)
{
	PtrToAdjVNode NewNode;

	/* 插入边<V1,V2>  */
	/*  先为V2建立新的邻接点 */
	NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
	NewNode->AdjV = E->V2;
	NewNode->Weight = E->Weight;
	/* 将V2插入V1的表头 */
	NewNode->Next = Graph->G[E->V1].FirstEdge;
	Graph->G[E->V1].FirstEdge = NewNode;

	/* 如果是无向图,还要插入边<V2,V1> */
	NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
	NewNode->AdjV = E->V1;
	NewNode->Weight = E->Weight;
	/* 将V1插入V2的表头 */
	NewNode->Next = Graph->G[E->V2].FirstEdge;
	Graph->G[E->V2].FirstEdge = NewNode;
}
  1. 为边的顶点V2创建一个新的邻接点(NewNode)。
  2. 将边的顶点V2和权重赋值给新建立的邻接点(NewNode)。
  3. 将新建立的邻接点(NewNode)插入到顶点V1的邻接表的头部。

如果是无向图,则再反过来执行一遍。

 

完整的图的建立 

LGraph BuildGraph()
{
	int Nv,i;
	Vertex V;
	LGraph Graph;
	Edge E;

	scanf("%d", Graph->Nv);
	Graph = CreateGraph(Graph->Nv);

	scanf("%d", Graph->Ne);

	if ((Graph->Ne) != 0) 
	{
		E = (Edge)malloc(sizeof(struct ENode));

		printf("Enter the edges (format: V1 V2 Weight):\n");
		for (i = 0; i < Graph->Ne; i++) 
		{
			scanf("%d %d %d", &(E->V1), &(E->V2), &(E->Weight));
			InsertEdge(Graph, E);
		}

		free(E);
	}

	return Graph;
}

与邻接矩阵的实现类似


end


学习自:MOOC数据结构——陈越、何钦铭

 

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

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

相关文章

Maven介绍与安装和配置

目录 Maven 简介 约定优于配置 Maven 特点 Maven 安装与配置 Maven 下载 配置 Maven 环境变量 Maven 简介 Maven 是一款基于 Java 平台的项目管理和整合工具&#xff0c;它将项目的开发和管理过程抽象成一个项目对象模型&#xff08;POM&#xff09;。开发人员只需要做一…

C语言结构体

C语言结构体 前言1. 结构体的声明1.1 结构体的基础知识1.2 结构体声明1.3 结构体成员的类型1.4 结构体变量的定义和初始化 2. 结构体成员的访问2.1 结构体变量访问成员2.2 结构体指针访问指针变量的成员 3. 结构体传参4. 结尾 前言 C语言结构体是一种自定义数据类型&#xff0…

vite-plugin-pwa配置详解

vite-plugin-pwa配置详解 前提&#xff1a;前端域名和后端服务域名相同时&#xff0c;用window.open新开页面下载或者导出文件&#xff0c;项目中导出和下载功能失效&#xff0c;原因是&#xff0c;域名相同走缓存 实现service worker离线缓存以前需要自己编写sw.js文件内容&…

基于SpringBoot+Vue的闲一品交易平台设计与实现

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架下…

MT4电脑版交易软件使用技巧有哪些?

MT4交易软件作为连接券商平台与投资者之间的纽带&#xff0c;不仅是外汇金融机构的首选交易平台&#xff0c;也因其显著的优势成为了外汇投资者进行网上交易的重要平台。而MT4交易软件又分为电脑版和手机版&#xff0c;因为大多数投资者进行外汇投资时使用的是MT4电脑版软件&am…

Gradio的web界面演示与交互机器学习模型,接口自动刷新或连续刷新数据流《5》

通过在接口中设置liveTrue&#xff0c;可以使接口自动刷新。现在&#xff0c;一旦用户输入发生变化&#xff0c;界面就会重新计算。依然使用计算器的示例&#xff1a; 实时接口 import gradio as grdef calculator(num1, operation, num2):if operation "add":ret…

浏览器原理+跨域+解决方案

原网址&#xff1a;浏览器部分笔记_浏览器不同窗口cookie共享吗_JackieChan_的博客-CSDN博客 一、浏览器存储对象 1.cookie cookie是一种纯文本文件&#xff0c;大小只有4kb&#xff0c;每次发送非跨域html请求时都会自动携带。特性如下&#xff1a; cookie一旦创建&#xff…

华为开源自研AI框架昇思MindSpore应用案例:Pix2Pix实现图像转换

目录 一、环境准备1.进入ModelArts官网2.使用CodeLab体验Notebook实例 在实际应用场景中&#xff0c;由于训练数据集不足&#xff0c;所以很少有人会从头开始训练整个网络。普遍的做法是&#xff0c;在一个非常大的基础数据集上训练得到一个预训练模型&#xff0c;然后使用该模…

Java程序设计入门教程--主函数

情形 在Java中&#xff0c;主函数就是主方法&#xff0c;即main()方法。它是Java应用程序的入口方法&#xff0c;也就是说&#xff0c;程序在运行的时候&#xff0c;第一个执行的方法就是main()方法&#xff0c;这个方法和其他的方法有很大的不同&#xff0c;比如方法的名字必…

Python100天:01.初识python

❝ 本教程计划通过100天的时间&#xff0c;每天分享一篇关于python的知识点&#xff0c;与大家一起学习python这门编程语言。 ❞ Python 对初学者来说是一门很棒的语言&#xff1a; 容易学 有一个积极的支持社区 在网络开发、游戏、数据科学方面提供多种机会。 Python的应用领域…

PMP课堂模拟题目及解析(第13期)

121. 项目经理、团队成员以及若干干系人共同参与一次风险研讨会。已经根据风险管理计划生成并提供一份风险报告。若要为各个项目风险进行优先级排序&#xff0c;现在必须执行哪一项分析&#xff1f; A. 定量风险分析 B. 根本原因分析 C. 偏差分析 D. 定性风险分析 122. …

Yarn资源调度详解

第1章 Yarn资源调度器 思考&#xff1a; 1&#xff09;如何管理集群资源&#xff1f; 2&#xff09;如何给任务合理分配资源&#xff1f; Yarn是一个资源调度平台&#xff0c;负责为运算程序提供服务器运算资源&#xff0c;相当于一个分布式的操作系统平台&#xff0c;而MapRe…

什么是产品操作手册?企业该怎样制作产品操作手册页面?

产品操作手册是一种用于指导用户如何正确使用和维护产品的文档。它通常包括产品的基本信息、操作步骤、安全警告、故障排除、维护方法等内容。产品操作手册对于企业来说非常重要&#xff0c;它不仅可以提高用户的使用体验&#xff0c;还可以为企业节省售后服务成本。本文将介绍…

cython编译加密python源码

场景 python的解释特性是将py编译为独有的二进制编码pyc 文件&#xff0c;然后对pyc中的指令进行解释执行&#xff0c;但是 pyc的反编译却非常简单&#xff0c;可直接反编译为源码&#xff0c;当需要将产品发布到外部环境的时候&#xff0c;源码的保护尤为重要。 一、Cpython介…

Java程序设计入门教程--标识符和关键字

目录 标识符 标识符的约定 标识符 1. 定义 用来标识类名&#xff0c;变量名&#xff0c;方法名&#xff0c;类型名&#xff0c;数组名&#xff0c;文件名的有效序列称为标识符。简单地说&#xff0c;标识符就是一个名字。 2. 标识符命名规则 &#xff08;1&#xff09;大小…

Tuxera for Mac2023中文版读写硬盘U盘工具

在日常生活中&#xff0c;我们使用Mac时经常会遇到外部设备不能正常使用的情况&#xff0c;如&#xff1a;U盘、硬盘、软盘等等一系列存储设备&#xff0c;而这些设备的格式大多为NTFS&#xff0c;Mac系统对NTFS格式分区存在一定的兼容性问题&#xff0c;不能正常读写。 那么什…

算法|1.二分及其扩展

算法|1.二分及其扩展 1、有序数组中找到num 题意&#xff1a;给定有序数组&#xff0c;在有序数组中找到指定数字&#xff0c;找到返回true&#xff0c;找不到返回false. 解题思路&#xff1a; 数组有序查找指定元素使用二分法L指针初始值设为0&#xff0c;R指针初始值设为…

chatgpt赋能python:Python修改配置文件内容

Python 修改配置文件内容 介绍 配置文件是软件开发中经常使用的一种文件&#xff0c;用于存储程序的配置参数。在实际开发中&#xff0c;我们经常需要修改配置文件内容来满足我们的需求。Python 提供了很多方法来操作配置文件&#xff0c;让我们能够方便地修改配置文件。 本…

camunda如何部署到容器云Kubernetes

部署Camunda到Kubernetes需要以下步骤&#xff1a; 1、将Camunda打包成Docker镜像。 2、在Kubernetes中创建一个Deployment对象&#xff0c;用于定义Camunda应用程序的副本数量、容器镜像、环境变量、卷挂载等信息。例如&#xff0c;可以使用以下命令创建一个Deployment&…

镜像二叉树和求二叉树最大深度(java)

镜像二叉树和求二叉树最大深度 镜像二叉树。有些题目叫翻转二叉树。是同一个题。二叉树的最大深度 镜像二叉树。有些题目叫翻转二叉树。是同一个题。 题目描述&#xff1a;给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 示例&#xff1…