Пример #1
0
        private int M;         // number of characters in regular expression

        /// <summary>Initializes the NFA from the specified regular expression.</summary>
        /// <param name="regexp">the regular expression</param>
        /// <exception cref="ArgumentException">if the regular expression is invalid</exception>
        ///
        public NFA(string regexp)
        {
            this.regexp = regexp;
            M           = regexp.Length;
            LinkedStack <int> ops = new LinkedStack <int>();

            G = new Digraph(M + 1);
            for (int i = 0; i < M; i++)
            {
                int lp = i;
                if (regexp[i] == '(' || regexp[i] == '|')
                {
                    ops.Push(i);
                }
                else if (regexp[i] == ')')
                {
                    int or = ops.Pop();

                    // 2-way or operator
                    if (regexp[or] == '|')
                    {
                        lp = ops.Pop();
                        G.AddEdge(lp, or + 1);
                        G.AddEdge(or, i);
                    }
                    else if (regexp[or] == '(')
                    {
                        lp = or;
                    }
                    else
                    {
                        Debug.Assert(false);
                    }
                }

                // closure operator (uses 1-character lookahead)
                if (i < M - 1 && regexp[i + 1] == '*')
                {
                    G.AddEdge(lp, i + 1);
                    G.AddEdge(i + 1, lp);
                }
                if (regexp[i] == '(' || regexp[i] == '*' || regexp[i] == ')')
                {
                    G.AddEdge(i, i + 1);
                }
            }
            if (ops.Count != 0)
            {
                throw new ArgumentException("Invalid regular expression");
            }
        }
Пример #2
0
        private void dfs(Digraph G, int v)
        {
            marked[v] = true;
            low[v]    = pre++;
            int min = low[v];

            stack.Push(v);
            foreach (int w in G.Adj(v))
            {
                if (!marked[w])
                {
                    dfs(G, w);
                }
                if (low[w] < min)
                {
                    min = low[w];
                }
            }
            if (min < low[v])
            {
                low[v] = min;
                return;
            }
            int u;

            do
            {
                u      = stack.Pop();
                id[u]  = count;
                low[u] = G.V;
            } while (u != v);
            count++;
        }
Пример #3
0
        private void dfs(Digraph G, int v)
        {
            marked[v]   = true;
            preorder[v] = pre++;
            stack1.Push(v);
            stack2.Push(v);
            foreach (int w in G.Adj(v))
            {
                if (!marked[w])
                {
                    dfs(G, w);
                }
                else if (id[w] == -1)
                {
                    while (preorder[stack2.Peek()] > preorder[w])
                    {
                        stack2.Pop();
                    }
                }
            }

            // found strong component containing v
            if (stack2.Peek() == v)
            {
                stack2.Pop();
                int w;
                do
                {
                    w     = stack1.Pop();
                    id[w] = count;
                } while (w != v);
                count++;
            }
        }
Пример #4
0
        private LinkedStack <int> cycle = null; // Eulerian cycle; null if no such cylce

        /// <summary>
        /// Computes an Eulerian cycle in the specified digraph, if one exists.
        /// </summary>
        /// <param name="G">the digraph</param>
        ///
        public DirectedEulerianCycle(Digraph G)
        {
            // must have at least one edge
            if (G.E == 0)
            {
                return;
            }

            // necessary condition: indegree(v) = outdegree(v) for each vertex v
            // (without this check, DFS might return a path instead of a cycle)
            for (int v = 0; v < G.V; v++)
            {
                if (G.Outdegree(v) != G.Indegree(v))
                {
                    return;
                }
            }

            // create local view of adjacency lists, to iterate one vertex at a time
            IEnumerator <int>[] adj = new IEnumerator <int> [G.V];
            for (int v = 0; v < G.V; v++)
            {
                adj[v] = G.Adj(v).GetEnumerator();
            }

            // initialize stack with any non-isolated vertex
            int s = nonIsolatedVertex(G);
            LinkedStack <int> stack = new LinkedStack <int>();

            stack.Push(s);

            // greedily add to putative cycle, depth-first search style
            cycle = new LinkedStack <int>();
            while (!stack.IsEmpty)
            {
                int v = stack.Pop();
                while (adj[v].MoveNext())
                {
                    stack.Push(v);
                    v = adj[v].Current;
                }
                // add vertex with no more leaving edges to cycle
                cycle.Push(v);
            }

            // check if all edges have been used
            // (in case there are two or more vertex-disjoint Eulerian cycles)
            if (cycle.Count != G.E + 1)
            {
                cycle = null;
            }

            Debug.Assert(certifySolution(G));
        }
