C#,图论与图算法,图(Graph)的数据结构设计与源代码

news2024/11/24 16:52:18

因为后面即将发布的大量有关“图”的算法与源代码都需要用到下面的这些基础数据,为避免大家去下载,特意先发布于此。

一、图(Graph)的基础知识

图(Graph)是一组对象的图示,其中一些对象对通过链接连接。互连对象由称为顶点的点表示,连接顶点的链接称为边。

形式上,图是一对集(V,E),其中V是顶点集,E是连接顶点对的边集。

图形数据结构

数学图可以用数据结构表示。我们可以使用顶点数组和二维边数组来表示图。在继续之前,让我们先熟悉一些重要的术语−

顶点− 图的每个节点都表示为一个顶点。在以下示例中,带标签的圆表示顶点。因此,A到G是顶点。我们可以使用下图所示的数组来表示它们。这里A可以通过索引0来标识。B可以使用索引1等进行识别。

− 边表示两个顶点之间的路径或两个顶点之间的线。在以下示例中,从A到B、B到C等的线表示边。我们可以使用二维数组来表示数组,如下图所示。这里AB可以表示为第0行第1列的1,BC可以表示为第1行第2列的1,依此类推,其他组合保持为0。

邻接关系− 如果两个节点或顶点通过边相互连接,则它们是相邻的。在以下示例中,B与A相邻,C与B相邻,依此类推。

路径− 路径表示两个顶点之间的边序列。

二、图的基本操作

以下是图形的基本主要操作:

添加顶点 — 将顶点添加到图形中。

添加边 — 在图形的两个顶点之间添加边。

显示顶点 — 显示图形的顶点。

遍历 — 深度优先遍历,宽度优先遍历;

布局 — 图的布局算法

三、图的相关数据

1、节点

using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;

namespace Legalsoft.Truffer.Algorithm
{
    /// <summary>
    /// 图的结点(坐标)信息
    /// </summary>
    public class Node
    {
        /// <summary>
        /// 编号
        /// </summary>
        public int Id { get; set; } = 0;
        /// <summary>
        /// X坐标
        /// </summary>
        public double X { get; set; } = 0.0;
        /// <summary>
        /// Y坐标
        /// </summary>
        public double Y { get; set; } = 0.0;
        //public int Weight { get; set; } = 0;
        /// <summary>
        /// 默认构造函数
        /// </summary>
        public Node() 
		{
		}

		public Node(int id) 
		{
			Id = id;
		}

        /// <summary>
        /// 长度(原点距离)
        /// </summary>
        public double Length
        {
            get
            {
                double len = LengthSquare;
                if (Math.Abs(len) < float.Epsilon) return 0.0;
                return Math.Sqrt(len);
            }
        }

        /// <summary>
        /// 长度平方
        /// </summary>
        public double LengthSquare
        {
            get
            {
                return (X * X) + (Y * Y);
            }
        }

        /// <summary>
        /// 缩放
        /// </summary>
        /// <param name="rate"></param>
        public void Scale(double rate)
        {
            X *= rate;
            Y *= rate;
        }

        /// <summary>
        /// 移动到目的点
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public void MoveTo(double x, double y)
        {
            X = x;
            Y = y;
        }

        /// <summary>
        /// 移动
        /// </summary>
        /// <param name="delta"></param>
        public void Move(Node delta)
        {
            this.X += delta.X;
            this.Y += delta.Y;
        }

        /// <summary>
        /// 加号重载
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static Node operator +(Node a, Node b)
        {
            Node c = new Node();
            c.X = a.X + b.X;
            c.Y = a.Y + b.Y;
            return c;
        }

        /// <summary>
        /// 减号重载
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static Node operator -(Node a, Node b)
        {
            Node c = new Node();
            c.X = a.X - b.X;
            c.Y = a.Y - b.Y;
            return c;
        }
    }
}

2、边

using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;

namespace Legalsoft.Truffer.Algorithm
{
	public class Edge
	{
		/// <summary>
		/// 起点(第一点)编号
		/// </summary>
		public int First { get; set; } = -1;
		/// <summary>
		/// 终点(第二点)编号
		/// </summary>
		public int Second { get; set; } = -1;
		/// <summary>
		/// 权值
		/// </summary>
		public int Weight { get; set; } = 0;
		/// <summary>
		/// 默认构造函数
		/// </summary>
		public Edge()
		{
		}
		/// <summary>
		/// 两点构造函数
		/// </summary>
		/// <param name="f"></param>
		/// <param name="s"></param>
		public Edge(int f, int s)
		{
			First = f;
			Second = s;
		}
		/// <summary>
		/// 两点及权值构造函数
		/// </summary>
		/// <param name="f"></param>
		/// <param name="s"></param>
		/// <param name="w"></param>
		public Edge(int f, int s, int w)
		{
			First = f;
			Second = s;
			Weight = w;
		}
	}
}

