示例#1
0
        /// <summary>
        /// Returns a cycle digraph on <c>V</c> vertices.</summary>
        /// <param name="V">the number of vertices in the cycle</param>
        /// <returns>a digraph that is a directed cycle on <c>V</c> vertices</returns>
        ///
        public static Digraph Cycle(int V)
        {
            Digraph G = new Digraph(V);

            int[] vertices = new int[V];
            for (int i = 0; i < V; i++)
            {
                vertices[i] = i;
            }
            StdRandom.Shuffle(vertices);
            for (int i = 0; i < V - 1; i++)
            {
                G.AddEdge(vertices[i], vertices[i + 1]);
            }
            G.AddEdge(vertices[V - 1], vertices[0]);
            return(G);
        }
示例#2
0
        /// <summary>
        /// Returns a random rooted-out DAG on <c>V</c> vertices and <c>E</c> edges.
        /// A rooted out-tree is a DAG in which every vertex is reachable from a
        /// single vertex.
        /// The DAG returned is not chosen uniformly at random among all such DAGs.</summary>
        /// <param name="V">the number of vertices</param>
        /// <param name="E">the number of edges</param>
        /// <returns>a random rooted-out DAG on <c>V</c> vertices and <c>E</c> edges</returns>
        ///
        public static Digraph RootedOutDAG(int V, int E)
        {
            if (E > (long)V * (V - 1) / 2)
            {
                throw new ArgumentException("Too many edges");
            }
            if (E < V - 1)
            {
                throw new ArgumentException("Too few edges");
            }
            Digraph    G   = new Digraph(V);
            SET <Edge> set = new SET <Edge>();

            // fix a topological order
            int[] vertices = new int[V];
            for (int i = 0; i < V; i++)
            {
                vertices[i] = i;
            }
            StdRandom.Shuffle(vertices);

            // one edge pointing from each vertex, other than the root = vertices[V-1]
            for (int v = 0; v < V - 1; v++)
            {
                int  w = StdRandom.Uniform(v + 1, V);
                Edge e = new Edge(w, v);
                set.Add(e);
                G.AddEdge(vertices[w], vertices[v]);
            }

            while (G.E < E)
            {
                int  v = StdRandom.Uniform(V);
                int  w = StdRandom.Uniform(V);
                Edge e = new Edge(w, v);
                if ((v < w) && !set.Contains(e))
                {
                    set.Add(e);
                    G.AddEdge(vertices[w], vertices[v]);
                }
            }
            return(G);
        }
示例#3
0
        // tournament
        /// <summary>
        /// Returns a random tournament digraph on <c>V</c> vertices. A tournament digraph
        /// is a DAG in which for every two vertices, there is one directed edge.
        /// A tournament is an oriented complete graph.</summary>
        /// <param name="V">the number of vertices</param>
        /// <returns>a random tournament digraph on <c>V</c> vertices</returns>
        ///
        public static Digraph Tournament(int V)
        {
            Digraph G = new Digraph(V);

            for (int v = 0; v < G.V; v++)
            {
                for (int w = v + 1; w < G.V; w++)
                {
                    if (StdRandom.Bernoulli(0.5))
                    {
                        G.AddEdge(v, w);
                    }
                    else
                    {
                        G.AddEdge(w, v);
                    }
                }
            }
            return(G);
        }
示例#4
0
文件: Digraph.cs 项目: zzhi/Algs4Net
        /// <summary>
        /// Returns the reverse of the digraph.</summary>
        /// <returns>the reverse of the digraph</returns>
        ///
        public Digraph Reverse()
        {
            Digraph R = new Digraph(V);

            for (int v = 0; v < V; v++)
            {
                foreach (int w in Adj(v))
                {
                    R.AddEdge(w, v);
                }
            }
            return(R);
        }