Пример #5
0
        private void bfs(Graph G, int s)
        {
            LinkedQueue <int> q = new LinkedQueue <int>();

            color[s]  = WHITE;
            marked[s] = true;
            q.Enqueue(s);

            while (!q.IsEmpty)
            {
                int v = q.Dequeue();
                foreach (int w in G.Adj(v))
                {
                    if (!marked[w])
                    {
                        marked[w] = true;
                        edgeTo[w] = v;
                        color[w]  = !color[v];
                        q.Enqueue(w);
                    }
                    else if (color[w] == color[v])
                    {
                        isBipartite = false;

                        // to form odd cycle, consider s-v path and s-w path
                        // and let x be closest node to v and w common to two paths
                        // then (w-x path) + (x-v path) + (edge v-w) is an odd-length cycle
                        // Note: distTo[v] == distTo[w];
                        cycle = new LinkedQueue <int>();
                        LinkedStack <int> stack = new LinkedStack <int>();
                        int x = v, y = w;
                        while (x != y)
                        {
                            stack.Push(x);
                            cycle.Enqueue(y);
                            x = edgeTo[x];
                            y = edgeTo[y];
                        }
                        stack.Push(x);
                        while (!stack.IsEmpty)
                        {
                            cycle.Enqueue(stack.Pop());
                        }
                        cycle.Enqueue(w);
                        return;
                    }
                }
            }
        }
Пример #6
0
        private readonly int s; // source vertex

        /// <summary>
        /// Computes the vertices connected to the source vertex <c>s</c> in the graph <c>G</c>.</summary>
        /// <param name="G">the graph</param>
        /// <param name="s">the source vertex</param>
        ///
        public NonrecursiveDFS(Graph G, int s)
        {
            this.s = s;
            marked = new bool[G.V];
            edgeTo = new int[G.V];

            // to be able to iterate over each adjacency list, keeping track of which
            // vertex in each adjacency list needs to be explored next
            IEnumerator <int>[] adj = new IEnumerator <int> [G.V];
            for (int v = 0; v < G.V; v++)
            {
                adj[v] = G.Adj(v).GetEnumerator();
            }

            // depth-first search using an explicit stack
            LinkedStack <int> stack = new LinkedStack <int>();

            marked[s] = true;
            stack.Push(s);
            //Console.Write("Visiting ({0})\n", s);
            while (!stack.IsEmpty)
            {
                int v = stack.Peek();
                if (adj[v].MoveNext())
                {
                    int w = adj[v].Current;
                    //Console.Write("Approaching {0}\n", w);
                    if (!marked[w])
                    {
                        // discovered vertex w for the first time
                        marked[w] = true;
                        edgeTo[w] = v;
                        stack.Push(w);
                        //Console.Write("Visiting ({0})\n", w);
                    }
                    //else
                    //  Console.Write("Visited {0}\n", w);
                }
                else
                {
                    //Console.Write("Returning from {0}\n", stack.Peek());
                    stack.Pop();
                }
            }
        }
Пример #7
0
        public static void MainTest(string[] args)
        {
            LinkedStack <string> s = new LinkedStack <string>();

            TextInput StdIn = new TextInput();

            while (!StdIn.IsEmpty)
            {
                string item = StdIn.ReadString();
                if (!item.Equals("-"))
                {
                    s.Push(item);
                }
                else if (!s.IsEmpty)
                {
                    Console.Write(s.Pop() + " ");
                }
            }
            Console.WriteLine("(" + s.Count + " left on stack)");
        }
