仅使用LINQ在图形中查找路径

时间:2015-06-27 02:23:56

标签: c# linq graph

这个问题是关于找到一个LINQ-Query,它从任何给定节点到任何其他给定节点提取非循环图中的路径。

请注意这只是关于LINQ(证明其权力或显示其局限性)

假设以下类表示图G = (V,E)

DataStruc

    internal class Vertice
    {
        private Int32 id;

        public Vertice(Int32 id)
        {
            this.id = id;
        }

        public Int32 GetId()
        {
            return this.id;
        }
    }
    internal class Edge
    {
        private Int32 id;
        private Vertice v1;
        private Vertice v2;

        public Edge(Int32 id, Vertice v1, Vertice v2)
        {
            this.id = id;
            this.v1 = v1;
            this.v2 = v2;
        }

        public Vertice GetFirstVertice()
        {
            return this.v1;
        }
        public Vertice GetSecondVertice()
        {
            return this.v2;
        }
        public Int32 GetId()
        {
            return this.id;
        }

        public Boolean ConnectedTo(Vertice v)
        {
            if (v.GetId() == this.v1.GetId()) return true;
            if (v.GetId() == this.v2.GetId()) return true;

            return false;
        }

        public Boolean Connects(Vertice u, Vertice v)
        {
            if (!this.ConnectedTo(u)) return false;
            if (!this.ConnectedTo(v)) return false;

            return true;
        }
    }

现在使用图片下方显示的代码创建一个图形(是的,图片显示了一个有向图,但现在让我们忽略它)

Graph to model

创建图表的代码

        // Create Vertices
        List<Vertice> v = new List<Vertice>();
        v.Add(new Vertice(0));
        v.Add(new Vertice(1));
        v.Add(new Vertice(2));
        v.Add(new Vertice(3));
        v.Add(new Vertice(4));

        // Create Edges
        List<Edge> e = new List<Edge>();
        e.Add(new Edge(0, v[0], v[1]));
        e.Add(new Edge(1, v[1], v[2]));
        e.Add(new Edge(2, v[1], v[3]));
        e.Add(new Edge(3, v[1], v[4]));
        e.Add(new Edge(4, v[2], v[4]));

现在让我们查询图表(v,e)

查询从v0提取所有边缘到v1

        var edge_query =
            from edge in e
            where edge.Connects(v[0], v[1])
            select edge;

执行查询只给出一条边(id = 0)。我现在很好奇是否可以编写返回多组边的LINQ查询,其中每个集包含从给定节点u到另一个给定节点v的一条路径

以下是可以粘贴到ConsoleApplication

的完整代码

亲切的问候, BENJ

using System;
using System.Collections.Generic;
using System.Linq;

namespace StackOverflow
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create Vertices
            List<Vertice> v = new List<Vertice>();
            v.Add(new Vertice(0));
            v.Add(new Vertice(1));
            v.Add(new Vertice(2));
            v.Add(new Vertice(3));
            v.Add(new Vertice(4));

            // Create Edges
            List<Edge> e = new List<Edge>();
            e.Add(new Edge(0, v[0], v[1]));
            e.Add(new Edge(1, v[1], v[2]));
            e.Add(new Edge(2, v[1], v[3]));
            e.Add(new Edge(3, v[1], v[4]));
            e.Add(new Edge(4, v[2], v[4]));

            // Query Set
            var edge_query =
                from edge in e
                where edge.Connects(v[0], v[1])
                select edge;

            foreach (Edge edge in edge_query)
            {
                Console.WriteLine("e" + edge.GetId() + " connects v" + edge.GetFirstVertice().GetId() + " and v" + edge.GetSecondVertice().GetId());
            }

            // Wait for the user to understand
            Console.WriteLine();
            Console.WriteLine("[ENTER] to terminate ...");
            Console.ReadLine();

        }

        internal class Vertice
        {
            private Int32 id;

            public Vertice(Int32 id)
            {
                this.id = id;
            }

            public Int32 GetId()
            {
                return this.id;
            }
        }
        internal class Edge
        {
            private Int32 id;
            private Vertice v1;
            private Vertice v2;

            public Edge(Int32 id, Vertice v1, Vertice v2)
            {
                this.id = id;
                this.v1 = v1;
                this.v2 = v2;
            }

            public Vertice GetFirstVertice()
            {
                return this.v1;
            }
            public Vertice GetSecondVertice()
            {
                return this.v2;
            }
            public Int32 GetId()
            {
                return this.id;
            }

            public Boolean ConnectedTo(Vertice v)
            {
                if (v.GetId() == this.v1.GetId()) return true;
                if (v.GetId() == this.v2.GetId()) return true;

                return false;
            }
            public Boolean Connects(Vertice u, Vertice v)
            {
                if (!this.ConnectedTo(u)) return false;
                if (!this.ConnectedTo(v)) return false;

                return true;
            }
        }
    }
}

编辑1

即。将Edge.Connects - 方法更改为

            public Boolean Connects(Vertice u, Vertice v)
            {
                if (this.v1.GetId() != u.GetId()) return false;
                if (this.v2.GetId() != v.GetId()) return false;

                return true;
            }

可以使用查询

            var edge_query =
                from u1 in v
                from edge1 in e
                from edge2 in e
                where edge1.Connects(v_start, u1)
                where edge2.Connects(u1, v_stop)
                select new Tuple<Edge, Edge>(edge1, edge2);

通过V中的任何顶点v_start提取从v_stopu1的所有路径,是否可以扩展查询以考虑任意数量的中间顶点?

enter image description here

0 个答案:

没有答案