class Vertex<T>
{
List<Vertex<T>> neighbors;
T value;
bool isVisited;
public List<Vertex<T>> Neighbors { get { return neighbors; } set { neighbors = value; } }
public T Value { get { return value; } set { this.value = value; } }
public bool IsVisited { get { return isVisited; } set { isVisited = value; } }
public int NeighborsCount { get { return neighbors.Count; } }
public Vertex(T value)
{
this.value = value;
isVisited = false;
neighbors = new List<Vertex<T>>();
}
public Vertex(T value, List<Vertex<T>> neighbors)
{
this.value = value;
isVisited = false;
this.neighbors = neighbors;
}
public void Visit()
{
isVisited = true;
}
public void AddEdge(Vertex<T> vertex)
{
neighbors.Add(vertex);
}
public void AddEdges(List<Vertex<T>> newNeighbors)
{
neighbors.AddRange(newNeighbors);
}
public void RemoveEdge(Vertex<T> vertex)
{
neighbors.Remove(vertex);
}
public override string ToString()
{
StringBuilder allNeighbors = new StringBuilder("");
allNeighbors.Append(value + ": ");
foreach (Vertex<T> neighbor in neighbors)
{
allNeighbors.Append(neighbor.value + " ");
}
return allNeighbors.ToString();
}
}
class UndirectedGenericGraph<T>
{
// The list of vertices in the graph
private List<Vertex<T>> vertices;
// The number of vertices
int size;
public List<Vertex<T>> Vertices { get { return vertices; } }
public int Size { get { return vertices.Count; } }
public UndirectedGenericGraph(int initialSize)
{
if(size < 0)
{
throw new ArgumentException("Number of vertices cannot be negative");
}
size = initialSize;
vertices = new List<Vertex<T>>(initialSize);
}
public UndirectedGenericGraph(List<Vertex<T>> initialNodes)
{
vertices = initialNodes;
size = vertices.Count;
}
public void AddVertex(Vertex<T> vertex)
{
vertices.Add(vertex);
}
public void RemoveVertex(Vertex<T> vertex)
{
vertices.Remove(vertex);
}
public bool HasVertex(Vertex<T> vertex)
{
return vertices.Contains(vertex);
}
public void DepthFirstSearch(Vertex<T> root)
{
if (!root.IsVisited)
{
Console.Write(root.Value + " ");
root.Visit();
foreach(Vertex<T> neighbor in root.Neighbors)
{
DepthFirstSearch(neighbor);
}
}
}
public void BreadthFirstSearch(Vertex<T> root)
{
Queue<Vertex<T>> queue = new Queue<Vertex<T>>();
root.Visit();
queue.Enqueue(root);
while(queue.Count > 0)
{
Vertex<T> current = queue.Dequeue();
foreach (Vertex<T> neighbor in current.Neighbors)
{
if (!neighbor.IsVisited)
{
Console.Write(neighbor.Value + " ");
neighbor.Visit();
queue.Enqueue(neighbor);
}
}
}
}
}
class Program
{
static void Main(string[] args)
{
// Create a list of vertices using the Vertex<T> class
List<Vertex<string>> vertices = new List<Vertex<string>>
(
new Vertex<string> []
{
new Vertex<string>("Los Angeles"),
new Vertex<string>("San Francisco"),
new Vertex<string>("Las Vegas"),
new Vertex<string>("Seattle"),
new Vertex<string>("Austin"),
new Vertex<string>("Portland")
}
);
// Establish edges; Ex. Los Angeles -> San Francisco, Las Vegas, Portland
vertices[0].AddEdges(new List<Vertex<string>>(new Vertex<string>[]
{
vertices[1], vertices[2], vertices[5]
}));
vertices[1].AddEdges(new List<Vertex<string>>(new Vertex<string>[]
{
vertices[0], vertices[3], vertices[5]
}));
vertices[2].AddEdges(new List<Vertex<string>>(new Vertex<string>[]
{
vertices[0], vertices[1], vertices[4]
}));
vertices[3].AddEdges(new List<Vertex<string>>(new Vertex<string>[]
{
vertices[1], vertices[5]
}));
vertices[4].AddEdges(new List<Vertex<string>>(new Vertex<string>[]
{
vertices[2]
}));
vertices[5].AddEdges(new List<Vertex<string>>(new Vertex<string>[]
{
vertices[1], vertices[3]
}));
// Create graph using the UndirectedGenericGraph<T> class
UndirectedGenericGraph<string> testGraph = new UndirectedGenericGraph<string>(vertices);
// Check to see that all neighbors are properly set up
foreach(Vertex<string> vertex in vertices)
{
Console.WriteLine(vertex.ToString());
}
// Test searching algorithms
testGraph.DepthFirstSearch(vertices[0]);
//testGraph.BreadthFirstSearch(vertices[0]);
}
}
class Vertex<T>
{
public Vertex(T value, params Vertex<T>[] parameters)
: this(value, (IEnumerable<Vertex<T>>)parameters) { }
public Vertex(T value, IEnumerable<Vertex<T>> neighbors = null)
{
Value = value;
Neighbors = neighbors?.ToList() ?? new List<Vertex<T>>();
IsVisited = false; // can be omitted, default is false but some
// people like to have everything explicitly
// initialized
}
public T Value { get; } // can be made writable
public List<Vertex<T>> Neighbors { get; }
public bool IsVisited { get; set; }
public int NeighborCount => Neighbors.Count;
public void AddEdge(Vertex<T> vertex)
{
Neighbors.Add(vertex);
}
public void AddEdges(params Vertex<T>[] newNeighbors)
{
Neighbors.AddRange(newNeighbors);
}
public void AddEdges(IEnumerable<Vertex<T>> newNeighbors)
{
Neighbors.AddRange(newNeighbors);
}
public void RemoveEdge(Vertex<T> vertex)
{
Neighbors.Remove(vertex);
}
public override string ToString()
{
return Neighbors.Aggregate(new StringBuilder($"{Value}: "), (sb, n) => sb.Append($"{n.Value} ")).ToString();
//return $"{Value}: {(string.Join(" ", Neighbors.Select(n => n.Value)))}";
}
}
public void CheckVertices()
{
var la = new Vertex<string>("Los Angeles");
var sf = new Vertex<string>("San Francisco");
var lv = new Vertex<string>("Las Vegas");
var se = new Vertex<string>("Seattle");
var au = new Vertex<string>("Austin");
var po = new Vertex<string>("Portland");
var testGraph = new UndirectedGenericGraph<string>();
// la <=> sf, lv, po
testGraph.AddPair(la, sf);
testGraph.AddPair(la, lv);
testGraph.AddPair(la, po);
// sf <=> se, po
testGraph.AddPair(sf, se);
testGraph.AddPair(sf, po);
// lv <=> au
testGraph.AddPair(lv, au);
// se <=> po
testGraph.AddPair(se, po);
// Check to see that all neighbors are properly set up
foreach (var vertex in testGraph.Vertices)
{
System.Diagnostics.Debug.WriteLine(vertex.ToString());
}
// Test searching algorithms
testGraph.DepthFirstSearch(la, (m) => System.Diagnostics.Debug.WriteLine(m));
}
class UndirectedGenericGraph<T>
{
public UndirectedGenericGraph(params Vertex<T>[] initialNodes)
: this((IEnumerable<Vertex<T>>)initialNodes) { }
public UndirectedGenericGraph(IEnumerable<Vertex<T>> initialNodes = null)
{
Vertices = initialNodes?.ToList() ?? new List<Vertex<T>>();
}
public List<Vertex<T>> Vertices { get; }
public int Size => Vertices.Count;
public void AddPair(Vertex<T> first, Vertex<T> second)
{
AddToList(first);
AddToList(second);
AddNeighbors(first, second);
}
public void DepthFirstSearch(Vertex<T> root, Action<string> writer)
{
UnvisitAll();
DepthFirstSearchImplementation(root, writer);
}
private void DepthFirstSearchImplementation(Vertex<T> root, Action<string> writer)
{
if (!root.IsVisited)
{
writer($"{root.Value} ");
root.IsVisited = true;
foreach (Vertex<T> neighbor in root.Neighbors)
{
DepthFirstSearchImplementation(neighbor, writer);
}
}
}
private void AddToList(Vertex<T> vertex)
{
if (!Vertices.Contains(vertex))
{
Vertices.Add(vertex);
}
}
private void AddNeighbors(Vertex<T> first, Vertex<T> second)
{
AddNeighbor(first, second);
AddNeighbor(second, first);
}
private void AddNeighbor(Vertex<T> first, Vertex<T> second)
{
if (!first.Neighbors.Contains(second))
{
first.AddEdge(second);
}
}
private void UnvisitAll()
{
foreach(var vertex in Vertices)
{
vertex.IsVisited = false;
}
}
}
class DeepthFirstIterator<T>
{
private readonly Vertex<T> root;
private readonly HashSet<Vertex<T>> visited = new HashSet<Vertex<T>>();
public DeepthFirstIterator(Vertex<T> rootVertex)
{
root = rootVertex;
}
public IEnumerable<Vertex<T>> Iterate()
{
visited.Clear();
return DepthFirstSearch(root, visited);
}
private IEnumerable<Vertex<T>> DepthFirstSearch(Vertex<T> vertex, HashSet<Vertex<T>> visited)
{
if (visited.Contains(vertex))
yield break;
visited.Add(vertex);
yield return vertex;
foreach (Vertex<T> neighbor in vertex.Neighbors.SelectMany(n => DepthFirstSearch(n, visited)))
yield return neighbor;
}
}
{
List<Vertex<T>> neighbors;
T value;
bool isVisited;
public List<Vertex<T>> Neighbors { get { return neighbors; } set { neighbors = value; } }
public T Value { get { return value; } set { this.value = value; } }
public bool IsVisited { get { return isVisited; } set { isVisited = value; } }
public int NeighborsCount { get { return neighbors.Count; } }
public Vertex(T value)
{
this.value = value;
isVisited = false;
neighbors = new List<Vertex<T>>();
}
public Vertex(T value, List<Vertex<T>> neighbors)
{
this.value = value;
isVisited = false;
this.neighbors = neighbors;
}
public void Visit()
{
isVisited = true;
}
public void AddEdge(Vertex<T> vertex)
{
neighbors.Add(vertex);
}
public void AddEdges(List<Vertex<T>> newNeighbors)
{
neighbors.AddRange(newNeighbors);
}
public void RemoveEdge(Vertex<T> vertex)
{
neighbors.Remove(vertex);
}
public override string ToString()
{
StringBuilder allNeighbors = new StringBuilder("");
allNeighbors.Append(value + ": ");
foreach (Vertex<T> neighbor in neighbors)
{
allNeighbors.Append(neighbor.value + " ");
}
return allNeighbors.ToString();
}
}
class UndirectedGenericGraph<T>
{
// The list of vertices in the graph
private List<Vertex<T>> vertices;
// The number of vertices
int size;
public List<Vertex<T>> Vertices { get { return vertices; } }
public int Size { get { return vertices.Count; } }
public UndirectedGenericGraph(int initialSize)
{
if(size < 0)
{
throw new ArgumentException("Number of vertices cannot be negative");
}
size = initialSize;
vertices = new List<Vertex<T>>(initialSize);
}
public UndirectedGenericGraph(List<Vertex<T>> initialNodes)
{
vertices = initialNodes;
size = vertices.Count;
}
public void AddVertex(Vertex<T> vertex)
{
vertices.Add(vertex);
}
public void RemoveVertex(Vertex<T> vertex)
{
vertices.Remove(vertex);
}
public bool HasVertex(Vertex<T> vertex)
{
return vertices.Contains(vertex);
}
public void DepthFirstSearch(Vertex<T> root)
{
if (!root.IsVisited)
{
Console.Write(root.Value + " ");
root.Visit();
foreach(Vertex<T> neighbor in root.Neighbors)
{
DepthFirstSearch(neighbor);
}
}
}
public void BreadthFirstSearch(Vertex<T> root)
{
Queue<Vertex<T>> queue = new Queue<Vertex<T>>();
root.Visit();
queue.Enqueue(root);
while(queue.Count > 0)
{
Vertex<T> current = queue.Dequeue();
foreach (Vertex<T> neighbor in current.Neighbors)
{
if (!neighbor.IsVisited)
{
Console.Write(neighbor.Value + " ");
neighbor.Visit();
queue.Enqueue(neighbor);
}
}
}
}
}
class Program
{
static void Main(string[] args)
{
// Create a list of vertices using the Vertex<T> class
List<Vertex<string>> vertices = new List<Vertex<string>>
(
new Vertex<string> []
{
new Vertex<string>("Los Angeles"),
new Vertex<string>("San Francisco"),
new Vertex<string>("Las Vegas"),
new Vertex<string>("Seattle"),
new Vertex<string>("Austin"),
new Vertex<string>("Portland")
}
);
// Establish edges; Ex. Los Angeles -> San Francisco, Las Vegas, Portland
vertices[0].AddEdges(new List<Vertex<string>>(new Vertex<string>[]
{
vertices[1], vertices[2], vertices[5]
}));
vertices[1].AddEdges(new List<Vertex<string>>(new Vertex<string>[]
{
vertices[0], vertices[3], vertices[5]
}));
vertices[2].AddEdges(new List<Vertex<string>>(new Vertex<string>[]
{
vertices[0], vertices[1], vertices[4]
}));
vertices[3].AddEdges(new List<Vertex<string>>(new Vertex<string>[]
{
vertices[1], vertices[5]
}));
vertices[4].AddEdges(new List<Vertex<string>>(new Vertex<string>[]
{
vertices[2]
}));
vertices[5].AddEdges(new List<Vertex<string>>(new Vertex<string>[]
{
vertices[1], vertices[3]
}));
// Create graph using the UndirectedGenericGraph<T> class
UndirectedGenericGraph<string> testGraph = new UndirectedGenericGraph<string>(vertices);
// Check to see that all neighbors are properly set up
foreach(Vertex<string> vertex in vertices)
{
Console.WriteLine(vertex.ToString());
}
// Test searching algorithms
testGraph.DepthFirstSearch(vertices[0]);
//testGraph.BreadthFirstSearch(vertices[0]);
}
}
class Vertex<T>
{
public Vertex(T value, params Vertex<T>[] parameters)
: this(value, (IEnumerable<Vertex<T>>)parameters) { }
public Vertex(T value, IEnumerable<Vertex<T>> neighbors = null)
{
Value = value;
Neighbors = neighbors?.ToList() ?? new List<Vertex<T>>();
IsVisited = false; // can be omitted, default is false but some
// people like to have everything explicitly
// initialized
}
public T Value { get; } // can be made writable
public List<Vertex<T>> Neighbors { get; }
public bool IsVisited { get; set; }
public int NeighborCount => Neighbors.Count;
public void AddEdge(Vertex<T> vertex)
{
Neighbors.Add(vertex);
}
public void AddEdges(params Vertex<T>[] newNeighbors)
{
Neighbors.AddRange(newNeighbors);
}
public void AddEdges(IEnumerable<Vertex<T>> newNeighbors)
{
Neighbors.AddRange(newNeighbors);
}
public void RemoveEdge(Vertex<T> vertex)
{
Neighbors.Remove(vertex);
}
public override string ToString()
{
return Neighbors.Aggregate(new StringBuilder($"{Value}: "), (sb, n) => sb.Append($"{n.Value} ")).ToString();
//return $"{Value}: {(string.Join(" ", Neighbors.Select(n => n.Value)))}";
}
}
public void CheckVertices()
{
var la = new Vertex<string>("Los Angeles");
var sf = new Vertex<string>("San Francisco");
var lv = new Vertex<string>("Las Vegas");
var se = new Vertex<string>("Seattle");
var au = new Vertex<string>("Austin");
var po = new Vertex<string>("Portland");
var testGraph = new UndirectedGenericGraph<string>();
// la <=> sf, lv, po
testGraph.AddPair(la, sf);
testGraph.AddPair(la, lv);
testGraph.AddPair(la, po);
// sf <=> se, po
testGraph.AddPair(sf, se);
testGraph.AddPair(sf, po);
// lv <=> au
testGraph.AddPair(lv, au);
// se <=> po
testGraph.AddPair(se, po);
// Check to see that all neighbors are properly set up
foreach (var vertex in testGraph.Vertices)
{
System.Diagnostics.Debug.WriteLine(vertex.ToString());
}
// Test searching algorithms
testGraph.DepthFirstSearch(la, (m) => System.Diagnostics.Debug.WriteLine(m));
}
class UndirectedGenericGraph<T>
{
public UndirectedGenericGraph(params Vertex<T>[] initialNodes)
: this((IEnumerable<Vertex<T>>)initialNodes) { }
public UndirectedGenericGraph(IEnumerable<Vertex<T>> initialNodes = null)
{
Vertices = initialNodes?.ToList() ?? new List<Vertex<T>>();
}
public List<Vertex<T>> Vertices { get; }
public int Size => Vertices.Count;
public void AddPair(Vertex<T> first, Vertex<T> second)
{
AddToList(first);
AddToList(second);
AddNeighbors(first, second);
}
public void DepthFirstSearch(Vertex<T> root, Action<string> writer)
{
UnvisitAll();
DepthFirstSearchImplementation(root, writer);
}
private void DepthFirstSearchImplementation(Vertex<T> root, Action<string> writer)
{
if (!root.IsVisited)
{
writer($"{root.Value} ");
root.IsVisited = true;
foreach (Vertex<T> neighbor in root.Neighbors)
{
DepthFirstSearchImplementation(neighbor, writer);
}
}
}
private void AddToList(Vertex<T> vertex)
{
if (!Vertices.Contains(vertex))
{
Vertices.Add(vertex);
}
}
private void AddNeighbors(Vertex<T> first, Vertex<T> second)
{
AddNeighbor(first, second);
AddNeighbor(second, first);
}
private void AddNeighbor(Vertex<T> first, Vertex<T> second)
{
if (!first.Neighbors.Contains(second))
{
first.AddEdge(second);
}
}
private void UnvisitAll()
{
foreach(var vertex in Vertices)
{
vertex.IsVisited = false;
}
}
}
class DeepthFirstIterator<T>
{
private readonly Vertex<T> root;
private readonly HashSet<Vertex<T>> visited = new HashSet<Vertex<T>>();
public DeepthFirstIterator(Vertex<T> rootVertex)
{
root = rootVertex;
}
public IEnumerable<Vertex<T>> Iterate()
{
visited.Clear();
return DepthFirstSearch(root, visited);
}
private IEnumerable<Vertex<T>> DepthFirstSearch(Vertex<T> vertex, HashSet<Vertex<T>> visited)
{
if (visited.Contains(vertex))
yield break;
visited.Add(vertex);
yield return vertex;
foreach (Vertex<T> neighbor in vertex.Neighbors.SelectMany(n => DepthFirstSearch(n, visited)))
yield return neighbor;
}
}
No comments:
Post a Comment