C# 根据两点名称,寻找两短路程的最优解,【有数据库设计,完整代码】

文章讲述了在数据库设计中如何通过sys_pilot表存储点位信息,并介绍了一种后端算法,利用轮询找出两点之间的最短路径,如A1到C1的最优解A1-B1-C1。同时提到了前端使用Uni-app开发的Canvas子组件实现图形绘制。
摘要由CSDN通过智能技术生成

前言

如果我们遇到路径问题,可以使用点点连线,给定一个点,可以到达另外几个点,寻找最优解
例:如下图所示,如果要从A1-C1,可以有三条路

1.A1-B1-C1
2.A1-B2-C1
3.A1-B3-C1

最优解肯定是A1-B1-C1,因为两点之间直线最短,但当业务复杂时,我们就要通过轮询来查出最优路径
在这里插入图片描述

数据库设计

首先是数据库的设计:创建表:sys_pilot

CREATE TABLE sys_pilot (
	pilotid numeric(1000) NOT NULL, -- 内场点位Id
	ptname varchar(50) NOT NULL, -- 点位名称
	xaxis int4 NOT NULL, -- X轴
	yaxis int4 NULL, -- Y轴
	transfer varchar(500) NULL, -- 经过点
	CONSTRAINT sys_pilot_pk PRIMARY KEY (pilotid)
);
COMMENT ON TABLE public.sys_pilot IS '点位图表';

后端代码

根据传入的两点名称,例:A1,C1
最优解:A1-B1-C1就会被依次返回

        private static Dictionary<string, Sys_Pilot> _points;
		/// <summary>
        /// 查找图形点位
        /// </summary>
        /// <param name="json"></param>
        /// <returns></returns>
        /// <exception cref="InterfaceException"></exception>
        public List<Sys_Pilot> VerifyPilot(string json)
        {
            Sys_Pilot pilot = JsonHelper.Instance.Deserialize<Sys_Pilot>(json);
            if (pilot == null)
            {
                throw new InterfaceException("请求参数错误");
            }

            string[] values = pilot.PtName.Split(',');

            if (values.Length != 2)
            {
                throw new InterfaceException("请传入两个点");
            }

            string inPoint = values[0];
            string terminus = values[1];

            Sys_PilotDtl pilotDtl = _paramsDal.FirstOrDefault(new Sys_PilotDtl { BeginName = inPoint, EndName = terminus });

            if (!pilotDtl.IsEmpty())
            {
                List<Sys_Pilot> pilots1 = new List<Sys_Pilot>();

                string[] Val = pilotDtl.Transfer.Split(',');

                for (int i = 0; i < Val.Length; i++)
                {
                    Sys_Pilot pilot2 = _paramsDal.FirstOrDefault(new Sys_Pilot { PtName = Val[i] });

                    pilots1.Add(pilot2);
                }

                return pilots1;
            }


            List<Sys_Pilot> pilots = _paramsDal.FindData(new Sys_Pilot());


            List<Sys_Pilot> shortestPath = ShortestPath(pilots, inPoint, terminus);

            return shortestPath;
        }
        /// <summary>
        /// 轮询查出中间点
        /// </summary>
        /// <param name="pilots"></param>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <returns></returns>
        public List<Sys_Pilot> ShortestPath(List<Sys_Pilot> pilots, string start, string end)
        {
            Dictionary<string, Sys_Pilot> _points = pilots.ToDictionary(p => p.PtName);

            if (!_points.ContainsKey(start))
                throw new InterfaceException("起点不存在!");
            if (!_points.ContainsKey(end))
                throw new InterfaceException("终点不存在!");


            ShortestPath sp = new ShortestPath();
            foreach (Sys_Pilot item in pilots)
            {
                if (item.Transfer.IsEmpty())
                {
                    continue;
                }
                foreach (string str in item.Transfer.Split(','))
                {
                    sp.AddEdge(item.PtName, str);
                }
            }

            List<string> shortestPath = sp.FindShortestPath(start, end);

            List<Sys_Pilot> pilotsList = new List<Sys_Pilot>();
            foreach (string str in shortestPath)
            {
                pilotsList.Add(pilots.Find(p => p.PtName == str));
            }

            // 保存查出的最短路径
            string transfer = string.Join(",", pilotsList.Select(p => p.PtName));
            Sys_PilotDtl pilotDtl = new Sys_PilotDtl
            {
                PilotDtlId = YitIdHelper.NextId(),
                BeginName = start,
                EndName = end,
                Transfer = transfer,
                Creator = _tokenBLL.GetUserName(),
                CreateTime = _paramsDal.GetDBDateTime(),
                Modifier = _tokenBLL.GetUserName(),
                ModifierTime = _paramsDal.GetDBDateTime()
            };
            _paramsDal.InsertData(pilotDtl);

            return pilotsList;
        }

ShortestPath类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GUIDE.IOMS.PlatForm.Common.Utilities
{
    public class ShortestPath
    {
        private Dictionary<string, List<string>> graph;

        public ShortestPath()
        {
            graph = new Dictionary<string, List<string>>();
        }

        public void AddEdge(string source, string destination)
        {
            if (!graph.ContainsKey(source))
            {
                graph[source] = new List<string>();
            }
            graph[source].Add(destination);
        }

        public List<string> FindShortestPath(string start, string end)
        {
            Queue<string> queue = new Queue<string>();
            Dictionary<string, int> distance = new Dictionary<string, int>();
            Dictionary<string, string> predecessor = new Dictionary<string, string>();
            List<string> shortestPath = new List<string>();

            distance[start] = 0;
            predecessor[start] = " ";
            queue.Enqueue(start);

            while (queue.Count > 0)
            {
                string current = queue.Dequeue();

                if (current == end)
                {
                    string temp = end;
                    while (temp != " ")
                    {
                        shortestPath.Insert(0, temp);
                        temp = predecessor[temp];
                    }
                    break;
                }

                if (graph.ContainsKey(current))
                {
                    foreach (string neighbor in graph[current])
                    {
                        if (!distance.ContainsKey(neighbor))
                        {
                            distance[neighbor] = distance[current] + 1;
                            predecessor[neighbor] = current;
                            queue.Enqueue(neighbor);
                        }
                    }
                }
            }

            return shortestPath;
        }
    }
}

后记

前端代码是通过Uni-app实现的,有兴趣可以看下Uni-app开发Canvas当子组件示例,点点绘制图形

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值