From ef0b4664272bef276e447f3627e9fe556305e80b Mon Sep 17 00:00:00 2001 From: Mengyu Zhou Date: Wed, 8 Aug 2018 20:55:43 +0800 Subject: [PATCH 01/12] Add customized edge weight support for graphs. --- DataStructures/Graphs/CliqueGraph.cs | 10 ++-- DataStructures/Graphs/DirectedDenseGraph.cs | 6 +- DataStructures/Graphs/DirectedSparseGraph.cs | 6 +- .../Graphs/DirectedWeightedDenseGraph.cs | 42 ++++++------- .../Graphs/DirectedWeightedSparseGraph.cs | 52 ++++++++-------- DataStructures/Graphs/IEdge.cs | 6 +- DataStructures/Graphs/IGraph.cs | 13 ++-- DataStructures/Graphs/IWeightedGraph.cs | 12 ++-- DataStructures/Graphs/UndirectedDenseGraph.cs | 6 +- .../Graphs/UndirectedSparseGraph.cs | 6 +- .../Graphs/UndirectedWeightedDenseGraph.cs | 48 +++++++-------- .../Graphs/UndirectedWeightedSparseGraph.cs | 60 +++++++++---------- DataStructures/Graphs/UnweightedEdge.cs | 2 +- DataStructures/Graphs/WeightedEdge.cs | 10 ++-- 14 files changed, 142 insertions(+), 137 deletions(-) diff --git a/DataStructures/Graphs/CliqueGraph.cs b/DataStructures/Graphs/CliqueGraph.cs index 2d075564..6f7f3db3 100644 --- a/DataStructures/Graphs/CliqueGraph.cs +++ b/DataStructures/Graphs/CliqueGraph.cs @@ -255,7 +255,7 @@ ISet> getPairs(ICollection vertices) /// /// An enumerable collection of all graph edges. /// - public IEnumerable> Edges + public IEnumerable> Edges { get { @@ -273,7 +273,7 @@ public IEnumerable> Edges /// /// Get all incoming edges to vertex. /// - public IEnumerable> IncomingEdges(T vertex) + public IEnumerable> IncomingEdges(T vertex) { List> incomingEdges = new List>(); @@ -296,7 +296,7 @@ public IEnumerable> IncomingEdges(T vertex) /// /// Get all outgoing edges from a vertex. /// - public IEnumerable> OutgoingEdges(T vertex) + public IEnumerable> OutgoingEdges(T vertex) { List> outgoingEdges = new List>(); @@ -394,7 +394,7 @@ public void AddVertices(IEnumerable collection) /// Adds a list of vertices to the graph. /// /// Collection. - void IGraph.AddVertices(IList collection) + void IGraph.AddVertices(IList collection) { AddVertices(collection); } @@ -598,7 +598,7 @@ ICollection> getEdges() /// Returns the list of Vertices. /// /// The vertices. - IEnumerable IGraph.Vertices + IEnumerable IGraph.Vertices { get { diff --git a/DataStructures/Graphs/DirectedDenseGraph.cs b/DataStructures/Graphs/DirectedDenseGraph.cs index 264dff1c..caea4be0 100644 --- a/DataStructures/Graphs/DirectedDenseGraph.cs +++ b/DataStructures/Graphs/DirectedDenseGraph.cs @@ -102,17 +102,17 @@ public virtual IEnumerable Vertices } - IEnumerable> IGraph.Edges + IEnumerable> IGraph.Edges { get { return this.Edges; } } - IEnumerable> IGraph.IncomingEdges(T vertex) + IEnumerable> IGraph.IncomingEdges(T vertex) { return this.IncomingEdges(vertex); } - IEnumerable> IGraph.OutgoingEdges(T vertex) + IEnumerable> IGraph.OutgoingEdges(T vertex) { return this.OutgoingEdges(vertex); } diff --git a/DataStructures/Graphs/DirectedSparseGraph.cs b/DataStructures/Graphs/DirectedSparseGraph.cs index e8ce7df9..a55c6e88 100644 --- a/DataStructures/Graphs/DirectedSparseGraph.cs +++ b/DataStructures/Graphs/DirectedSparseGraph.cs @@ -92,17 +92,17 @@ public virtual IEnumerable Vertices } - IEnumerable> IGraph.Edges + IEnumerable> IGraph.Edges { get { return this.Edges; } } - IEnumerable> IGraph.IncomingEdges(T vertex) + IEnumerable> IGraph.IncomingEdges(T vertex) { return this.IncomingEdges(vertex); } - IEnumerable> IGraph.OutgoingEdges(T vertex) + IEnumerable> IGraph.OutgoingEdges(T vertex) { return this.OutgoingEdges(vertex); } diff --git a/DataStructures/Graphs/DirectedWeightedDenseGraph.cs b/DataStructures/Graphs/DirectedWeightedDenseGraph.cs index 68ea3c5e..521991e8 100644 --- a/DataStructures/Graphs/DirectedWeightedDenseGraph.cs +++ b/DataStructures/Graphs/DirectedWeightedDenseGraph.cs @@ -23,18 +23,18 @@ namespace DataStructures.Graphs /// /// This class represents the graph as an adjacency-matrix (two dimensional integer array). /// - public class DirectedWeightedDenseGraph : DirectedDenseGraph, IWeightedGraph where T : IComparable + public class DirectedWeightedDenseGraph : DirectedDenseGraph, IWeightedGraph where T : IComparable where W : IComparable { /// /// INSTANCE VARIABLES /// - private const long EMPTY_EDGE_SLOT = 0; + private static readonly W EMPTY_EDGE_SLOT = default(W); private const object EMPTY_VERTEX_SLOT = (object)null; // Store edges and their weights as integers. // Any edge with a value of zero means it doesn't exist. Otherwise, it exist with a specific weight value. // Default value for positive edges is 1. - protected new long[,] _adjacencyMatrix { get; set; } + protected new W[,] _adjacencyMatrix { get; set; } /// @@ -47,7 +47,7 @@ public DirectedWeightedDenseGraph(uint capacity = 10) _verticesCapacity = (int)capacity; _vertices = new ArrayList(_verticesCapacity); - _adjacencyMatrix = new long[_verticesCapacity, _verticesCapacity]; + _adjacencyMatrix = new W[_verticesCapacity, _verticesCapacity]; _adjacencyMatrix.Populate(rows: _verticesCapacity, columns: _verticesCapacity, defaultValue: EMPTY_EDGE_SLOT); } @@ -57,13 +57,13 @@ public DirectedWeightedDenseGraph(uint capacity = 10) /// protected override bool _doesEdgeExist(int source, int destination) { - return (_adjacencyMatrix[source, destination] != EMPTY_EDGE_SLOT); + return (EMPTY_EDGE_SLOT.Equals(_adjacencyMatrix[source, destination])); } /// /// Helper function. Gets the weight of a directed edge. /// - private long _getEdgeWeight(int source, int destination) + private W _getEdgeWeight(int source, int destination) { return _adjacencyMatrix[source, destination]; } @@ -80,7 +80,7 @@ public override bool IsWeighted /// /// An enumerable collection of all weighted directed edges in graph. /// - public virtual IEnumerable> Edges + public new virtual IEnumerable> Edges { get { @@ -93,7 +93,7 @@ public virtual IEnumerable> Edges /// /// Get all incoming unweighted edges to a vertex. /// - public virtual IEnumerable> IncomingEdges(T vertex) + public new virtual IEnumerable> IncomingEdges(T vertex) { if (!HasVertex(vertex)) throw new KeyNotFoundException("Vertex doesn't belong to graph."); @@ -104,7 +104,7 @@ public virtual IEnumerable> IncomingEdges(T vertex) { if (_vertices[adjacent] != null && _doesEdgeExist(adjacent, source)) { - yield return (new WeightedEdge( + yield return (new WeightedEdge( (T)_vertices[adjacent], // from vertex, // to _getEdgeWeight(source, adjacent) // weight @@ -116,7 +116,7 @@ public virtual IEnumerable> IncomingEdges(T vertex) /// /// Get all outgoing unweighted edges from a vertex. /// - public virtual IEnumerable> OutgoingEdges(T vertex) + public new virtual IEnumerable> OutgoingEdges(T vertex) { if (!HasVertex(vertex)) throw new KeyNotFoundException("Vertex doesn't belong to graph."); @@ -127,7 +127,7 @@ public virtual IEnumerable> OutgoingEdges(T vertex) { if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) { - yield return (new WeightedEdge( + yield return (new WeightedEdge( vertex, // from (T)_vertices[adjacent], // to _getEdgeWeight(source, adjacent) // weight @@ -149,10 +149,10 @@ public virtual IEnumerable> OutgoingEdges(T vertex) /// /// Connects two vertices together with a weight, in the direction: first->second. /// - public virtual bool AddEdge(T source, T destination, long weight) + public virtual bool AddEdge(T source, T destination, W weight) { // Return if the weight is equals to the empty edge value - if (weight == EMPTY_EDGE_SLOT) + if (EMPTY_EDGE_SLOT.Equals(weight)) return false; // Get indices of vertices @@ -199,10 +199,10 @@ public override bool RemoveEdge(T source, T destination) /// /// Updates the edge weight from source to destination. /// - public virtual bool UpdateEdgeWeight(T source, T destination, long weight) + public virtual bool UpdateEdgeWeight(T source, T destination, W weight) { // Return if the weight is equals to the empty edge value - if (weight == EMPTY_EDGE_SLOT) + if (EMPTY_EDGE_SLOT.Equals(weight)) return false; // Get indices of vertices @@ -271,7 +271,7 @@ public override bool RemoveVertex(T vertex) /// /// Get edge object from source to destination. /// - public virtual WeightedEdge GetEdge(T source, T destination) + public virtual WeightedEdge GetEdge(T source, T destination) { // Get indices of vertices int srcIndex = _vertices.IndexOf(source); @@ -283,13 +283,13 @@ public virtual WeightedEdge GetEdge(T source, T destination) if (!_doesEdgeExist(srcIndex, dstIndex)) throw new Exception("Edge doesn't exist."); - return (new WeightedEdge(source, destination, _getEdgeWeight(srcIndex, dstIndex))); + return (new WeightedEdge(source, destination, _getEdgeWeight(srcIndex, dstIndex))); } /// /// Returns the edge weight from source to destination. /// - public virtual long GetEdgeWeight(T source, T destination) + public virtual W GetEdgeWeight(T source, T destination) { return GetEdge(source, destination).Weight; } @@ -297,12 +297,12 @@ public virtual long GetEdgeWeight(T source, T destination) /// /// Returns the neighbours of a vertex as a dictionary of nodes-to-weights. /// - public virtual Dictionary NeighboursMap(T vertex) + public virtual Dictionary NeighboursMap(T vertex) { if (!HasVertex(vertex)) return null; - var neighbors = new Dictionary(); + var neighbors = new Dictionary(); int source = _vertices.IndexOf(vertex); // Check existence of vertex @@ -351,7 +351,7 @@ public override void Clear() _edgesCount = 0; _verticesCount = 0; _vertices = new ArrayList(_verticesCapacity); - _adjacencyMatrix = new long[_verticesCapacity, _verticesCapacity]; + _adjacencyMatrix = new W[_verticesCapacity, _verticesCapacity]; _adjacencyMatrix.Populate(rows: _verticesCapacity, columns: _verticesCapacity, defaultValue: EMPTY_EDGE_SLOT); } diff --git a/DataStructures/Graphs/DirectedWeightedSparseGraph.cs b/DataStructures/Graphs/DirectedWeightedSparseGraph.cs index 66c0ccfe..5c72cd9d 100644 --- a/DataStructures/Graphs/DirectedWeightedSparseGraph.cs +++ b/DataStructures/Graphs/DirectedWeightedSparseGraph.cs @@ -18,15 +18,15 @@ namespace DataStructures.Graphs { - public class DirectedWeightedSparseGraph : IGraph, IWeightedGraph where T : IComparable + public class DirectedWeightedSparseGraph : IGraph, IWeightedGraph where T : IComparable where W : IComparable { /// /// INSTANCE VARIABLES /// - private const long EMPTY_EDGE_VALUE = 0; + private static readonly W EMPTY_EDGE_VALUE = default(W); protected virtual int _edgesCount { get; set; } protected virtual T _firstInsertedNode { get; set; } - protected virtual Dictionary>> _adjacencyList { get; set; } + protected virtual Dictionary>> _adjacencyList { get; set; } /// @@ -37,19 +37,19 @@ public DirectedWeightedSparseGraph() : this(10) { } public DirectedWeightedSparseGraph(uint initialCapacity) { _edgesCount = 0; - _adjacencyList = new Dictionary>>((int)initialCapacity); + _adjacencyList = new Dictionary>>((int)initialCapacity); } /// /// Helper function. Returns edge object from source to destination, if exists; otherwise, null. /// - protected virtual WeightedEdge _tryGetEdge(T source, T destination) + protected virtual WeightedEdge _tryGetEdge(T source, T destination) { - WeightedEdge edge = null; + WeightedEdge edge = null; // Predicate - var sourceToDestinationPredicate = new Predicate>((item) => item.Source.IsEqualTo(source) && item.Destination.IsEqualTo(destination)); + var sourceToDestinationPredicate = new Predicate>((item) => item.Source.IsEqualTo(source) && item.Destination.IsEqualTo(destination)); // Try to find a match if(_adjacencyList.ContainsKey(source)) @@ -72,7 +72,7 @@ protected virtual bool _doesEdgeExist(T source, T destination) /// Helper function. Gets the weight of a directed edge. /// Presumes edge does already exist. /// - private long _getEdgeWeight(T source, T destination) + private W _getEdgeWeight(T source, T destination) { return _tryGetEdge(source, destination).Weight; } @@ -123,17 +123,17 @@ public IEnumerable Vertices } - IEnumerable> IGraph.Edges + IEnumerable> IGraph.Edges { get { return this.Edges; } } - IEnumerable> IGraph.IncomingEdges(T vertex) + IEnumerable> IGraph.IncomingEdges(T vertex) { return this.IncomingEdges(vertex); } - IEnumerable> IGraph.OutgoingEdges(T vertex) + IEnumerable> IGraph.OutgoingEdges(T vertex) { return this.OutgoingEdges(vertex); } @@ -142,7 +142,7 @@ IEnumerable> IGraph.OutgoingEdges(T vertex) /// /// An enumerable collection of all directed weighted edges in graph. /// - public virtual IEnumerable> Edges + public virtual IEnumerable> Edges { get { @@ -155,16 +155,16 @@ public virtual IEnumerable> Edges /// /// Get all incoming directed weighted edges to a vertex. /// - public virtual IEnumerable> IncomingEdges(T vertex) + public virtual IEnumerable> IncomingEdges(T vertex) { if (!HasVertex(vertex)) throw new KeyNotFoundException("Vertex doesn't belong to graph."); - var predicate = new Predicate>((edge) => edge.Destination.IsEqualTo(vertex)); + var predicate = new Predicate>((edge) => edge.Destination.IsEqualTo(vertex)); foreach(var adjacent in _adjacencyList.Keys) { - WeightedEdge incomingEdge = null; + WeightedEdge incomingEdge = null; if (_adjacencyList[adjacent].TryFindFirst(predicate, out incomingEdge)) yield return incomingEdge; @@ -174,7 +174,7 @@ public virtual IEnumerable> IncomingEdges(T vertex) /// /// Get all outgoing directed weighted edges from a vertex. /// - public virtual IEnumerable> OutgoingEdges(T vertex) + public virtual IEnumerable> OutgoingEdges(T vertex) { if (!HasVertex(vertex)) throw new KeyNotFoundException("Vertex doesn't belong to graph."); @@ -196,10 +196,10 @@ public bool AddEdge(T source, T destination) /// /// Connects two vertices together with a weight, in the direction: first->second. /// - public bool AddEdge(T source, T destination, long weight) + public bool AddEdge(T source, T destination, W weight) { // Check existence of nodes, the validity of the weight value, and the non-existence of edge - if (weight == EMPTY_EDGE_VALUE) + if (EMPTY_EDGE_VALUE.Equals(weight)) return false; if (!HasVertex(source) || !HasVertex(destination)) return false; @@ -207,7 +207,7 @@ public bool AddEdge(T source, T destination, long weight) return false; // Add edge from source to destination - var edge = new WeightedEdge(source, destination, weight); + var edge = new WeightedEdge(source, destination, weight); _adjacencyList[source].Append(edge); // Increment edges count @@ -241,10 +241,10 @@ public virtual bool RemoveEdge(T source, T destination) return true; } - public bool UpdateEdgeWeight(T source, T destination, long weight) + public bool UpdateEdgeWeight(T source, T destination, W weight) { // Check existence of vertices and validity of the weight value - if (weight == EMPTY_EDGE_VALUE) + if (EMPTY_EDGE_VALUE.Equals(weight)) return false; if (!HasVertex(source) || !HasVertex(destination)) return false; @@ -264,7 +264,7 @@ public bool UpdateEdgeWeight(T source, T destination, long weight) /// /// Get edge object from source to destination. /// - public virtual WeightedEdge GetEdge(T source, T destination) + public virtual WeightedEdge GetEdge(T source, T destination) { if (!HasVertex(source) || !HasVertex(destination)) throw new KeyNotFoundException("Either one of the vertices or both of them don't exist."); @@ -282,7 +282,7 @@ public virtual WeightedEdge GetEdge(T source, T destination) /// /// Returns the edge weight from source to destination. /// - public virtual long GetEdgeWeight(T source, T destination) + public virtual W GetEdgeWeight(T source, T destination) { return GetEdge(source, destination).Weight; } @@ -310,7 +310,7 @@ public virtual bool AddVertex(T vertex) if (_adjacencyList.Count == 0) _firstInsertedNode = vertex; - _adjacencyList.Add(vertex, new DLinkedList>()); + _adjacencyList.Add(vertex, new DLinkedList>()); return true; } @@ -383,13 +383,13 @@ public virtual DLinkedList Neighbours(T vertex) /// /// Returns the neighbours of a vertex as a dictionary of nodes-to-weights. /// - public Dictionary NeighboursMap(T vertex) + public Dictionary NeighboursMap(T vertex) { if (!HasVertex(vertex)) return null; var neighbors = _adjacencyList[vertex]; - var map = new Dictionary(neighbors.Count); + var map = new Dictionary(neighbors.Count); foreach (var adjacent in neighbors) map.Add(adjacent.Destination, adjacent.Weight); diff --git a/DataStructures/Graphs/IEdge.cs b/DataStructures/Graphs/IEdge.cs index 35371119..ad9bb615 100644 --- a/DataStructures/Graphs/IEdge.cs +++ b/DataStructures/Graphs/IEdge.cs @@ -5,7 +5,7 @@ namespace DataStructures.Graphs /// /// This interface should be implemented by all edges classes. /// - public interface IEdge : IComparable> where TVertex : IComparable + public interface IEdge : IComparable> where TVertex : IComparable { /// /// Gets a value indicating whether this edge is weighted. @@ -30,7 +30,9 @@ public interface IEdge : IComparable> where TVertex : IC /// Unwighted edges can be thought of as edges of the same weight /// /// The weight. - Int64 Weight { get; set; } + TWeight Weight { get; set; } } + + public interface IEdge : IEdge where TVertex : IComparable { } } diff --git a/DataStructures/Graphs/IGraph.cs b/DataStructures/Graphs/IGraph.cs index 1ae595cc..aba12999 100644 --- a/DataStructures/Graphs/IGraph.cs +++ b/DataStructures/Graphs/IGraph.cs @@ -1,11 +1,11 @@ using System; using System.Collections.Generic; - using DataStructures.Lists; +using System.Linq; namespace DataStructures.Graphs { - public interface IGraph where T : IComparable + public interface IGraph where T : IComparable { /// /// Returns true, if graph is directed; false otherwise. @@ -35,17 +35,17 @@ public interface IGraph where T : IComparable /// /// An enumerable collection of edges. /// - IEnumerable> Edges { get; } + IEnumerable> Edges { get; } /// /// Get all incoming edges from vertex /// - IEnumerable> IncomingEdges(T vertex); + IEnumerable> IncomingEdges(T vertex); /// /// Get all outgoing edges from vertex /// - IEnumerable> OutgoingEdges(T vertex); + IEnumerable> OutgoingEdges(T vertex); /// /// Connects two vertices together. @@ -124,5 +124,6 @@ public interface IGraph where T : IComparable /// void Clear(); } -} + public interface IGraph : IGraph where T : IComparable { } +} diff --git a/DataStructures/Graphs/IWeightedGraph.cs b/DataStructures/Graphs/IWeightedGraph.cs index 66f3a857..c994edb4 100644 --- a/DataStructures/Graphs/IWeightedGraph.cs +++ b/DataStructures/Graphs/IWeightedGraph.cs @@ -5,32 +5,32 @@ namespace DataStructures.Graphs /// /// This interface should be implemented alongside the IGraph interface. /// - public interface IWeightedGraph where T : IComparable + public interface IWeightedGraph where T : IComparable where W : IComparable { /// /// Connects two vertices together with a weight, in the direction: first->second. /// - bool AddEdge(T source, T destination, long weight); + bool AddEdge(T source, T destination, W weight); /// /// Updates the edge weight from source to destination. /// - bool UpdateEdgeWeight(T source, T destination, long weight); + bool UpdateEdgeWeight(T source, T destination, W weight); /// /// Get edge object from source to destination. /// - WeightedEdge GetEdge(T source, T destination); + WeightedEdge GetEdge(T source, T destination); /// /// Returns the edge weight from source to destination. /// - long GetEdgeWeight(T source, T destination); + W GetEdgeWeight(T source, T destination); /// /// Returns the neighbours of a vertex as a dictionary of nodes-to-weights. /// - System.Collections.Generic.Dictionary NeighboursMap(T vertex); + System.Collections.Generic.Dictionary NeighboursMap(T vertex); } } diff --git a/DataStructures/Graphs/UndirectedDenseGraph.cs b/DataStructures/Graphs/UndirectedDenseGraph.cs index f6526541..55f7d212 100644 --- a/DataStructures/Graphs/UndirectedDenseGraph.cs +++ b/DataStructures/Graphs/UndirectedDenseGraph.cs @@ -108,17 +108,17 @@ public virtual IEnumerable Vertices } - IEnumerable> IGraph.Edges + IEnumerable> IGraph.Edges { get { return this.Edges; } } - IEnumerable> IGraph.IncomingEdges(T vertex) + IEnumerable> IGraph.IncomingEdges(T vertex) { return this.IncomingEdges(vertex); } - IEnumerable> IGraph.OutgoingEdges(T vertex) + IEnumerable> IGraph.OutgoingEdges(T vertex) { return this.OutgoingEdges(vertex); } diff --git a/DataStructures/Graphs/UndirectedSparseGraph.cs b/DataStructures/Graphs/UndirectedSparseGraph.cs index 3593c0ec..06a50d9b 100644 --- a/DataStructures/Graphs/UndirectedSparseGraph.cs +++ b/DataStructures/Graphs/UndirectedSparseGraph.cs @@ -93,17 +93,17 @@ public virtual IEnumerable Vertices } - IEnumerable> IGraph.Edges + IEnumerable> IGraph.Edges { get { return this.Edges; } } - IEnumerable> IGraph.IncomingEdges(T vertex) + IEnumerable> IGraph.IncomingEdges(T vertex) { return this.IncomingEdges(vertex); } - IEnumerable> IGraph.OutgoingEdges(T vertex) + IEnumerable> IGraph.OutgoingEdges(T vertex) { return this.OutgoingEdges(vertex); } diff --git a/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs b/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs index c26094ca..d3f6fb16 100644 --- a/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs +++ b/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs @@ -21,18 +21,18 @@ namespace DataStructures.Graphs /// /// This class represents the graph as an adjacency-matrix (two dimensional integer array). /// - public class UndirectedWeightedDenseGraph : UndirectedDenseGraph, IWeightedGraph where T : IComparable + public class UndirectedWeightedDenseGraph : UndirectedDenseGraph, IWeightedGraph where T : IComparable where W : IComparable { /// /// INSTANCE VARIABLES /// - private const long EMPTY_EDGE_SLOT = 0; + private static readonly W EMPTY_EDGE_SLOT = default(W); private const object EMPTY_VERTEX_SLOT = (object)null; // Store edges and their weights as integers. // Any edge with a value of zero means it doesn't exist. Otherwise, it exist with a specific weight value. // Default value for positive edges is 1. - protected new long[,] _adjacencyMatrix { get; set; } + protected new W[,] _adjacencyMatrix { get; set; } /// @@ -45,7 +45,7 @@ public UndirectedWeightedDenseGraph(uint capacity = 10) _verticesCapacity = (int)capacity; _vertices = new ArrayList(_verticesCapacity); - _adjacencyMatrix = new long[_verticesCapacity, _verticesCapacity]; + _adjacencyMatrix = new W[_verticesCapacity, _verticesCapacity]; _adjacencyMatrix.Populate(rows: _verticesCapacity, columns: _verticesCapacity, defaultValue: EMPTY_EDGE_SLOT); } @@ -55,15 +55,15 @@ public UndirectedWeightedDenseGraph(uint capacity = 10) /// protected override bool _doesEdgeExist(int source, int destination) { - return (_adjacencyMatrix[source, destination] != EMPTY_EDGE_SLOT) || (_adjacencyMatrix[destination, source] != EMPTY_EDGE_SLOT); + return (!EMPTY_EDGE_SLOT.Equals(_adjacencyMatrix[source, destination])) || (!EMPTY_EDGE_SLOT.Equals(_adjacencyMatrix[destination, source])); } /// /// Helper function. Gets the weight of a undirected edge. /// - private long _getEdgeWeight(int source, int destination) + private W _getEdgeWeight(int source, int destination) { - return (_adjacencyMatrix[source, destination] != EMPTY_EDGE_SLOT ? _adjacencyMatrix[source, destination] : _adjacencyMatrix[destination, source]); + return (!EMPTY_EDGE_SLOT.Equals(_adjacencyMatrix[source, destination]) ? _adjacencyMatrix[source, destination] : _adjacencyMatrix[destination, source]); } @@ -78,7 +78,7 @@ public override bool IsWeighted /// /// An enumerable collection of edges. /// - public virtual IEnumerable> Edges + public new virtual IEnumerable> Edges { get { @@ -104,7 +104,7 @@ public virtual IEnumerable> Edges continue; seen.Add(outgoingEdge); - yield return (new WeightedEdge(outgoingEdge.Key, outgoingEdge.Value, weight)); + yield return (new WeightedEdge(outgoingEdge.Key, outgoingEdge.Value, weight)); } } }//end-foreach @@ -114,7 +114,7 @@ public virtual IEnumerable> Edges /// /// Get all incoming edges to a vertex /// - public virtual IEnumerable> IncomingEdges(T vertex) + public new virtual IEnumerable> IncomingEdges(T vertex) { if (!HasVertex(vertex)) throw new KeyNotFoundException("Vertex doesn't belong to graph."); @@ -125,7 +125,7 @@ public virtual IEnumerable> IncomingEdges(T vertex) { if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) { - yield return (new WeightedEdge( + yield return (new WeightedEdge( (T)_vertices[adjacent], // from vertex, // to _getEdgeWeight(source, adjacent) // weight @@ -137,7 +137,7 @@ public virtual IEnumerable> IncomingEdges(T vertex) /// /// Get all outgoing weighted edges from vertex /// - public virtual IEnumerable> OutgoingEdges(T vertex) + public new virtual IEnumerable> OutgoingEdges(T vertex) { if (!HasVertex(vertex)) throw new KeyNotFoundException("Vertex doesn't belong to graph."); @@ -148,7 +148,7 @@ public virtual IEnumerable> OutgoingEdges(T vertex) { if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) { - yield return (new WeightedEdge( + yield return (new WeightedEdge( vertex, // from (T)_vertices[adjacent], // to _getEdgeWeight(source, adjacent) // weight @@ -170,10 +170,10 @@ public virtual IEnumerable> OutgoingEdges(T vertex) /// /// Connects two vertices together with a weight, in the direction: first->second. /// - public virtual bool AddEdge(T source, T destination, long weight) + public virtual bool AddEdge(T source, T destination, W weight) { // Return if the weight is equals to the empty edge value - if (weight == EMPTY_EDGE_SLOT) + if (EMPTY_EDGE_SLOT.Equals(weight)) return false; // Get indices of vertices @@ -223,10 +223,10 @@ public override bool RemoveEdge(T source, T destination) /// /// Updates the edge weight from source to destination. /// - public virtual bool UpdateEdgeWeight(T source, T destination, long weight) + public virtual bool UpdateEdgeWeight(T source, T destination, W weight) { // Return if the weight is equals to the empty edge value - if (weight == EMPTY_EDGE_SLOT) + if (EMPTY_EDGE_SLOT.Equals(weight)) return false; // Get indices of vertices @@ -240,7 +240,7 @@ public virtual bool UpdateEdgeWeight(T source, T destination, long weight) return false; // Edge exists, use only one triangle of the matrix - if (_adjacencyMatrix[srcIndex, dstIndex] != EMPTY_EDGE_SLOT) + if (!EMPTY_EDGE_SLOT.Equals(_adjacencyMatrix[srcIndex, dstIndex])) _adjacencyMatrix[srcIndex, dstIndex] = weight; else _adjacencyMatrix[dstIndex, srcIndex] = weight; @@ -290,7 +290,7 @@ public override bool RemoveVertex(T vertex) /// /// Get edge object from source to destination. /// - public virtual WeightedEdge GetEdge(T source, T destination) + public virtual WeightedEdge GetEdge(T source, T destination) { // Get indices of vertices int srcIndex = _vertices.IndexOf(source); @@ -302,13 +302,13 @@ public virtual WeightedEdge GetEdge(T source, T destination) if (!_doesEdgeExist(srcIndex, dstIndex)) throw new Exception("Edge doesn't exist."); - return (new WeightedEdge(source, destination, _getEdgeWeight(srcIndex, dstIndex))); + return (new WeightedEdge(source, destination, _getEdgeWeight(srcIndex, dstIndex))); } /// /// Returns the edge weight from source to destination. /// - public virtual long GetEdgeWeight(T source, T destination) + public virtual W GetEdgeWeight(T source, T destination) { return GetEdge(source, destination).Weight; } @@ -316,12 +316,12 @@ public virtual long GetEdgeWeight(T source, T destination) /// /// Returns the neighbours of a vertex as a dictionary of nodes-to-weights. /// - public virtual Dictionary NeighboursMap(T vertex) + public virtual Dictionary NeighboursMap(T vertex) { if (!HasVertex(vertex)) return null; - var neighbors = new Dictionary(); + var neighbors = new Dictionary(); int source = _vertices.IndexOf(vertex); // Check existence of vertex @@ -370,7 +370,7 @@ public override void Clear() _edgesCount = 0; _verticesCount = 0; _vertices = new ArrayList(_verticesCapacity); - _adjacencyMatrix = new long[_verticesCapacity, _verticesCapacity]; + _adjacencyMatrix = new W[_verticesCapacity, _verticesCapacity]; _adjacencyMatrix.Populate(rows: _verticesCapacity, columns: _verticesCapacity, defaultValue: EMPTY_EDGE_SLOT); } } diff --git a/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs b/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs index 20859241..2901442d 100644 --- a/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs +++ b/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs @@ -17,15 +17,15 @@ namespace DataStructures.Graphs { - public class UndirectedWeightedSparseGraph : IGraph, IWeightedGraph where T : IComparable + public class UndirectedWeightedSparseGraph : IGraph, IWeightedGraph where T : IComparable where W : IComparable { /// /// INSTANCE VARIABLES /// - private const long EMPTY_EDGE_VALUE = 0; + private static readonly W EMPTY_EDGE_VALUE = default(W); protected virtual int _edgesCount { get; set; } protected virtual T _firstInsertedNode { get; set; } - protected virtual Dictionary>> _adjacencyList { get; set; } + protected virtual Dictionary>> _adjacencyList { get; set; } /// @@ -36,20 +36,20 @@ public UndirectedWeightedSparseGraph() : this(10) { } public UndirectedWeightedSparseGraph(uint initialCapacity) { _edgesCount = 0; - _adjacencyList = new Dictionary>>((int)initialCapacity); + _adjacencyList = new Dictionary>>((int)initialCapacity); } /// /// Helper function. Returns edge object from source to destination, if exists; otherwise, null. /// - protected virtual WeightedEdge _tryGetEdge(T source, T destination) + protected virtual WeightedEdge _tryGetEdge(T source, T destination) { var success = false; - WeightedEdge edge = null; + WeightedEdge edge = null; - var sourceToDestinationPredicate = new Predicate>((item) => item.Source.IsEqualTo(source) && item.Destination.IsEqualTo(destination)); - var destinationToSourcePredicate = new Predicate>((item) => item.Source.IsEqualTo(destination) && item.Destination.IsEqualTo(source)); + var sourceToDestinationPredicate = new Predicate>((item) => item.Source.IsEqualTo(source) && item.Destination.IsEqualTo(destination)); + var destinationToSourcePredicate = new Predicate>((item) => item.Source.IsEqualTo(destination) && item.Destination.IsEqualTo(source)); if(_adjacencyList.ContainsKey(source)) success = _adjacencyList[source].TryFindFirst(sourceToDestinationPredicate, out edge); @@ -73,7 +73,7 @@ protected virtual bool _doesEdgeExist(T source, T destination) /// Helper function. Gets the weight of a undirected edge. /// Presumes edge does already exist. /// - private long _getEdgeWeight(T source, T destination) + private W _getEdgeWeight(T source, T destination) { return _tryGetEdge(source, destination).Weight; } @@ -124,17 +124,17 @@ public IEnumerable Vertices } - IEnumerable> IGraph.Edges + IEnumerable> IGraph.Edges { get { return this.Edges; } } - IEnumerable> IGraph.IncomingEdges(T vertex) + IEnumerable> IGraph.IncomingEdges(T vertex) { return this.IncomingEdges(vertex); } - IEnumerable> IGraph.OutgoingEdges(T vertex) + IEnumerable> IGraph.OutgoingEdges(T vertex) { return this.OutgoingEdges(vertex); } @@ -143,7 +143,7 @@ IEnumerable> IGraph.OutgoingEdges(T vertex) /// /// An enumerable collection of all weighted edges in Graph. /// - public virtual IEnumerable> Edges + public virtual IEnumerable> Edges { get { @@ -169,19 +169,19 @@ public virtual IEnumerable> Edges /// /// Get all incoming weighted edges to a vertex /// - public virtual IEnumerable> IncomingEdges(T vertex) + public virtual IEnumerable> IncomingEdges(T vertex) { if (!HasVertex(vertex)) throw new KeyNotFoundException("Vertex doesn't belong to graph."); foreach(var edge in _adjacencyList[vertex]) - yield return (new WeightedEdge(edge.Destination, edge.Source, edge.Weight)); + yield return (new WeightedEdge(edge.Destination, edge.Source, edge.Weight)); } /// /// Get all outgoing weighted edges from a vertex. /// - public virtual IEnumerable> OutgoingEdges(T vertex) + public virtual IEnumerable> OutgoingEdges(T vertex) { if (!HasVertex(vertex)) throw new KeyNotFoundException("Vertex doesn't belong to graph."); @@ -203,10 +203,10 @@ public bool AddEdge(T source, T destination) /// /// Connects two vertices together with a weight, in the direction: first->second. /// - public bool AddEdge(T source, T destination, long weight) + public bool AddEdge(T source, T destination, W weight) { // Check existence of nodes, the validity of the weight value, and the non-existence of edge - if (weight == EMPTY_EDGE_VALUE) + if (EMPTY_EDGE_VALUE.Equals(weight)) return false; if (!HasVertex(source) || !HasVertex(destination)) return false; @@ -214,8 +214,8 @@ public bool AddEdge(T source, T destination, long weight) return false; // Add edge from source to destination - var sourceDdge = new WeightedEdge(source, destination, weight); - var destinationEdge = new WeightedEdge(destination, source, weight); + var sourceDdge = new WeightedEdge(source, destination, weight); + var destinationEdge = new WeightedEdge(destination, source, weight); _adjacencyList[source].Append(sourceDdge); _adjacencyList[destination].Append(destinationEdge); @@ -235,12 +235,12 @@ public virtual bool RemoveEdge(T source, T destination) if (!HasVertex(source) || !HasVertex(destination)) return false; - WeightedEdge edge1, edge2; + WeightedEdge edge1, edge2; - var sourceToDestinationPredicate = new Predicate>((item) => item.Source.IsEqualTo(source) && item.Destination.IsEqualTo(destination)); + var sourceToDestinationPredicate = new Predicate>((item) => item.Source.IsEqualTo(source) && item.Destination.IsEqualTo(destination)); _adjacencyList[source].TryFindFirst(sourceToDestinationPredicate, out edge1); - var destinationToSourcePredicate = new Predicate>((item) => item.Source.IsEqualTo(destination) && item.Destination.IsEqualTo(source)); + var destinationToSourcePredicate = new Predicate>((item) => item.Source.IsEqualTo(destination) && item.Destination.IsEqualTo(source)); _adjacencyList[destination].TryFindFirst(destinationToSourcePredicate, out edge2); // If edge doesn't exist, return false @@ -261,10 +261,10 @@ public virtual bool RemoveEdge(T source, T destination) return true; } - public bool UpdateEdgeWeight(T source, T destination, long weight) + public bool UpdateEdgeWeight(T source, T destination, W weight) { // Check existence of vertices and validity of the weight value - if (weight == EMPTY_EDGE_VALUE) + if (EMPTY_EDGE_VALUE.Equals(weight)) return false; if (!HasVertex(source) || !HasVertex(destination)) return false; @@ -300,7 +300,7 @@ public bool UpdateEdgeWeight(T source, T destination, long weight) /// /// Get edge object from source to destination. /// - public virtual WeightedEdge GetEdge(T source, T destination) + public virtual WeightedEdge GetEdge(T source, T destination) { if (!HasVertex(source) || !HasVertex(destination)) throw new KeyNotFoundException("Either one of the vertices or both of them don't exist."); @@ -318,7 +318,7 @@ public virtual WeightedEdge GetEdge(T source, T destination) /// /// Returns the edge weight from source to destination. /// - public virtual long GetEdgeWeight(T source, T destination) + public virtual W GetEdgeWeight(T source, T destination) { return GetEdge(source, destination).Weight; } @@ -346,7 +346,7 @@ public virtual bool AddVertex(T vertex) if (_adjacencyList.Count == 0) _firstInsertedNode = vertex; - _adjacencyList.Add(vertex, new DLinkedList>()); + _adjacencyList.Add(vertex, new DLinkedList>()); return true; } @@ -414,13 +414,13 @@ public virtual DLinkedList Neighbours(T vertex) /// /// Returns the neighbours of a vertex as a dictionary of nodes-to-weights. /// - public Dictionary NeighboursMap(T vertex) + public Dictionary NeighboursMap(T vertex) { if (!HasVertex(vertex)) return null; var neighbors = _adjacencyList[vertex]; - var map = new Dictionary(neighbors.Count); + var map = new Dictionary(neighbors.Count); foreach (var adjacent in neighbors) map.Add(adjacent.Destination, adjacent.Weight); diff --git a/DataStructures/Graphs/UnweightedEdge.cs b/DataStructures/Graphs/UnweightedEdge.cs index 8bffc61f..123026b4 100644 --- a/DataStructures/Graphs/UnweightedEdge.cs +++ b/DataStructures/Graphs/UnweightedEdge.cs @@ -53,7 +53,7 @@ public UnweightedEdge(TVertex src, TVertex dst) #region IComparable implementation - public int CompareTo(IEdge other) + public int CompareTo(IEdge other) { if (other == null) return -1; diff --git a/DataStructures/Graphs/WeightedEdge.cs b/DataStructures/Graphs/WeightedEdge.cs index 8c2979bd..c20040a8 100644 --- a/DataStructures/Graphs/WeightedEdge.cs +++ b/DataStructures/Graphs/WeightedEdge.cs @@ -7,7 +7,9 @@ namespace DataStructures.Graphs /// /// The graph weighted edge class. /// - public class WeightedEdge : IEdge where TVertex : IComparable + public class WeightedEdge : IEdge + where TVertex : IComparable + where TWeight : IComparable { /// /// Gets or sets the source. @@ -25,7 +27,7 @@ public class WeightedEdge : IEdge where TVertex : IComparable< /// Gets or sets the weight of edge. /// /// The weight. - public Int64 Weight { get; set; } + public TWeight Weight { get; set; } /// /// Gets a value indicating whether this edge is weighted. @@ -39,7 +41,7 @@ public bool IsWeighted /// /// CONSTRUCTOR /// - public WeightedEdge(TVertex src, TVertex dst, Int64 weight) + public WeightedEdge(TVertex src, TVertex dst, TWeight weight) { Source = src; Destination = dst; @@ -48,7 +50,7 @@ public WeightedEdge(TVertex src, TVertex dst, Int64 weight) #region IComparable implementation - public int CompareTo(IEdge other) + public int CompareTo(IEdge other) { if (other == null) return -1; From 9ab1535130531cd702636e62fa004b5922439ec1 Mon Sep 17 00:00:00 2001 From: Mengyu Zhou Date: Wed, 8 Aug 2018 21:06:55 +0800 Subject: [PATCH 02/12] Add default weight type for IWeightedGraph. --- DataStructures/Graphs/IWeightedGraph.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DataStructures/Graphs/IWeightedGraph.cs b/DataStructures/Graphs/IWeightedGraph.cs index c994edb4..1f62d649 100644 --- a/DataStructures/Graphs/IWeightedGraph.cs +++ b/DataStructures/Graphs/IWeightedGraph.cs @@ -32,5 +32,7 @@ public interface IWeightedGraph where T : IComparable where W : ICompar /// System.Collections.Generic.Dictionary NeighboursMap(T vertex); } + + public interface IWeightedGraph : IWeightedGraph where T : IComparable { } } From b03600b0939d26aba445596c3469705a661fbd7d Mon Sep 17 00:00:00 2001 From: Mengyu Zhou Date: Thu, 9 Aug 2018 14:20:05 +0800 Subject: [PATCH 03/12] Add default WeightedEdge with long weights. --- DataStructures/Graphs/WeightedEdge.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/DataStructures/Graphs/WeightedEdge.cs b/DataStructures/Graphs/WeightedEdge.cs index c20040a8..c972d386 100644 --- a/DataStructures/Graphs/WeightedEdge.cs +++ b/DataStructures/Graphs/WeightedEdge.cs @@ -63,4 +63,11 @@ public int CompareTo(IEdge other) } #endregion } + + public class WeightedEdge : WeightedEdge where TVertex : IComparable + { + public WeightedEdge(TVertex src, TVertex dst, long weight) : base(src, dst, weight) + { + } + } } From c358a40e0f261371ee33de516aac101ed01e9542 Mon Sep 17 00:00:00 2001 From: Mengyu Zhou Date: Thu, 9 Aug 2018 14:30:56 +0800 Subject: [PATCH 04/12] Add default weight type for all weighted graph classes. --- DataStructures/Graphs/DirectedWeightedDenseGraph.cs | 2 +- DataStructures/Graphs/DirectedWeightedSparseGraph.cs | 1 + DataStructures/Graphs/UndirectedWeightedDenseGraph.cs | 1 + DataStructures/Graphs/UndirectedWeightedSparseGraph.cs | 2 ++ 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/DataStructures/Graphs/DirectedWeightedDenseGraph.cs b/DataStructures/Graphs/DirectedWeightedDenseGraph.cs index 521991e8..1d190781 100644 --- a/DataStructures/Graphs/DirectedWeightedDenseGraph.cs +++ b/DataStructures/Graphs/DirectedWeightedDenseGraph.cs @@ -357,5 +357,5 @@ public override void Clear() } + public class DirectedWeightedDenseGraph : DirectedWeightedDenseGraph where T : IComparable { } } - diff --git a/DataStructures/Graphs/DirectedWeightedSparseGraph.cs b/DataStructures/Graphs/DirectedWeightedSparseGraph.cs index 5c72cd9d..72f690b2 100644 --- a/DataStructures/Graphs/DirectedWeightedSparseGraph.cs +++ b/DataStructures/Graphs/DirectedWeightedSparseGraph.cs @@ -538,4 +538,5 @@ public virtual void Clear() } + public class DirectedWeightedSparseGraph : DirectedWeightedSparseGraph where T : IComparable { } } diff --git a/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs b/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs index d3f6fb16..c9f43eb4 100644 --- a/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs +++ b/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs @@ -375,4 +375,5 @@ public override void Clear() } } + public class UndirectedWeightedDenseGraph : UndirectedWeightedDenseGraph where T : IComparable { } } diff --git a/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs b/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs index 2901442d..cf86d93f 100644 --- a/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs +++ b/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs @@ -568,4 +568,6 @@ public virtual void Clear() } } + + public class UndirectedWeightedSparseGraph : UndirectedWeightedSparseGraph where T : IComparable { } } From 1c08ff2c509c1efbd63248f7ab5008ae2fa43b4e Mon Sep 17 00:00:00 2001 From: Mengyu Zhou Date: Mon, 20 Aug 2018 20:17:37 +0800 Subject: [PATCH 05/12] Fix unit tests. --- DataStructures/Graphs/DirectedWeightedDenseGraph.cs | 2 +- DataStructures/Graphs/DirectedWeightedSparseGraph.cs | 2 +- DataStructures/Graphs/UndirectedWeightedDenseGraph.cs | 2 +- DataStructures/Graphs/UndirectedWeightedSparseGraph.cs | 2 +- UnitTest/AlgorithmsTests/GraphsBellmanFordShortestPaths.cs | 2 +- UnitTest/AlgorithmsTests/GraphsDijkstraShortestPathsTest.cs | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/DataStructures/Graphs/DirectedWeightedDenseGraph.cs b/DataStructures/Graphs/DirectedWeightedDenseGraph.cs index 1d190781..b49c33dd 100644 --- a/DataStructures/Graphs/DirectedWeightedDenseGraph.cs +++ b/DataStructures/Graphs/DirectedWeightedDenseGraph.cs @@ -357,5 +357,5 @@ public override void Clear() } - public class DirectedWeightedDenseGraph : DirectedWeightedDenseGraph where T : IComparable { } + public class DirectedWeightedDenseGraph : DirectedWeightedDenseGraph, IWeightedGraph where T : IComparable { } } diff --git a/DataStructures/Graphs/DirectedWeightedSparseGraph.cs b/DataStructures/Graphs/DirectedWeightedSparseGraph.cs index 72f690b2..ac3c67a5 100644 --- a/DataStructures/Graphs/DirectedWeightedSparseGraph.cs +++ b/DataStructures/Graphs/DirectedWeightedSparseGraph.cs @@ -538,5 +538,5 @@ public virtual void Clear() } - public class DirectedWeightedSparseGraph : DirectedWeightedSparseGraph where T : IComparable { } + public class DirectedWeightedSparseGraph : DirectedWeightedSparseGraph, IGraph, IWeightedGraph where T : IComparable { } } diff --git a/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs b/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs index c9f43eb4..da7026ab 100644 --- a/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs +++ b/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs @@ -375,5 +375,5 @@ public override void Clear() } } - public class UndirectedWeightedDenseGraph : UndirectedWeightedDenseGraph where T : IComparable { } + public class UndirectedWeightedDenseGraph : UndirectedWeightedDenseGraph, IWeightedGraph where T : IComparable { } } diff --git a/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs b/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs index cf86d93f..e4baa2a2 100644 --- a/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs +++ b/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs @@ -569,5 +569,5 @@ public virtual void Clear() } - public class UndirectedWeightedSparseGraph : UndirectedWeightedSparseGraph where T : IComparable { } + public class UndirectedWeightedSparseGraph : UndirectedWeightedSparseGraph, IGraph, IWeightedGraph where T : IComparable { } } diff --git a/UnitTest/AlgorithmsTests/GraphsBellmanFordShortestPaths.cs b/UnitTest/AlgorithmsTests/GraphsBellmanFordShortestPaths.cs index b6ab8940..08c954ec 100644 --- a/UnitTest/AlgorithmsTests/GraphsBellmanFordShortestPaths.cs +++ b/UnitTest/AlgorithmsTests/GraphsBellmanFordShortestPaths.cs @@ -13,7 +13,7 @@ public static class GraphsBellmanFordShortestPaths public static void DoTest() { string[] V; - IEnumerable> E; + IEnumerable> E; DirectedWeightedSparseGraph graph; BellmanFordShortestPaths, string> BellmanFord; diff --git a/UnitTest/AlgorithmsTests/GraphsDijkstraShortestPathsTest.cs b/UnitTest/AlgorithmsTests/GraphsDijkstraShortestPathsTest.cs index 2ee32add..70410405 100644 --- a/UnitTest/AlgorithmsTests/GraphsDijkstraShortestPathsTest.cs +++ b/UnitTest/AlgorithmsTests/GraphsDijkstraShortestPathsTest.cs @@ -44,7 +44,7 @@ public static void DoTest() Assert.True(status == true); // Get E - IEnumerable> E = graph.Edges; + IEnumerable> E = graph.Edges; Assert.True(graph.EdgesCount == 10, "Wrong Edges Count."); // PRINT THE GRAPH From 01ce17d8262b9e6f2eb1b8e15885812017b9e113 Mon Sep 17 00:00:00 2001 From: Mengyu Zhou Date: Tue, 21 Aug 2018 01:32:30 +0800 Subject: [PATCH 06/12] Revert changes in unit tests. --- UnitTest/AlgorithmsTests/GraphsBellmanFordShortestPaths.cs | 2 +- UnitTest/AlgorithmsTests/GraphsDijkstraShortestPathsTest.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/UnitTest/AlgorithmsTests/GraphsBellmanFordShortestPaths.cs b/UnitTest/AlgorithmsTests/GraphsBellmanFordShortestPaths.cs index 08c954ec..b6ab8940 100644 --- a/UnitTest/AlgorithmsTests/GraphsBellmanFordShortestPaths.cs +++ b/UnitTest/AlgorithmsTests/GraphsBellmanFordShortestPaths.cs @@ -13,7 +13,7 @@ public static class GraphsBellmanFordShortestPaths public static void DoTest() { string[] V; - IEnumerable> E; + IEnumerable> E; DirectedWeightedSparseGraph graph; BellmanFordShortestPaths, string> BellmanFord; diff --git a/UnitTest/AlgorithmsTests/GraphsDijkstraShortestPathsTest.cs b/UnitTest/AlgorithmsTests/GraphsDijkstraShortestPathsTest.cs index 70410405..2ee32add 100644 --- a/UnitTest/AlgorithmsTests/GraphsDijkstraShortestPathsTest.cs +++ b/UnitTest/AlgorithmsTests/GraphsDijkstraShortestPathsTest.cs @@ -44,7 +44,7 @@ public static void DoTest() Assert.True(status == true); // Get E - IEnumerable> E = graph.Edges; + IEnumerable> E = graph.Edges; Assert.True(graph.EdgesCount == 10, "Wrong Edges Count."); // PRINT THE GRAPH From 912968d8db26aadddfbcc8a428c47176ad3c38ea Mon Sep 17 00:00:00 2001 From: Mengyu Zhou Date: Tue, 21 Aug 2018 01:38:42 +0800 Subject: [PATCH 07/12] Add backward compatibility code. --- DataStructures/Graphs/CliqueGraph.cs | 19 +++++++++++++++---- DataStructures/Graphs/DirectedDenseGraph.cs | 16 +++++++++++++++- DataStructures/Graphs/DirectedSparseGraph.cs | 15 +++++++++++++++ .../Graphs/DirectedWeightedDenseGraph.cs | 5 ++++- .../Graphs/DirectedWeightedSparseGraph.cs | 18 +++++++++++++++++- DataStructures/Graphs/IGraph.cs | 18 +++++++++++++++++- DataStructures/Graphs/IWeightedGraph.cs | 8 +++++++- DataStructures/Graphs/UndirectedDenseGraph.cs | 15 +++++++++++++++ .../Graphs/UndirectedSparseGraph.cs | 15 +++++++++++++++ .../Graphs/UndirectedWeightedDenseGraph.cs | 7 +++++-- .../Graphs/UndirectedWeightedSparseGraph.cs | 17 ++++++++++++++++- DataStructures/Graphs/WeightedEdge.cs | 17 +++++++++++++++-- 12 files changed, 156 insertions(+), 14 deletions(-) diff --git a/DataStructures/Graphs/CliqueGraph.cs b/DataStructures/Graphs/CliqueGraph.cs index 6f7f3db3..557ba17e 100644 --- a/DataStructures/Graphs/CliqueGraph.cs +++ b/DataStructures/Graphs/CliqueGraph.cs @@ -255,7 +255,7 @@ ISet> getPairs(ICollection vertices) /// /// An enumerable collection of all graph edges. /// - public IEnumerable> Edges + public IEnumerable> Edges { get { @@ -269,11 +269,13 @@ public IEnumerable> Edges return returnEdges; } } + + IEnumerable> IGraph.Edges => this.Edges; /// /// Get all incoming edges to vertex. /// - public IEnumerable> IncomingEdges(T vertex) + public IEnumerable> IncomingEdges(T vertex) { List> incomingEdges = new List>(); @@ -292,11 +294,16 @@ public IEnumerable> IncomingEdges(T vertex) return incomingEdges; } + + IEnumerable> IGraph.IncomingEdges(T vertex) + { + return this.IncomingEdges(vertex); + } /// /// Get all outgoing edges from a vertex. /// - public IEnumerable> OutgoingEdges(T vertex) + public IEnumerable> OutgoingEdges(T vertex) { List> outgoingEdges = new List>(); @@ -315,6 +322,11 @@ public IEnumerable> OutgoingEdges(T vertex) return outgoingEdges; } + IEnumerable> IGraph.OutgoingEdges(T vertex) + { + return this.OutgoingEdges(vertex); + } + /// /// Connects two vertices together. /// @@ -824,7 +836,6 @@ static V Pick(IEnumerable Set) enumerator.Dispose(); return ret; } - } internal class UnordererPair : Tuple, IEquatable> where T : IEquatable diff --git a/DataStructures/Graphs/DirectedDenseGraph.cs b/DataStructures/Graphs/DirectedDenseGraph.cs index caea4be0..c7814795 100644 --- a/DataStructures/Graphs/DirectedDenseGraph.cs +++ b/DataStructures/Graphs/DirectedDenseGraph.cs @@ -102,21 +102,35 @@ public virtual IEnumerable Vertices } + IEnumerable> IGraph.Edges + { + get { return this.Edges; } + } + IEnumerable> IGraph.Edges { get { return this.Edges; } } + IEnumerable> IGraph.IncomingEdges(T vertex) + { + return this.IncomingEdges(vertex); + } + IEnumerable> IGraph.IncomingEdges(T vertex) { return this.IncomingEdges(vertex); } - IEnumerable> IGraph.OutgoingEdges(T vertex) + IEnumerable> IGraph.OutgoingEdges(T vertex) { return this.OutgoingEdges(vertex); } + IEnumerable> IGraph.OutgoingEdges(T vertex) + { + return this.OutgoingEdges(vertex); + } /// /// An enumerable collection of all directed unweighted edges in graph. diff --git a/DataStructures/Graphs/DirectedSparseGraph.cs b/DataStructures/Graphs/DirectedSparseGraph.cs index a55c6e88..07275eda 100644 --- a/DataStructures/Graphs/DirectedSparseGraph.cs +++ b/DataStructures/Graphs/DirectedSparseGraph.cs @@ -92,16 +92,31 @@ public virtual IEnumerable Vertices } + IEnumerable> IGraph.Edges + { + get { return this.Edges; } + } + IEnumerable> IGraph.Edges { get { return this.Edges; } } + IEnumerable> IGraph.IncomingEdges(T vertex) + { + return this.IncomingEdges(vertex); + } + IEnumerable> IGraph.IncomingEdges(T vertex) { return this.IncomingEdges(vertex); } + IEnumerable> IGraph.OutgoingEdges(T vertex) + { + return this.OutgoingEdges(vertex); + } + IEnumerable> IGraph.OutgoingEdges(T vertex) { return this.OutgoingEdges(vertex); diff --git a/DataStructures/Graphs/DirectedWeightedDenseGraph.cs b/DataStructures/Graphs/DirectedWeightedDenseGraph.cs index b49c33dd..492f8db8 100644 --- a/DataStructures/Graphs/DirectedWeightedDenseGraph.cs +++ b/DataStructures/Graphs/DirectedWeightedDenseGraph.cs @@ -357,5 +357,8 @@ public override void Clear() } - public class DirectedWeightedDenseGraph : DirectedWeightedDenseGraph, IWeightedGraph where T : IComparable { } + public class DirectedWeightedDenseGraph : DirectedWeightedDenseGraph, IWeightedGraph where T : IComparable + { + public new WeightedEdge GetEdge(T source, T destination) => base.GetEdge(source, destination).ToSimpleEdge(); + } } diff --git a/DataStructures/Graphs/DirectedWeightedSparseGraph.cs b/DataStructures/Graphs/DirectedWeightedSparseGraph.cs index ac3c67a5..07486774 100644 --- a/DataStructures/Graphs/DirectedWeightedSparseGraph.cs +++ b/DataStructures/Graphs/DirectedWeightedSparseGraph.cs @@ -13,6 +13,7 @@ using System; using System.Collections.Generic; +using System.Linq; using DataStructures.Common; using DataStructures.Lists; @@ -538,5 +539,20 @@ public virtual void Clear() } - public class DirectedWeightedSparseGraph : DirectedWeightedSparseGraph, IGraph, IWeightedGraph where T : IComparable { } + public class DirectedWeightedSparseGraph : DirectedWeightedSparseGraph, IGraph, IWeightedGraph where T : IComparable + { + public new IEnumerable> Edges => base.Edges.Select(edge => edge.ToSimpleEdge()); + + public new WeightedEdge GetEdge(T source, T destination) => base.GetEdge(source, destination).ToSimpleEdge(); + + public new IEnumerable> IncomingEdges(T vertex) => base.IncomingEdges(vertex).Select(edge => edge.ToSimpleEdge()); + + public new IEnumerable> OutgoingEdges(T vertex) => base.OutgoingEdges(vertex).Select(edge => edge.ToSimpleEdge()); + + IEnumerable> IGraph.Edges => this.Edges; + + IEnumerable> IGraph.IncomingEdges(T vertex) => this.IncomingEdges(vertex); + + IEnumerable> IGraph.OutgoingEdges(T vertex) => this.OutgoingEdges(vertex); + } } diff --git a/DataStructures/Graphs/IGraph.cs b/DataStructures/Graphs/IGraph.cs index aba12999..b38e4fb4 100644 --- a/DataStructures/Graphs/IGraph.cs +++ b/DataStructures/Graphs/IGraph.cs @@ -124,6 +124,22 @@ public interface IGraph where T : IComparable /// void Clear(); } + + public interface IGraph : IGraph where T : IComparable + { + /// + /// An enumerable collection of edges. + /// + new IEnumerable> Edges { get; } + + /// + /// Get all incoming edges from vertex + /// + new IEnumerable> IncomingEdges(T vertex); - public interface IGraph : IGraph where T : IComparable { } + /// + /// Get all outgoing edges from vertex + /// + new IEnumerable> OutgoingEdges(T vertex); + } } diff --git a/DataStructures/Graphs/IWeightedGraph.cs b/DataStructures/Graphs/IWeightedGraph.cs index 1f62d649..d4877f78 100644 --- a/DataStructures/Graphs/IWeightedGraph.cs +++ b/DataStructures/Graphs/IWeightedGraph.cs @@ -33,6 +33,12 @@ public interface IWeightedGraph where T : IComparable where W : ICompar System.Collections.Generic.Dictionary NeighboursMap(T vertex); } - public interface IWeightedGraph : IWeightedGraph where T : IComparable { } + public interface IWeightedGraph : IWeightedGraph where T : IComparable + { + /// + /// Get edge object from source to destination. + /// + new WeightedEdge GetEdge(T source, T destination); + } } diff --git a/DataStructures/Graphs/UndirectedDenseGraph.cs b/DataStructures/Graphs/UndirectedDenseGraph.cs index 55f7d212..a7751962 100644 --- a/DataStructures/Graphs/UndirectedDenseGraph.cs +++ b/DataStructures/Graphs/UndirectedDenseGraph.cs @@ -108,16 +108,31 @@ public virtual IEnumerable Vertices } + IEnumerable> IGraph.Edges + { + get { return this.Edges; } + } + IEnumerable> IGraph.Edges { get { return this.Edges; } } + IEnumerable> IGraph.IncomingEdges(T vertex) + { + return this.IncomingEdges(vertex); + } + IEnumerable> IGraph.IncomingEdges(T vertex) { return this.IncomingEdges(vertex); } + IEnumerable> IGraph.OutgoingEdges(T vertex) + { + return this.OutgoingEdges(vertex); + } + IEnumerable> IGraph.OutgoingEdges(T vertex) { return this.OutgoingEdges(vertex); diff --git a/DataStructures/Graphs/UndirectedSparseGraph.cs b/DataStructures/Graphs/UndirectedSparseGraph.cs index 06a50d9b..601f7fdd 100644 --- a/DataStructures/Graphs/UndirectedSparseGraph.cs +++ b/DataStructures/Graphs/UndirectedSparseGraph.cs @@ -93,16 +93,31 @@ public virtual IEnumerable Vertices } + IEnumerable> IGraph.Edges + { + get { return this.Edges; } + } + IEnumerable> IGraph.Edges { get { return this.Edges; } } + IEnumerable> IGraph.IncomingEdges(T vertex) + { + return this.IncomingEdges(vertex); + } + IEnumerable> IGraph.IncomingEdges(T vertex) { return this.IncomingEdges(vertex); } + IEnumerable> IGraph.OutgoingEdges(T vertex) + { + return this.OutgoingEdges(vertex); + } + IEnumerable> IGraph.OutgoingEdges(T vertex) { return this.OutgoingEdges(vertex); diff --git a/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs b/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs index da7026ab..4f884746 100644 --- a/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs +++ b/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs @@ -374,6 +374,9 @@ public override void Clear() _adjacencyMatrix.Populate(rows: _verticesCapacity, columns: _verticesCapacity, defaultValue: EMPTY_EDGE_SLOT); } } - - public class UndirectedWeightedDenseGraph : UndirectedWeightedDenseGraph, IWeightedGraph where T : IComparable { } + + public class UndirectedWeightedDenseGraph : UndirectedWeightedDenseGraph, IWeightedGraph where T : IComparable + { + public new WeightedEdge GetEdge(T source, T destination) => base.GetEdge(source, destination).ToSimpleEdge(); + } } diff --git a/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs b/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs index e4baa2a2..bd521673 100644 --- a/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs +++ b/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs @@ -12,6 +12,7 @@ using System; using System.Collections.Generic; +using System.Linq; using DataStructures.Common; using DataStructures.Lists; @@ -567,7 +568,21 @@ public virtual void Clear() _adjacencyList.Clear(); } } + + public class UndirectedWeightedSparseGraph : UndirectedWeightedSparseGraph, IGraph, IWeightedGraph where T : IComparable + { + public new IEnumerable> Edges => base.Edges.Select(edge => edge.ToSimpleEdge()); + + public new WeightedEdge GetEdge(T source, T destination) => base.GetEdge(source, destination).ToSimpleEdge(); + + public new IEnumerable> IncomingEdges(T vertex) => base.IncomingEdges(vertex).Select(edge => edge.ToSimpleEdge()); + public new IEnumerable> OutgoingEdges(T vertex) => base.OutgoingEdges(vertex).Select(edge => edge.ToSimpleEdge()); - public class UndirectedWeightedSparseGraph : UndirectedWeightedSparseGraph, IGraph, IWeightedGraph where T : IComparable { } + IEnumerable> IGraph.Edges => this.Edges; + + IEnumerable> IGraph.IncomingEdges(T vertex) => this.IncomingEdges(vertex); + + IEnumerable> IGraph.OutgoingEdges(T vertex) => this.OutgoingEdges(vertex); + } } diff --git a/DataStructures/Graphs/WeightedEdge.cs b/DataStructures/Graphs/WeightedEdge.cs index c972d386..4b4ab19d 100644 --- a/DataStructures/Graphs/WeightedEdge.cs +++ b/DataStructures/Graphs/WeightedEdge.cs @@ -63,11 +63,24 @@ public int CompareTo(IEdge other) } #endregion } - - public class WeightedEdge : WeightedEdge where TVertex : IComparable + + public class WeightedEdge : WeightedEdge, IEdge where TVertex : IComparable { public WeightedEdge(TVertex src, TVertex dst, long weight) : base(src, dst, weight) { } + + public WeightedEdge(WeightedEdge edge) : base(edge.Source, edge.Destination, edge.Weight) + { + } + } + + public static class WeightedEdgeExtension + { + public static WeightedEdge ToSimpleEdge(this WeightedEdge edge) + where TVertex : IComparable + { + return new WeightedEdge(edge.Source, edge.Destination, edge.Weight); + } } } From 2a908aaa8b9249ad988e00ab99b1174052cb875a Mon Sep 17 00:00:00 2001 From: Mengyu Zhou Date: Tue, 21 Aug 2018 01:53:17 +0800 Subject: [PATCH 08/12] Fix Dijkstra unit test on arithmetic overflow. --- Algorithms/Graphs/DijkstraShortestPaths.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Algorithms/Graphs/DijkstraShortestPaths.cs b/Algorithms/Graphs/DijkstraShortestPaths.cs index 516eb5bc..8a9e8a01 100644 --- a/Algorithms/Graphs/DijkstraShortestPaths.cs +++ b/Algorithms/Graphs/DijkstraShortestPaths.cs @@ -205,7 +205,7 @@ private bool _checkOptimalityConditions(TGraph graph, TVertex source) { var w = _nodesToIndices[edge.Key]; - if (_distances[v] + edge.Value < _distances[w]) + if (_distances[v] < _distances[w] - edge.Value) { Console.WriteLine("edge " + vertex + "-" + edge.Key + " is not relaxed"); return false; From 19b69b176ce6a16d0dc27af4a814e079cb426d7b Mon Sep 17 00:00:00 2001 From: Mengyu Zhou Date: Fri, 26 Jul 2019 22:52:17 +0800 Subject: [PATCH 09/12] Fix DFS and BFS tests of UndirectedWeightedDenseGraph. --- .../GraphsUndirectedWeightedDenseGraphTest.cs | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/UnitTest/DataStructuresTests/GraphsUndirectedWeightedDenseGraphTest.cs b/UnitTest/DataStructuresTests/GraphsUndirectedWeightedDenseGraphTest.cs index bbb0db4f..38c8e5ee 100644 --- a/UnitTest/DataStructuresTests/GraphsUndirectedWeightedDenseGraphTest.cs +++ b/UnitTest/DataStructuresTests/GraphsUndirectedWeightedDenseGraphTest.cs @@ -85,28 +85,26 @@ public static void DoTest() // BFS from A // Walk the graph using BFS from A: var bfsWalk = graph.BreadthFirstWalk("a"); - - // output: (s) (a) (x) (z) (d) (c) (f) (v) - // output: (s) (a) (x) (z) (d) (c) (f) (v) - Assert.True(bfsWalk.SequenceEqual(new[] { "s", "a", "x", "z", "d", "c", "f", "v" })); + // output: (a) (z) (s) (x) (d) (c) (f) (v) + Assert.True(bfsWalk.SequenceEqual(new[] { "a", "z", "s", "x", "d", "c", "f", "v" })); // DFS from A // Walk the graph using DFS from A: var dfsWalk = graph.DepthFirstWalk("a"); - // output: (s) (a) (x) (z) (d) (c) (f) (v) - Assert.True(bfsWalk.SequenceEqual(new[] { "s", "a", "x", "z", "d", "c", "f", "v" })); + // output: (a) (x) (c) (v) (f) (d) (s) (z) + Assert.True(dfsWalk.SequenceEqual(new[] { "a", "x", "c", "v", "f", "d", "s", "z" })); // BFS from F // Walk the graph using BFS from F: bfsWalk = graph.BreadthFirstWalk("f"); - // output: (s) (a) (x) (z) (d) (c) (f) (v) - Assert.True(bfsWalk.SequenceEqual(new[] { "s", "a", "x", "z", "d", "c", "f", "v" })); + // output: (f) (d) (c) (s) (x) (v) (a) (z) + Assert.True(bfsWalk.SequenceEqual(new[] { "f", "d", "c", "s", "x", "v", "a", "z" })); // DFS from F // Walk the graph using DFS from F: dfsWalk = graph.DepthFirstWalk("f"); - // output: (s) (a) (x) (z) (d) (c) (f) (v) - Assert.True(bfsWalk.SequenceEqual(new[] { "s", "a", "x", "z", "d", "c", "f", "v" })); + // output: (f) (c) (v) (d) (x) (s) (a) (z) + Assert.True(dfsWalk.SequenceEqual(new[] { "f", "c", "v", "d", "x", "s", "a", "z" })); /********************************************************************/ @@ -131,10 +129,8 @@ public static void DoTest() // Walk the graph using DFS: dfsWalk = graph.DepthFirstWalk(); - // output: (a) (b) (e) (d) (c) (f) - Assert.True(bfsWalk.SequenceEqual(new[] { "a", "b", "e", "d", "c", "f" })); - - Console.ReadLine(); + // output: (a) (d) (e) (c) (f) (b) + Assert.True(dfsWalk.SequenceEqual(new[] { "a", "d", "e", "c", "f", "b" })); } } From 0e01698d3c5fb9474db95264c9ef56ea2af8bf8a Mon Sep 17 00:00:00 2001 From: Mengyu Zhou Date: Thu, 23 Jan 2020 15:38:44 +0800 Subject: [PATCH 10/12] Fix null pointer exception. --- DataStructures/Graphs/UndirectedWeightedDenseGraph.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs b/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs index 5ba64b86..964fc549 100644 --- a/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs +++ b/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs @@ -347,6 +347,6 @@ public override void Clear() public class UndirectedWeightedDenseGraph : UndirectedWeightedDenseGraph, IWeightedGraph where T : IComparable { - public new WeightedEdge GetEdge(T source, T destination) => base.GetEdge(source, destination).ToSimpleEdge(); + public new WeightedEdge GetEdge(T source, T destination) => base.GetEdge(source, destination)?.ToSimpleEdge(); } } From e030c7dbdc8a971fadd879d3e0a58ab3c21a5fec Mon Sep 17 00:00:00 2001 From: Mengyu Zhou Date: Thu, 23 Jan 2020 16:38:44 +0800 Subject: [PATCH 11/12] Remove unecessary custom weight support. --- Algorithms/Graphs/DijkstraShortestPaths.cs | 18 ++++++++++-- DataStructures/Graphs/CliqueGraph.cs | 16 ++--------- DataStructures/Graphs/DirectedDenseGraph.cs | 15 ---------- DataStructures/Graphs/DirectedSparseGraph.cs | 15 ---------- .../Graphs/DirectedWeightedSparseGraph.cs | 8 +++--- DataStructures/Graphs/IEdge.cs | 11 +------- DataStructures/Graphs/IGraph.cs | 28 ++++--------------- DataStructures/Graphs/UndirectedDenseGraph.cs | 15 ---------- .../Graphs/UndirectedSparseGraph.cs | 15 ---------- .../Graphs/UndirectedWeightedSparseGraph.cs | 8 +++--- DataStructures/Graphs/UnweightedEdge.cs | 16 ++--------- DataStructures/Graphs/WeightedEdge.cs | 12 ++++---- 12 files changed, 41 insertions(+), 136 deletions(-) diff --git a/Algorithms/Graphs/DijkstraShortestPaths.cs b/Algorithms/Graphs/DijkstraShortestPaths.cs index c72f7719..1977ab72 100644 --- a/Algorithms/Graphs/DijkstraShortestPaths.cs +++ b/Algorithms/Graphs/DijkstraShortestPaths.cs @@ -27,6 +27,20 @@ public class DijkstraShortestPaths private readonly TGraph _graph; private readonly TVertex _source; + private long GetEdgeWeight(IEdge edge) + { + // TODO: Change Dijkstra algorithm to support edge weights that are not Int64 compatible. + if (edge.IsWeighted) + { + var e = edge as WeightedEdge; + return e.Weight; + } + else + { + return 1; + } + } + public DijkstraShortestPaths(TGraph graph, TVertex source) { if (graph == null) @@ -38,7 +52,7 @@ public DijkstraShortestPaths(TGraph graph, TVertex source) if (!graph.HasVertex(source)) throw new ArgumentException("The source vertex doesn't belong to graph."); - if (graph.Edges.Any(edge => edge.Weight < 0)) + if (graph.Edges.Any(edge => GetEdgeWeight(edge) < 0)) throw new ArgumentException("Negative edge weight detected."); _graph = graph; @@ -62,7 +76,7 @@ private void _dijkstra() foreach (var outgoingEdge in outgoingEdges) { var adjacentIndex = _nodesToIndices[outgoingEdge.Destination]; - var delta = _distances[currentVertexIndex] != Infinity ? _distances[currentVertexIndex] + outgoingEdge.Weight : Infinity; + var delta = _distances[currentVertexIndex] != Infinity ? _distances[currentVertexIndex] + GetEdgeWeight(outgoingEdge) : Infinity; if (delta < _distances[adjacentIndex]) { diff --git a/DataStructures/Graphs/CliqueGraph.cs b/DataStructures/Graphs/CliqueGraph.cs index 557ba17e..4707c976 100644 --- a/DataStructures/Graphs/CliqueGraph.cs +++ b/DataStructures/Graphs/CliqueGraph.cs @@ -269,8 +269,6 @@ public IEnumerable> Edges return returnEdges; } } - - IEnumerable> IGraph.Edges => this.Edges; /// /// Get all incoming edges to vertex. @@ -294,11 +292,6 @@ public IEnumerable> IncomingEdges(T vertex) return incomingEdges; } - - IEnumerable> IGraph.IncomingEdges(T vertex) - { - return this.IncomingEdges(vertex); - } /// /// Get all outgoing edges from a vertex. @@ -322,11 +315,6 @@ public IEnumerable> OutgoingEdges(T vertex) return outgoingEdges; } - IEnumerable> IGraph.OutgoingEdges(T vertex) - { - return this.OutgoingEdges(vertex); - } - /// /// Connects two vertices together. /// @@ -406,7 +394,7 @@ public void AddVertices(IEnumerable collection) /// Adds a list of vertices to the graph. /// /// Collection. - void IGraph.AddVertices(IList collection) + void IGraph.AddVertices(IList collection) { AddVertices(collection); } @@ -610,7 +598,7 @@ ICollection> getEdges() /// Returns the list of Vertices. /// /// The vertices. - IEnumerable IGraph.Vertices + IEnumerable IGraph.Vertices { get { diff --git a/DataStructures/Graphs/DirectedDenseGraph.cs b/DataStructures/Graphs/DirectedDenseGraph.cs index c7814795..14150a2a 100644 --- a/DataStructures/Graphs/DirectedDenseGraph.cs +++ b/DataStructures/Graphs/DirectedDenseGraph.cs @@ -107,31 +107,16 @@ IEnumerable> IGraph.Edges get { return this.Edges; } } - IEnumerable> IGraph.Edges - { - get { return this.Edges; } - } - IEnumerable> IGraph.IncomingEdges(T vertex) { return this.IncomingEdges(vertex); } - IEnumerable> IGraph.IncomingEdges(T vertex) - { - return this.IncomingEdges(vertex); - } - IEnumerable> IGraph.OutgoingEdges(T vertex) { return this.OutgoingEdges(vertex); } - IEnumerable> IGraph.OutgoingEdges(T vertex) - { - return this.OutgoingEdges(vertex); - } - /// /// An enumerable collection of all directed unweighted edges in graph. /// diff --git a/DataStructures/Graphs/DirectedSparseGraph.cs b/DataStructures/Graphs/DirectedSparseGraph.cs index 07275eda..e8ce7df9 100644 --- a/DataStructures/Graphs/DirectedSparseGraph.cs +++ b/DataStructures/Graphs/DirectedSparseGraph.cs @@ -97,31 +97,16 @@ IEnumerable> IGraph.Edges get { return this.Edges; } } - IEnumerable> IGraph.Edges - { - get { return this.Edges; } - } - IEnumerable> IGraph.IncomingEdges(T vertex) { return this.IncomingEdges(vertex); } - IEnumerable> IGraph.IncomingEdges(T vertex) - { - return this.IncomingEdges(vertex); - } - IEnumerable> IGraph.OutgoingEdges(T vertex) { return this.OutgoingEdges(vertex); } - IEnumerable> IGraph.OutgoingEdges(T vertex) - { - return this.OutgoingEdges(vertex); - } - /// /// An enumerable collection of all directed unweighted edges in graph. diff --git a/DataStructures/Graphs/DirectedWeightedSparseGraph.cs b/DataStructures/Graphs/DirectedWeightedSparseGraph.cs index 07486774..4222ac39 100644 --- a/DataStructures/Graphs/DirectedWeightedSparseGraph.cs +++ b/DataStructures/Graphs/DirectedWeightedSparseGraph.cs @@ -19,7 +19,7 @@ namespace DataStructures.Graphs { - public class DirectedWeightedSparseGraph : IGraph, IWeightedGraph where T : IComparable where W : IComparable + public class DirectedWeightedSparseGraph : IGraph, IWeightedGraph where T : IComparable where W : IComparable { /// /// INSTANCE VARIABLES @@ -124,17 +124,17 @@ public IEnumerable Vertices } - IEnumerable> IGraph.Edges + IEnumerable> IGraph.Edges { get { return this.Edges; } } - IEnumerable> IGraph.IncomingEdges(T vertex) + IEnumerable> IGraph.IncomingEdges(T vertex) { return this.IncomingEdges(vertex); } - IEnumerable> IGraph.OutgoingEdges(T vertex) + IEnumerable> IGraph.OutgoingEdges(T vertex) { return this.OutgoingEdges(vertex); } diff --git a/DataStructures/Graphs/IEdge.cs b/DataStructures/Graphs/IEdge.cs index ad9bb615..ca269042 100644 --- a/DataStructures/Graphs/IEdge.cs +++ b/DataStructures/Graphs/IEdge.cs @@ -5,7 +5,7 @@ namespace DataStructures.Graphs /// /// This interface should be implemented by all edges classes. /// - public interface IEdge : IComparable> where TVertex : IComparable + public interface IEdge : IComparable> where TVertex : IComparable { /// /// Gets a value indicating whether this edge is weighted. @@ -24,15 +24,6 @@ public interface IEdge : IComparable> /// /// The destination. TVertex Destination { get; set; } - - /// - /// Gets or sets the weight of edge. - /// Unwighted edges can be thought of as edges of the same weight - /// - /// The weight. - TWeight Weight { get; set; } } - - public interface IEdge : IEdge where TVertex : IComparable { } } diff --git a/DataStructures/Graphs/IGraph.cs b/DataStructures/Graphs/IGraph.cs index b38e4fb4..4b0e0a02 100644 --- a/DataStructures/Graphs/IGraph.cs +++ b/DataStructures/Graphs/IGraph.cs @@ -1,11 +1,11 @@ using System; using System.Collections.Generic; + using DataStructures.Lists; -using System.Linq; namespace DataStructures.Graphs { - public interface IGraph where T : IComparable + public interface IGraph where T : IComparable { /// /// Returns true, if graph is directed; false otherwise. @@ -35,17 +35,17 @@ public interface IGraph where T : IComparable /// /// An enumerable collection of edges. /// - IEnumerable> Edges { get; } + IEnumerable> Edges { get; } /// /// Get all incoming edges from vertex /// - IEnumerable> IncomingEdges(T vertex); + IEnumerable> IncomingEdges(T vertex); /// /// Get all outgoing edges from vertex /// - IEnumerable> OutgoingEdges(T vertex); + IEnumerable> OutgoingEdges(T vertex); /// /// Connects two vertices together. @@ -124,22 +124,4 @@ public interface IGraph where T : IComparable /// void Clear(); } - - public interface IGraph : IGraph where T : IComparable - { - /// - /// An enumerable collection of edges. - /// - new IEnumerable> Edges { get; } - - /// - /// Get all incoming edges from vertex - /// - new IEnumerable> IncomingEdges(T vertex); - - /// - /// Get all outgoing edges from vertex - /// - new IEnumerable> OutgoingEdges(T vertex); - } } diff --git a/DataStructures/Graphs/UndirectedDenseGraph.cs b/DataStructures/Graphs/UndirectedDenseGraph.cs index aeb731bf..54de9f1c 100644 --- a/DataStructures/Graphs/UndirectedDenseGraph.cs +++ b/DataStructures/Graphs/UndirectedDenseGraph.cs @@ -113,31 +113,16 @@ IEnumerable> IGraph.Edges get { return this.Edges; } } - IEnumerable> IGraph.Edges - { - get { return this.Edges; } - } - IEnumerable> IGraph.IncomingEdges(T vertex) { return this.IncomingEdges(vertex); } - IEnumerable> IGraph.IncomingEdges(T vertex) - { - return this.IncomingEdges(vertex); - } - IEnumerable> IGraph.OutgoingEdges(T vertex) { return this.OutgoingEdges(vertex); } - IEnumerable> IGraph.OutgoingEdges(T vertex) - { - return this.OutgoingEdges(vertex); - } - /// /// An enumerable collection of edges. diff --git a/DataStructures/Graphs/UndirectedSparseGraph.cs b/DataStructures/Graphs/UndirectedSparseGraph.cs index 601f7fdd..3593c0ec 100644 --- a/DataStructures/Graphs/UndirectedSparseGraph.cs +++ b/DataStructures/Graphs/UndirectedSparseGraph.cs @@ -98,31 +98,16 @@ IEnumerable> IGraph.Edges get { return this.Edges; } } - IEnumerable> IGraph.Edges - { - get { return this.Edges; } - } - IEnumerable> IGraph.IncomingEdges(T vertex) { return this.IncomingEdges(vertex); } - IEnumerable> IGraph.IncomingEdges(T vertex) - { - return this.IncomingEdges(vertex); - } - IEnumerable> IGraph.OutgoingEdges(T vertex) { return this.OutgoingEdges(vertex); } - IEnumerable> IGraph.OutgoingEdges(T vertex) - { - return this.OutgoingEdges(vertex); - } - /// /// An enumerable collection of all unweighted edges in Graph. diff --git a/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs b/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs index bd521673..af941571 100644 --- a/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs +++ b/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs @@ -18,7 +18,7 @@ namespace DataStructures.Graphs { - public class UndirectedWeightedSparseGraph : IGraph, IWeightedGraph where T : IComparable where W : IComparable + public class UndirectedWeightedSparseGraph : IGraph, IWeightedGraph where T : IComparable where W : IComparable { /// /// INSTANCE VARIABLES @@ -125,17 +125,17 @@ public IEnumerable Vertices } - IEnumerable> IGraph.Edges + IEnumerable> IGraph.Edges { get { return this.Edges; } } - IEnumerable> IGraph.IncomingEdges(T vertex) + IEnumerable> IGraph.IncomingEdges(T vertex) { return this.IncomingEdges(vertex); } - IEnumerable> IGraph.OutgoingEdges(T vertex) + IEnumerable> IGraph.OutgoingEdges(T vertex) { return this.OutgoingEdges(vertex); } diff --git a/DataStructures/Graphs/UnweightedEdge.cs b/DataStructures/Graphs/UnweightedEdge.cs index 123026b4..65e1188e 100644 --- a/DataStructures/Graphs/UnweightedEdge.cs +++ b/DataStructures/Graphs/UnweightedEdge.cs @@ -9,8 +9,6 @@ namespace DataStructures.Graphs /// public class UnweightedEdge : IEdge where TVertex : IComparable { - private const int _edgeWeight = 0; - /// /// Gets or sets the source vertex. /// @@ -23,16 +21,6 @@ public class UnweightedEdge : IEdge where TVertex : IComparabl /// The destination. public TVertex Destination { get; set; } - /// - /// [PRIVATE MEMBER] Gets or sets the weight. - /// - /// The weight. - public Int64 Weight - { - get { throw new NotImplementedException("Unweighted edges don't have weights."); } - set { throw new NotImplementedException("Unweighted edges can't have weights."); } - } - /// /// Gets a value indicating whether this edge is weighted. /// @@ -53,9 +41,9 @@ public UnweightedEdge(TVertex src, TVertex dst) #region IComparable implementation - public int CompareTo(IEdge other) + public int CompareTo(IEdge other) { - if (other == null) + if (other == null || !(other is UnweightedEdge)) return -1; bool areNodesEqual = Source.IsEqualTo(other.Source) && Destination.IsEqualTo(other.Destination); diff --git a/DataStructures/Graphs/WeightedEdge.cs b/DataStructures/Graphs/WeightedEdge.cs index 428aa807..de45b9ee 100644 --- a/DataStructures/Graphs/WeightedEdge.cs +++ b/DataStructures/Graphs/WeightedEdge.cs @@ -7,7 +7,7 @@ namespace DataStructures.Graphs /// /// The graph weighted edge class. /// - public class WeightedEdge : IEdge + public class WeightedEdge : IEdge where TVertex : IComparable where TWeight : IComparable { @@ -49,16 +49,18 @@ public WeightedEdge(TVertex src, TVertex dst, TWeight weight) #region IComparable implementation - public int CompareTo(IEdge other) + public int CompareTo(IEdge other) { - if (other == null) + if (other == null || !(other is WeightedEdge)) return -1; - + bool areNodesEqual = Source.IsEqualTo(other.Source) && Destination.IsEqualTo(other.Destination); if (!areNodesEqual) return -1; - return Weight.CompareTo(other.Weight); + + var o = other as WeightedEdge; + return Weight.CompareTo(o.Weight); } #endregion } From 71077caca0db64c6aa7e2ea58b404bf800e50373 Mon Sep 17 00:00:00 2001 From: Mengyu Zhou Date: Thu, 23 Jan 2020 16:45:19 +0800 Subject: [PATCH 12/12] Revert blank line change. --- DataStructures/Graphs/DirectedDenseGraph.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/DataStructures/Graphs/DirectedDenseGraph.cs b/DataStructures/Graphs/DirectedDenseGraph.cs index 14150a2a..264dff1c 100644 --- a/DataStructures/Graphs/DirectedDenseGraph.cs +++ b/DataStructures/Graphs/DirectedDenseGraph.cs @@ -117,6 +117,7 @@ IEnumerable> IGraph.OutgoingEdges(T vertex) return this.OutgoingEdges(vertex); } + /// /// An enumerable collection of all directed unweighted edges in graph. ///