示例#5
0
        /// <summary>
        /// Initializes a digraph from a file using the specified delimiter.
        /// Each line in the file contains
        /// the name of a vertex, followed by a list of the names
        /// of the vertices adjacent to that vertex, separated by the delimiter.</summary>
        /// <param name="filename">the name of the file</param>
        /// <param name="delimiter">the delimiter between fields</param>
        ///
        public SymbolDigraph(string filename, string delimiter)
        {
            st = new ST <string, int>();

            // First pass builds the index by reading strings to associate
            // distinct strings with an index
            FileStream fsIn = File.OpenRead(filename);

            using (TextReader reader = new StreamReader(fsIn))
            {
                string nextLine = reader.ReadLine();
                while (nextLine != null)
                {
                    string[] a = nextLine.Split(delimiter.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                    for (int i = 0; i < a.Length; i++)
                    {
                        if (!st.Contains(a[i]))
                        {
                            st.Put(a[i], st.Count);
                        }
                    }
                    nextLine = reader.ReadLine();
                }
            }
            // inverted index to get string keys in an aray
            keys = new string[st.Count];
            foreach (string name in st.Keys())
            {
                keys[st[name]] = name;
            }

            // second pass builds the digraph by connecting first vertex on each
            // line to all others
            g    = new Digraph(st.Count);
            fsIn = File.OpenRead(filename);
            using (TextReader reader = new StreamReader(fsIn))
            {
                string nextLine = reader.ReadLine();
                while (nextLine != null)
                {
                    string[] a = nextLine.Split(delimiter.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                    int      v = st[a[0]];
                    for (int i = 1; i < a.Length; i++)
                    {
                        int w = st[a[i]];
                        g.AddEdge(v, w);
                    }
                    nextLine = reader.ReadLine();
                }
            }
        }
示例#6
0
        /// <summary>
        /// Returns an Eulerian cycle digraph on <c>V</c> vertices.</summary>
        /// <param name="V">the number of vertices in the cycle</param>
        /// <param name="E">the number of edges in the cycle</param>
        /// <returns>a digraph that is a directed Eulerian cycle on <c>V</c> vertices
        ///        and <c>E</c> edges</returns>
        /// <exception cref="ArgumentException">if either V &lt;= 0 or E &lt;= 0</exception>
        ///
        public static Digraph EulerianCycle(int V, int E)
        {
            if (E <= 0)
            {
                throw new ArgumentException("An Eulerian cycle must have at least one edge");
            }
            if (V <= 0)
            {
                throw new ArgumentException("An Eulerian cycle must have at least one vertex");
            }
            Digraph G = new Digraph(V);

            int[] vertices = new int[E];
            for (int i = 0; i < E; i++)
            {
                vertices[i] = StdRandom.Uniform(V);
            }
            for (int i = 0; i < E - 1; i++)
            {
                G.AddEdge(vertices[i], vertices[i + 1]);
            }
            G.AddEdge(vertices[E - 1], vertices[0]);
            return(G);
        }
示例#7
0
        public static void MainTest(string[] args)
        {
            int V = int.Parse(args[0]);
            int E = int.Parse(args[1]);

            // Eulerian cycle
            Digraph G1 = DigraphGenerator.EulerianCycle(V, E);

            DirectedEulerianPath.UnitTest(G1, "Eulerian cycle");

            // Eulerian path
            Digraph G2 = DigraphGenerator.EulerianPath(V, E);

            DirectedEulerianPath.UnitTest(G2, "Eulerian path");

            // add one random edge
            Digraph G3 = new Digraph(G2);

            G3.AddEdge(StdRandom.Uniform(V), StdRandom.Uniform(V));
            DirectedEulerianPath.UnitTest(G3, "one random edge added to Eulerian path");

            // self loop
            Digraph G4 = new Digraph(V);
            int     v4 = StdRandom.Uniform(V);

            G4.AddEdge(v4, v4);
            DirectedEulerianPath.UnitTest(G4, "single self loop");

            // single edge
            Digraph G5 = new Digraph(V);

            G5.AddEdge(StdRandom.Uniform(V), StdRandom.Uniform(V));
            DirectedEulerianPath.UnitTest(G5, "single edge");

            // empty digraph
            Digraph G6 = new Digraph(V);

            DirectedEulerianPath.UnitTest(G6, "empty digraph");

            // random digraph
            Digraph G7 = DigraphGenerator.Simple(V, E);

            DirectedEulerianPath.UnitTest(G7, "simple digraph");

            // 4-vertex digraph
            //Digraph G8 = new Digraph(new TextInput("eulerianD.txt"));
            //DirectedEulerianPath.UnitTest(G8, "4-vertex Eulerian digraph");
        }
示例#8
0
        /// <summary>
        /// Returns a complete binary tree digraph on <c>V</c> vertices.</summary>
        /// <param name="V">the number of vertices in the binary tree</param>
        /// <returns>a digraph that is a complete binary tree on <c>V</c> vertices</returns>
        ///
        public static Digraph BinaryTree(int V)
        {
            Digraph G = new Digraph(V);

            int[] vertices = new int[V];
            for (int i = 0; i < V; i++)
            {
                vertices[i] = i;
            }
            StdRandom.Shuffle(vertices);
            for (int i = 1; i < V; i++)
            {
                G.AddEdge(vertices[i], vertices[(i - 1) / 2]);
            }
            return(G);
        }
示例#9
0
        /// <summary>
        /// Returns an Eulerian path digraph on <c>V</c> vertices.</summary>
        /// <param name="V">the number of vertices in the path</param>
        /// <param name="E">the number of edges in the path</param>
        /// <returns>a digraph that is a directed Eulerian path on <c>V</c> vertices</returns>
        ///        and <c>E</c> edges
        /// <exception cref="ArgumentException">if either V &lt;= 0 or E &lt; 0</exception>
        ///
        public static Digraph EulerianPath(int V, int E)
        {
            if (E < 0)
            {
                throw new ArgumentException("negative number of edges");
            }
            if (V <= 0)
            {
                throw new ArgumentException("An Eulerian path must have at least one vertex");
            }
            Digraph G = new Digraph(V);

            int[] vertices = new int[E + 1];
            for (int i = 0; i < E + 1; i++)
            {
                vertices[i] = StdRandom.Uniform(V);
            }
            for (int i = 0; i < E; i++)
            {
                G.AddEdge(vertices[i], vertices[i + 1]);
            }
            return(G);
        }
示例#10
0
        /// <summary>
        /// Returns a random simple digraph on <c>V</c> vertices, with an
        /// edge between any two vertices with probability <c>p</c>. This is sometimes
        /// referred to as the Erdos-Renyi random digraph model.
        /// This implementations takes time propotional to V^2 (even if <c>p</c> is small).</summary>
        /// <param name="V">the number of vertices</param>
        /// <param name="p">the probability of choosing an edge</param>
        /// <returns>a random simple digraph on <c>V</c> vertices, with an edge between
        ///    any two vertices with probability <c>p</c></returns>
        /// <exception cref="ArgumentException">if probability is not between 0 and 1</exception>
        ///
        public static Digraph Simple(int V, double p)
        {
            if (p < 0.0 || p > 1.0)
            {
                throw new ArgumentException("Probability must be between 0 and 1");
            }
            Digraph G = new Digraph(V);

            for (int v = 0; v < V; v++)
            {
                for (int w = 0; w < V; w++)
                {
                    if (v != w)
                    {
                        if (StdRandom.Bernoulli(p))
                        {
                            G.AddEdge(v, w);
                        }
                    }
                }
            }
            return(G);
        }
示例#11
0
        public static void MainTest(string[] args)
        {
            int V = int.Parse(args[0]);
            int E = int.Parse(args[1]);

            // Eulerian cycle
            Digraph G1 = DigraphGenerator.EulerianCycle(V, E);

            DirectedEulerianCycle.UnitTest(G1, "Eulerian cycle");

            // Eulerian path
            Digraph G2 = DigraphGenerator.EulerianPath(V, E);

            DirectedEulerianCycle.UnitTest(G2, "Eulerian path");

            // empty digraph
            Digraph G3 = new Digraph(V);

            DirectedEulerianCycle.UnitTest(G3, "empty digraph");

            // self loop
            Digraph G4 = new Digraph(V);
            int     v4 = StdRandom.Uniform(V);

            G4.AddEdge(v4, v4);
            DirectedEulerianCycle.UnitTest(G4, "single self loop");

            // union of two disjoint cycles
            Digraph H1 = DigraphGenerator.EulerianCycle(V / 2, E / 2);
            Digraph H2 = DigraphGenerator.EulerianCycle(V - V / 2, E - E / 2);

            int[] perm = new int[V];
            for (int i = 0; i < V; i++)
            {
                perm[i] = i;
            }
            StdRandom.Shuffle(perm);
            Digraph G5 = new Digraph(V);

            for (int v = 0; v < H1.V; v++)
            {
                foreach (int w in H1.Adj(v))
                {
                    G5.AddEdge(perm[v], perm[w]);
                }
            }
            for (int v = 0; v < H2.V; v++)
            {
                foreach (int w in H2.Adj(v))
                {
                    G5.AddEdge(perm[V / 2 + v], perm[V / 2 + w]);
                }
            }
            DirectedEulerianCycle.UnitTest(G5, "Union of two disjoint cycles");

            // random digraph
            Digraph G6 = DigraphGenerator.Simple(V, E);

            DirectedEulerianCycle.UnitTest(G6, "simple digraph");

            // 4-vertex digraph - no data file
            //Digraph G7 = new Digraph(new TextInput("eulerianD.txt"));
            //DirectedEulerianCycle.UnitTest(G7, "4-vertex Eulerian digraph");
        }
示例#12
0
        /// <summary>
        /// Returns a random simple digraph on <c>V</c> vertices, <c>E</c>
        /// edges and (at least) <c>c</c> strong components. The vertices are randomly
        /// assigned integer labels between <c>0</c> and <c>c-1</c> (corresponding to
        /// strong components). Then, a strong component is creates among the vertices
        /// with the same label. Next, random edges (either between two vertices with
        /// the same labels or from a vetex with a smaller label to a vertex with a
        /// larger label). The number of components will be equal to the number of
        /// distinct labels that are assigned to vertices.</summary>
        /// <param name="V">the number of vertices</param>
        /// <param name="E">the number of edges</param>
        /// <param name="c">the (maximum) number of strong components</param>
        /// <returns>a random simple digraph on <c>V</c> vertices and
        /// <c>E</c> edges, with (at most) <c>c</c> strong components</returns>
        /// <exception cref="ArgumentException">if <c>c</c> is larger than <c>V</c></exception>
        ///
        public static Digraph Strong(int V, int E, int c)
        {
            if (c >= V || c <= 0)
            {
                throw new ArgumentException("Number of components must be between 1 and V");
            }
            if (E <= 2 * (V - c))
            {
                throw new ArgumentException("Number of edges must be at least 2(V-c)");
            }
            if (E > (long)V * (V - 1) / 2)
            {
                throw new ArgumentException("Too many edges");
            }

            // the digraph
            Digraph G = new Digraph(V);

            // edges added to G (to avoid duplicate edges)
            SET <Edge> set = new SET <Edge>();

            int[] label = new int[V];
            for (int v = 0; v < V; v++)
            {
                label[v] = StdRandom.Uniform(c);
            }

            // make all vertices with label c a strong component by
            // combining a rooted in-tree and a rooted out-tree
            for (int i = 0; i < c; i++)
            {
                // how many vertices in component c
                int count = 0;
                for (int v = 0; v < G.V; v++)
                {
                    if (label[v] == i)
                    {
                        count++;
                    }
                }

                // if (count == 0) System.err.println("less than desired number of strong components");

                int[] vertices = new int[count];
                int   j        = 0;
                for (int v = 0; v < V; v++)
                {
                    if (label[v] == i)
                    {
                        vertices[j++] = v;
                    }
                }
                StdRandom.Shuffle(vertices);

                // rooted-in tree with root = vertices[count-1]
                for (int v = 0; v < count - 1; v++)
                {
                    int  w = StdRandom.Uniform(v + 1, count);
                    Edge e = new Edge(w, v);
                    set.Add(e);
                    G.AddEdge(vertices[w], vertices[v]);
                }

                // rooted-out tree with root = vertices[count-1]
                for (int v = 0; v < count - 1; v++)
                {
                    int  w = StdRandom.Uniform(v + 1, count);
                    Edge e = new Edge(v, w);
                    set.Add(e);
                    G.AddEdge(vertices[v], vertices[w]);
                }
            }

            while (G.E < E)
            {
                int  v = StdRandom.Uniform(V);
                int  w = StdRandom.Uniform(V);
                Edge e = new Edge(v, w);
                if (!set.Contains(e) && v != w && label[v] <= label[w])
                {
                    set.Add(e);
                    G.AddEdge(v, w);
                }
            }

            return(G);
        }