X3

RedSky

导航

C#城市最短路径

123

public class City
{
    public int Id { get; set; }
    public string Name { get; set; }

    public List<City> Cities { get; set; } = new List<City>();
    public List<Road> Roads { get; set; } = new List<Road>();
}
/// <summary>
/// 城市之间的道路
/// </summary>
public class Road
{
    public int Id { get; set; }
    public int City1 { get; set; }
    public int City2 { get; set; }
    public int Days { get; set; }
}
public class CityGraph
{
    public List<City> Cities { get; set; } = new List<City>();
    public List<Road> Roads { get; set; } = new List<Road>();

    public void AddRoad(string c1, string c2, int days = 1)
    {
        AddRoad(Cities.Find(x => x.Name == c1), Cities.Find(x => x.Name == c2), days);
    }
    public void AddRoad(City city1, City city2, int days)
    {
        if(Roads.Exists(x => (x.City1 == city1.Id && x.City2 == city2.Id) || (x.City1 == city2.Id && x.City2 == city1.Id)))
            return;
        var r = new Road { City1 = city1.Id, City2 = city2.Id, Days = days };
        Roads.Add(r);
        city1.Roads.Add(r);
        city2.Roads.Add(r);
        city1.Cities.Add(city2);
        city2.Cities.Add(city1);
    }
    
    /// <summary>
    /// 查找两座城市之间的最短路径
    /// </summary>
    /// <param name="city1"></param>
    /// <param name="city2"></param>
    /// <returns></returns>
    public List<City> FindShortRoads(City city1, City city2)
    {
        //以起点城市为根节点,构建城市树
        //查找所有到达终点城市的路径
        //遍历所有路径,计算路径的深度
        //返回最小深度的路径
        CityNode root = new CityNode { Id = city1.Id };
        Tree(root);
        var list = root.FindNode(city2.Id);
        if (list.Count == 0)
            return null;
        // 计算最小深度
        int min = list.Min(x => x.Depth());
        var node = list.Find(f => f.Depth() == min);
        var result = new List<City>();
        do
        {
            result.Insert(0, Cities.Find(x => x.Id == node.Id));
            node = node.Parent;
        } while (node != null);
        return result;
    }

    /// <summary>
    /// 构建城市树
    /// </summary>
    /// <param name="node"></param>
    public void Tree(CityNode node)
    {
        var city = Cities.Find(x => x.Id == node.Id);
        foreach (var item in city.Cities)
        {
            if (!node.EqualParent(item.Id))
            {
                var road = Roads.Find(x => (x.City1 == node.Id && x.City2 == item.Id) || (x.City1 == item.Id && x.City2 == node.Id));
                node.AddChild(new CityNode { Id = item.Id, Days = road.Days });
            }
        }
        foreach (var item in node.Nodes)
        {
            Tree(item);
        }
    }
}

public class CityNode
{
    public int Id { get; set; }
    public int Days { get; set; }
    public CityNode Parent { get; set; }
    public List<CityNode> Nodes { get; set; } = new List<CityNode>();

    public void AddChild(CityNode node)
    {
        if (Nodes.Exists(x => x.Id == node.Id))
            return;
        Nodes.Add(node);
        node.Parent = this;
    }
    public void RemoveChild(CityNode node)
    {
        if (!Nodes.Exists(x => x.Id == node.Id))
            return;
        Nodes.Remove(node);
        if (node.Parent == this)
            node.Parent = null;
    }

    /// <summary>
    /// 判断父节点是否是指定的节点
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public bool EqualParent(int id)
    {
        if (Parent == null)
            return false;
        if (Parent.Id == id)
            return true;
        return Parent.EqualParent(id);
    }

    /// <summary>
    /// 计算深度
    /// </summary>
    /// <returns></returns>
    public int Depth()
    {
        if (Parent == null)
            return Days;
        return Parent.Depth() + Days;
    }

    /// <summary>
    /// 查找指定节点
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public List<CityNode> FindNode(int id)
    {
        if (Id == id)
            return new List<CityNode> { this };
        List<CityNode> list = new List<CityNode>();
        foreach (var item in Nodes)
        {
            var l = item.FindNode(id);
            if (l.Count > 0)
                list.AddRange(l);
        }
        return list;
    }
}

示例:

CityGraph cityGraph = new CityGraph();

#region Data
string s = "ABCDEFGHIJKLMNOPQRST";
for (int i = 0; i < s.Length; i++)
    cityGraph.Cities.Add(new City { Id = i + 1, Name = s[i].ToString() });
cityGraph.AddRoad("A", "B");
cityGraph.AddRoad("A", "H");
cityGraph.AddRoad("A", "G");
cityGraph.AddRoad("B", "C");
cityGraph.AddRoad("B", "J");
cityGraph.AddRoad("B", "I");
cityGraph.AddRoad("B", "H");
cityGraph.AddRoad("H", "I");
cityGraph.AddRoad("H", "P");
cityGraph.AddRoad("H", "G");
cityGraph.AddRoad("G", "P");
cityGraph.AddRoad("G", "O");
cityGraph.AddRoad("C", "D");
cityGraph.AddRoad("C", "J");
cityGraph.AddRoad("J", "D");
cityGraph.AddRoad("J", "K");
cityGraph.AddRoad("J", "I");
cityGraph.AddRoad("I", "R");
cityGraph.AddRoad("I", "Q");
cityGraph.AddRoad("I", "P");
cityGraph.AddRoad("P", "O");
cityGraph.AddRoad("D", "E");
cityGraph.AddRoad("D", "M");
cityGraph.AddRoad("D", "K");
cityGraph.AddRoad("K", "M");
cityGraph.AddRoad("K", "L");
cityGraph.AddRoad("K", "R");
cityGraph.AddRoad("R", "L");
cityGraph.AddRoad("R", "L");
cityGraph.AddRoad("R", "S");
cityGraph.AddRoad("R", "Q");
cityGraph.AddRoad("E", "F");
cityGraph.AddRoad("E", "M");
cityGraph.AddRoad("M", "F");
cityGraph.AddRoad("M", "N");
cityGraph.AddRoad("M", "L");
cityGraph.AddRoad("L", "N");
cityGraph.AddRoad("L", "T");
cityGraph.AddRoad("L", "S");
cityGraph.AddRoad("S", "T");
cityGraph.AddRoad("N", "T");
#endregion

Random random = new Random();
foreach (var item in cityGraph.Roads)
{
    item.Days = random.Next(1, 10);
}
var list = cityGraph.FindShortRoads(cityGraph.Cities[0], cityGraph.Cities.Last());
Debug.WriteLine(list.Select(x => x.Name).Aggregate((x, y) => x + "->" + y));

 

posted on 2025-05-09 17:58  HotSky  阅读(6)  评论(0)    收藏  举报