3、图

using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;

namespace Legalsoft.Truffer.Algorithm
{
	public partial class Graph
	{
		/// <summary>
		/// 是否为有向图?
		/// </summary>
		public bool Direction { get; set; } = false;
		/*
		/// <summary>
		/// 节点编码的起始编号0或1
		/// </summary>
		public int Node_Index_Start { get; set; } = 0;
		/// <summary>
		/// 节点编码的结束编号
		/// </summary>
		public int Node_Index_End { get; set; } = 0;
		*/
		/// <summary>
		/// 节点总数
		/// </summary>
		public int Node_Number { get; set; } = 0;
		/*
		/// <summary>
		/// 连线编码的起始编号0或1
		/// </summary>
		public int Edge_Start { get; set; } = 0;
		*/
		/// <summary>
		/// 连接线总数
		/// </summary>
		public int Edge_Number { get; set; } = 0;
		/// <summary>
		/// 节点编码列表
		/// </summary>
		public List<Node> Nodes { get; set; } = new List<Node>();
		/// <summary>
		/// 连接线列表
		/// </summary>
		public List<Edge> Edges { get; set; } = new List<Edge>();
		/// <summary>
		/// 节点邻接表
		/// </summary>
		public List<int>[] Adjacency { get; set; } = null;
		/// <summary>
		/// 邻接矩阵
		/// </summary>
		public int[,] Matrix { get; set; } = null;

		public Graph()
		{
		}

		public Graph(int v, int e = 0, bool direct = false)
		{
			Direction = direct;
			Node_Number = v;
			Edge_Number = e;
			Adjacency = new List<int>[Node_Number + 1];
			for (int i = 0; i <= Node_Number; i++)
			{
				Adjacency[i] = new List<int>();
			}
		}

		public void AddEdge(int a, int b)
		{
			Adjacency[a].Add(b);
			if (Direction == false)
			{
				Adjacency[b].Add(a);
			}
		}

		public void AddEdge(int a, int b, int w)
		{
			AddEdge(a, b);
			Edges.Add(new Edge(a, b, w));
		}

		public void AddEdge(int idx, int a, int b, int w)
		{
			Edges[idx] = new Edge(a, b, w);
		}

		public void AddNode(int a)
		{
			if (!Nodes.Exists(t => t.Id == a))
			{
				Nodes.Add(new Node(a));
			}
		}

		/// <summary>
		/// 按三元组构造图数据
		/// 三元数组为: {source,destination,weight}
		/// </summary>
		/// <param name="ternary_array">三元数据</param>
		public Graph(int[,] ternary_array, bool dir = false)
		{
			// 有向图?无向图?
			Direction = dir;

			Nodes = new List<Node>();
			Edges = new List<Edge>();
			Edge_Number = ternary_array.GetLength(0);
			for (int i = 0; i < ternary_array.GetLength(0); i++)
			{
				int n1 = ternary_array[i, 0];
				int n2 = ternary_array[i, 1];
				int wt = ternary_array[i, 2];
				AddEdge(n1, n2, wt);
			}
		}

		/// <summary>
		/// 按关联矩阵数据构建图
		/// [N x N],元素=0,无连接,>0 有连接线及weight
		/// </summary>
		/// <param name="v">节点数</param>
		/// <param name="e">连边数</param>
		/// <param name="matrix">关联矩阵</param>
		public Graph(int[,] matrix)
		{
			Node_Number = matrix.GetLength(0);
			Nodes = new List<Node>();
			Edges = new List<Edge>();
			Matrix = new int[Node_Number, Node_Number];
			for (int i = 0; i < Node_Number; i++)
			{
				for (int j = 0; j < Node_Number; j++)
				{
					if (matrix[i, j] > 0)
					{
						AddEdge(i, j, matrix[i, j]);
						Matrix[i, j] = matrix[i, j];
					}
				}
			}
		}

		public Edge FindEdge(int a, int b)
        {
			foreach (Edge e in Edges)
			{
				if (e.First == a && e.Second == b)
				{
					return e;
				}
				if (Direction == false)
				{
					if (e.First == b && e.Second == a)
					{
						return e;
					}
				}
			}
			return null;
        }