Пример #8
0
        private bool[] marked; // marked[v] = is there an s->v path?

        /// <summary>
        /// Computes the vertices reachable from the source vertex <c>s</c> in the
        /// digraph <c>G</c>.</summary>
        /// <param name="G">the digraph</param>
        /// <param name="s">the source vertex</param>
        ///
        public NonrecursiveDirectedDFS(Digraph G, int s)
        {
            marked = new bool[G.V];

            // to be able to iterate over each adjacency list, keeping track of which
            // vertex in each adjacency list needs to be explored next
            IEnumerator <int>[] adj = new IEnumerator <int> [G.V];
            for (int v = 0; v < G.V; v++)
            {
                adj[v] = G.Adj(v).GetEnumerator();
            }

            // depth-first search using an explicit stack
            LinkedStack <int> stack = new LinkedStack <int>();

            marked[s] = true;
            stack.Push(s);
            while (!stack.IsEmpty)
            {
                int v = stack.Peek();
                if (adj[v].MoveNext())
                {
                    int w = adj[v].Current;
                    // Console.Write("check {0}\n", w);
                    if (!marked[w])
                    {
                        // discovered vertex w for the first time
                        marked[w] = true;
                        // edgeTo[w] = v;
                        stack.Push(w);
                        // Console.Write("dfs({0})\n", w);
                    }
                }
                else
                {
                    // Console.Write("{0} done\n", v);
                    stack.Pop();
                }
            }
        }
Пример #9
0
        /// <summary>
        /// Computes the convex hull of the specified array of points.
        /// </summary>
        /// <param name="pts">the array of points</param>
        /// <exception cref="NullReferenceException">if <c>points</c> is <c>null</c> or if any
        /// entry in <c>points[]</c> is <c>null</c></exception>
        ///
        public GrahamScan(Point2D[] pts)
        {
            // defensive copy
            int N = pts.Length;

            Point2D[] points = new Point2D[N];
            for (int i = 0; i < N; i++)
            {
                points[i] = pts[i];
            }

            // preprocess so that points[0] has lowest y-coordinate; break ties by x-coordinate
            // points[0] is an extreme point of the convex hull
            // (alternatively, could do easily in linear time)
            Array.Sort(points);

            // sort by polar angle with respect to base point points[0],
            // breaking ties by distance to points[0]
            Array.Sort(points, 1, N - 1, points[0].GetPolarOrder());

            hull.Push(points[0]); // p[0] is first extreme point

            // find index k1 of first point not equal to points[0]
            int k1;

            for (k1 = 1; k1 < N; k1++)
            {
                if (!points[0].Equals(points[k1]))
                {
                    break;
                }
            }
            if (k1 == N)
            {
                return;           // all points equal
            }
            // find index k2 of first point not collinear with points[0] and points[k1]
            int k2;

            for (k2 = k1 + 1; k2 < N; k2++)
            {
                if (Point2D.Ccw(points[0], points[k1], points[k2]) != 0)
                {
                    break;
                }
            }
            hull.Push(points[k2 - 1]); // points[k2-1] is second extreme point

            // Graham scan; note that points[N-1] is extreme point different from points[0]
            for (int i = k2; i < N; i++)
            {
                Point2D top = hull.Pop();
                while (Point2D.Ccw(hull.Peek(), top, points[i]) <= 0)
                {
                    top = hull.Pop();
                }
                hull.Push(top);
                hull.Push(points[i]);
            }

            Debug.Assert(isConvex());
        }
Пример #10
0
        /// <summary>
        /// Computes an Eulerian cycle in the specified graph, if one exists.</summary>
        /// <param name="G">the graph</param>
        ///
        public EulerianCycle(Graph G)
        {
            // must have at least one edge
            if (G.E == 0)
            {
                return;
            }

            // necessary condition: all vertices have even degree
            // (this test is needed or it might find an Eulerian path instead of cycle)
            for (int v = 0; v < G.V; v++)
            {
                if (G.Degree(v) % 2 != 0)
                {
                    return;
                }
            }

            // create local view of adjacency lists, to iterate one vertex at a time
            // the helper Edge data type is used to avoid exploring both copies of an edge v-w
            LinkedQueue <Edge>[] adj = new LinkedQueue <Edge> [G.V];
            for (int v = 0; v < G.V; v++)
            {
                adj[v] = new LinkedQueue <Edge>();
            }

            for (int v = 0; v < G.V; v++)
            {
                int selfLoops = 0;
                foreach (int w in G.Adj(v))
                {
                    // careful with self loops
                    if (v == w)
                    {
                        if (selfLoops % 2 == 0)
                        {
                            Edge e = new Edge(v, w);
                            adj[v].Enqueue(e);
                            adj[w].Enqueue(e);
                        }
                        selfLoops++;
                    }
                    else if (v < w)
                    {
                        Edge e = new Edge(v, w);
                        adj[v].Enqueue(e);
                        adj[w].Enqueue(e);
                    }
                }
            }

            // initialize stack with any non-isolated vertex
            int s = nonIsolatedVertex(G);
            LinkedStack <int> stack = new LinkedStack <int>();

            stack.Push(s);

            // greedily search through edges in iterative DFS style
            cycle = new LinkedStack <int>();
            while (!stack.IsEmpty)
            {
                int v = stack.Pop();
                while (!adj[v].IsEmpty)
                {
                    Edge edge = adj[v].Dequeue();
                    if (edge.IsUsed)
                    {
                        continue;
                    }
                    edge.IsUsed = true;
                    stack.Push(v);
                    v = edge.Other(v);
                }
                // push vertex with no more leaving edges to cycle
                cycle.Push(v);
            }

            // check if all edges are used
            if (cycle.Count != G.E + 1)
            {
                cycle = null;
            }

            Debug.Assert(certifySolution(G));
        }