		/// <summary>
		/// 按邻接表的构造函数
		/// </summary>
		/// <param name="adj"></param>
		public Graph(List<List<int>> adj, bool dir = false)
		{
			// 有向图?无向图?
			Direction = dir;

			Node_Number = adj.Count;
			Nodes = new List<Node>();
			Edges = new List<Edge>();

			// 邻接矩阵
			Adjacency = adj.ToArray();

			int idx = 1;
			foreach (List<int> xu in adj)
			{
				foreach (int xv in xu)
				{
					AddEdge(idx, xv);
				}
				idx++;
			}
		}

		/// <summary>
		/// 邻接表 转为 邻接矩阵
		/// 1 起步!
		/// </summary>
		/// <returns></returns>
		public int[,] AdjacencyMatrix()
		{
			if (Matrix == null)
			{
				Matrix = new int[Node_Number + 1, Node_Number + 1];
				int idx = 0;
				foreach (List<int> xu in Adjacency)
				{
					// 因为 Adjacency[0] 没有被使用!跳过!
					if (idx > 0)
					{
						foreach (int xv in xu)
						{
							Matrix[idx, xv] = 1;
						}
					}
					idx++;
				}
			}
			return Matrix;
		}
	}
}

POWER BY TRUFFER.CN

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

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

相关文章

STM32(TIM定时器中断)

理论知识 定时器定时中断 接线图 定时器工作配置步骤 定时中断和内外时钟源选择 定时器中需要使用的函数 程序实现效果&#xff1a; void TIM_DeInit(TIM_TypeDef* TIMx); **// 恢复定时器的缺省配置**void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef*TIM…

jupyter中pip安装包会安装到别的环境。

文章目录 1. 查看jupyter当前环境和默认环境的路径和python版本2.安装包到正确的环境 如果你在 Jupyter Notebook 中使用 pip 安装包&#xff0c;它默认会将包安装到 Jupyter Notebook 所在的Python 环境。这可能会导致安装的包与你期望的环境不匹配。 1. 查看jupyter当前环境和…

RK3568平台开发系列讲解(基础篇)内核是如何发送事件到用户空间

🚀返回专栏总目录 文章目录 一、相关接口函数二、udevadm 命令三、实验沉淀、分享、成长,让自己和他人都能有所收获!😄 一、相关接口函数 kobject_uevent 是 Linux 内核中的一个函数, 用于生成和发送 uevent 事件。 它是 udev 和其他设备管理工具与内核通信的一种方式。…

mybatis源码阅读系列(二)

前言 上一篇文章mybatis源码阅读系列&#xff08;一&#xff09;介绍了mybatis和原生jdbc的区别&#xff0c;并通过代码展示了两者的运行过程和结果&#xff0c;下面让我们继续详细了解下mybatis的执行过程&#xff1b; package com.wyl.mybatis.service;import com.wyl.mybat…

给定参数c和长度为n的递增数组a(ai <= c), 对于0<=x<=y<=c, 求(x,y)的对数,满足x+y不是数组a中的元素且y-x不是a中元素

题目 思路&#xff1a; #include <bits/stdc.h> using namespace std; #define int long long #define pb push_back #define fi first #define se second #define lson p << 1 #define rson p << 1 | 1 const int maxn 1e6 5, inf 1e18, maxm 4e4 5, …

微信小程序关闭首页广告

由于之前微信小程序默认开启了首页广告位。导致很多老人误入广告页的内容&#xff0c;所以想着怎么屏蔽广告。好家伙&#xff0c;搜索一圈&#xff0c;要么是用户版本的屏蔽广告&#xff0c;或者是以下一个模棱两可的答案&#xff0c;要开发者设置一下什么参数的&#xff0c;如…

Opencascade基础教程(11):设置显示模式

1、设置显示模式 1.1 增加按钮添加消息响应函数 //线框 void COCCDemoDoc::OnButtonWireframemode() {//关闭边界框const Handle(Prs3d_Drawer)& aDrawer m_AISContext->DefaultDrawer();aDrawer->SetFaceBoundaryDraw(false);//线框m_AISContext->SetDisplayMo…

【SQL】1193. 每月交易 I 【年月日(日期)拼接相关函数】

前述 知识点学习&#xff1a; SQL 日期函数 day() 、month()、year() 各种使用方法mysql 两个字符年月拼接 题目描述 leetcode题目&#xff1a;1193. 每月交易 I 思路 先按照年月排&#xff0c;再按照country排列 日期拼接相关的函数 year(): 截取年份&#xff1b;month…

springboot蛋糕订购小程序的设计与实现

摘 要 相比于以前的传统手工管理方式&#xff0c;智能化的管理方式可以大幅降低商家的运营人员成本&#xff0c;实现了蛋糕订购的标准化、制度化、程序化的管理&#xff0c;有效地防止了蛋糕订购的随意管理&#xff0c;提高了信息的处理速度和精确度&#xff0c;能够及时、准确…

如何重置iPhone的网络设置?这里提供详细步骤

前言 本文介绍如何重置iPhone上的网络设置。该信息适用于iPhone 12到iPhone 6以及iOS 14到iOS 8。 如何在iPhone上重置网络设置 采取以下步骤重置iPhone上的网络设置&#xff1a; 1、在iPhone上&#xff0c;打开设置应用程序。 2、单击通用。 3、滚动到屏幕底部&#xff…

如何保存缓存和MySQL的双写一致呢?

如何保存缓存和MySQL的双写一致呢&#xff1f; 所谓的双写一致指的是&#xff0c;在同时使用缓存(如Redis)和数据库(如MySQL)的场景下,确保数据在缓存和数据库中的更新操作保持一致。当对数据进行修改的时候&#xff0c;无论是先修改缓存还是先修改数据库&#xff0c;最终都要保…

深度学习-解读GoogleNet深度学习网络

深度学习-解读GoogleNet深度学习网络 深度学习中&#xff0c;经典网络引领一波又一波的技术革命&#xff0c;从LetNet到当前最火的GPT所用的Transformer&#xff0c;它们把AI技术不断推向高潮。2012年AlexNet大放异彩&#xff0c;它把深度学习技术引领第一个高峰&#xff0c;打…

双向SSM: Vision Mamba Encoder

文章目录 Vision Mamba Encoder初始化输入映射序列变换参数映射BC参数映射delta参数映射 SSM参数初始化A , D矩阵初始化delta参数初始化 双向SSM初始化参数初始化 前向输入映射fast_pathuse_fast_pathno use_fast_path 双向SSMv1前向后向 v2前向后向 Vision Mamba Encoder Vis…

(四)Android布局类型(线性布局LinearLayout)

线性布局&#xff08;LinearLayout&#xff09;&#xff1a;按照一定的方向排列组件&#xff0c;方向主要分为水平方向和垂直方向。方向的设置通过属性android:orientation设置 android:orientation 其取值有两种 水平方向&#xff1a;android:orientation"horizontal&…

蓝桥杯单片机快速开发笔记——独立键盘

一、原理分析 二、思维导图 三、示例框架 #include "reg52.h" sbit S7 P3^0; sbit S6 P3^1; sbit S5 P3^2; sbit S4 P3^3; void ScanKeys(){if(S7 0){Delay(500);if(S7 0){while(S7 0);}}if(S6 0){Delay(500);if(S6 0){while(S6 0)…

简易版 RPC 框架实现 1.0 -http实现

RPC 是“远程过程调用&#xff08;Remote Procedure Call&#xff09;”的缩写形式&#xff0c;比较通俗的解释是&#xff1a;像本地方法调用一样调用远程的服务。虽然 RPC 的定义非常简单&#xff0c;但是相对完整的、通用的 RPC 框架涉及很多方面的内容&#xff0c;例如注册发…

iPhone 的健康数据采用的是 FHIR 传输格式

虽然感觉 FHIR 的数据传输格式还是有点繁琐的&#xff0c;但貌似现在也是唯一的事实上的标准。 通过 iPhone 健康上面查看的数据来看&#xff0c;有关健康的数据还是使用 FHIR 的数据传输格式。 不管怎么样&#xff0c;针对老旧的数据传输格式来看&#xff0c;FHIR 至少目前还是…

【网络】负载均衡

OSI模型每一层的负载均衡 在OSI模型中&#xff0c;每一层的负载均衡具体如下&#xff1a; 1. 第二层&#xff08;数据链路层&#xff09;&#xff1a;数据链路层的负载均衡通常涉及对MAC地址的操作。在这一层&#xff0c;可以使用虚拟MAC地址技术&#xff0c;外部设备对虚拟MA…

html中如何让网页禁用右键禁止查看源代码

在网页中&#xff0c;辛辛苦苦写的文章&#xff0c;被别人复制粘贴给盗用去另很多站长感到非常无奈&#xff0c;通常大家复制都会使用选取右键复制&#xff0c;或CTRLC等方式&#xff0c;下面介绍几种禁止鼠标右键代码&#xff0c;可减少网页上文章被抄袭的几率&#xff0c;当然…

软件杯 深度学习 python opencv 动物识别与检测

文章目录 0 前言1 深度学习实现动物识别与检测2 卷积神经网络2.1卷积层2.2 池化层2.3 激活函数2.4 全连接层2.5 使用tensorflow中keras模块实现卷积神经网络 3 YOLOV53.1 网络架构图3.2 输入端3.3 基准网络3.4 Neck网络3.5 Head输出层 4 数据集准备4.1 数据标注简介4.2 数据保存…