Пример #11
0
        /// <summary>
        /// Computes an Eulerian path in the specified graph, if one exists.</summary>
        /// <param name="G">the graph</param>
        ///
        public EulerianPath(Graph G)
        {
            // find vertex from which to start potential Eulerian path:
            // a vertex v with odd degree(v) if it exits;
            // otherwise a vertex with degree(v) > 0
            int oddDegreeVertices = 0;
            int s = nonIsolatedVertex(G);

            for (int v = 0; v < G.V; v++)
            {
                if (G.Degree(v) % 2 != 0)
                {
                    oddDegreeVertices++;
                    s = v;
                }
            }

            // graph can't have an Eulerian path
            // (this condition is needed for correctness)
            if (oddDegreeVertices > 2)
            {
                return;
            }

            // special case for graph with zero edges (has a degenerate Eulerian path)
            if (s == -1)
            {
                s = 0;
            }

            // create local view of adjacency lists, to iterate one vertex at a time
            // the helper Edge data type is used to avoid exploring both copies of an edge v-w
            LinkedQueue <Edge>[] adj = new LinkedQueue <Edge> [G.V];
            for (int v = 0; v < G.V; v++)
            {
                adj[v] = new LinkedQueue <Edge>();
            }

            for (int v = 0; v < G.V; v++)
            {
                int selfLoops = 0;
                foreach (int w in G.Adj(v))
                {
                    // careful with self loops
                    if (v == w)
                    {
                        if (selfLoops % 2 == 0)
                        {
                            Edge e = new Edge(v, w);
                            adj[v].Enqueue(e);
                            adj[w].Enqueue(e);
                        }
                        selfLoops++;
                    }
                    else if (v < w)
                    {
                        Edge e = new Edge(v, w);
                        adj[v].Enqueue(e);
                        adj[w].Enqueue(e);
                    }
                }
            }

            // initialize stack with any non-isolated vertex
            LinkedStack <int> stack = new LinkedStack <int>();

            stack.Push(s);

            // greedily search through edges in iterative DFS style
            path = new LinkedStack <int>();
            while (!stack.IsEmpty)
            {
                int v = stack.Pop();
                while (!adj[v].IsEmpty)
                {
                    Edge edge = adj[v].Dequeue();
                    if (edge.IsUsed)
                    {
                        continue;
                    }
                    edge.IsUsed = true;
                    stack.Push(v);
                    v = edge.Other(v);
                }
                // push vertex with no more leaving edges to path
                path.Push(v);
            }

            // check if all edges are used
            if (path.Count != G.E + 1)
            {
                path = null;
            }

            Debug.Assert(certifySolution(G));
        }
Пример #12
0
        private int[] distTo;            // distTo[v] = number of edges on shortest path to v

        /// <summary>
        /// Determines a maximum matching (and a minimum vertex cover)
        /// in a bipartite graph.</summary>
        /// <param name="G">the bipartite graph</param>
        /// <exception cref="ArgumentException">if <c>G</c> is not bipartite</exception>
        ///
        public HopcroftKarp(Graph G)
        {
            bipartition = new BipartiteX(G);
            if (!bipartition.IsBipartite)
            {
                throw new ArgumentException("graph is not bipartite");
            }

            // initialize empty matching
            this.V = G.V;
            mate   = new int[V];
            for (int v = 0; v < V; v++)
            {
                mate[v] = UNMATCHED;
            }

            // the call to hasAugmentingPath() provides enough info to reconstruct level graph
            while (hasAugmentingPath(G))
            {
                // to be able to iterate over each adjacency list, keeping track of which
                // vertex in each adjacency list needs to be explored next
                IEnumerator <int>[] adj = new IEnumerator <int> [G.V];
                for (int v = 0; v < G.V; v++)
                {
                    adj[v] = G.Adj(v).GetEnumerator();
                }

                // for each unmatched vertex s on one side of bipartition
                for (int s = 0; s < V; s++)
                {
                    if (IsMatched(s) || !bipartition.Color(s))
                    {
                        continue;                                // or use distTo[s] == 0
                    }
                    // find augmenting path from s using nonrecursive DFS
                    LinkedStack <int> path = new LinkedStack <int>();
                    path.Push(s);
                    while (!path.IsEmpty)
                    {
                        int v = path.Peek();

                        // retreat, no more edges in level graph leaving v
                        if (!adj[v].MoveNext())
                        {
                            path.Pop();
                        }

                        // advance
                        else
                        {
                            // process edge v-w only if it is an edge in level graph
                            int w = adj[v].Current;
                            if (!isLevelGraphEdge(v, w))
                            {
                                continue;
                            }

                            // add w to augmenting path
                            path.Push(w);

                            // augmenting path found: update the matching
                            if (!IsMatched(w))
                            {
                                // Console.WriteLine("augmenting path: " + toString(path));

                                while (!path.IsEmpty)
                                {
                                    int x = path.Pop();
                                    int y = path.Pop();
                                    mate[x] = y;
                                    mate[y] = x;
                                }
                                cardinality++;
                            }
                        }
                    }
                }
            }

            // also find a min vertex cover
            inMinVertexCover = new bool[V];
            for (int v = 0; v < V; v++)
            {
                if (bipartition.Color(v) && !marked[v])
                {
                    inMinVertexCover[v] = true;
                }
                if (!bipartition.Color(v) && marked[v])
                {
                    inMinVertexCover[v] = true;
                }
            }

            Debug.Assert(certifySolution(G));
        }
Пример #13
0
        private LinkedStack <int> path = null; // Eulerian path; null if no suh path

        /// <summary>
        /// Computes an Eulerian path in the specified digraph, if one exists.</summary>
        /// <param name="G">the digraph</param>
        ///
        public DirectedEulerianPath(Digraph G)
        {
            // find vertex from which to start potential Eulerian path:
            // a vertex v with outdegree(v) > indegree(v) if it exits;
            // otherwise a vertex with outdegree(v) > 0
            int deficit = 0;
            int s       = nonIsolatedVertex(G);

            for (int v = 0; v < G.V; v++)
            {
                if (G.Outdegree(v) > G.Indegree(v))
                {
                    deficit += (G.Outdegree(v) - G.Indegree(v));
                    s        = v;
                }
            }

            // digraph can't have an Eulerian path
            // (this condition is needed)
            if (deficit > 1)
            {
                return;
            }

            // special case for digraph with zero edges (has a degenerate Eulerian path)
            if (s == -1)
            {
                s = 0;
            }

            // create local view of adjacency lists, to iterate one vertex at a time
            IEnumerator <int>[] adj = new IEnumerator <int> [G.V];
            for (int v = 0; v < G.V; v++)
            {
                adj[v] = G.Adj(v).GetEnumerator();
            }

            // greedily add to cycle, depth-first search style
            LinkedStack <int> stack = new LinkedStack <int>();

            stack.Push(s);
            path = new LinkedStack <int>();
            while (!stack.IsEmpty)
            {
                int v = stack.Pop();
                while (adj[v].MoveNext())
                {
                    stack.Push(v);
                    v = adj[v].Current;
                }
                // push vertex with no more available edges to path
                path.Push(v);
            }

            // check if all edges have been used
            if (path.Count != G.E + 1)
            {
                path = null;
            }

            Debug.Assert(check(G));
        }