Skip to content

Fix inconsistent index and count when removing vertex from Graph. #451

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 101 additions & 0 deletions DataStructures.Tests/Graph/DirectedWeightedGraphTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,107 @@ public void GraphRemoveVertexTest_Success()
graph.GetNeighbors(vertexC).Should().HaveCount(0);
}

[Test]
public void GraphRemoveAndAddVertexTest_Success()
{
double weight_A_B = 1;
double weight_A_C = 2;
double weight_A_D = 3;
double weight_B_A = 4;
double weight_B_C = 5;
double weight_C_A = 6;
double weight_C_B = 7;
double weight_C_D = 8;
double weight_D_A = 9;
double weight_D_C = 10;

var graph = new DirectedWeightedGraph<char>(10);
var vertexA = graph.AddVertex('A');
var vertexB = graph.AddVertex('B');
var vertexC = graph.AddVertex('C');
graph.AddEdge(vertexA, vertexB, weight_A_B);
graph.AddEdge(vertexA, vertexC, weight_A_C);
graph.AddEdge(vertexB, vertexA, weight_B_A);
graph.AddEdge(vertexB, vertexC, weight_B_C);
graph.AddEdge(vertexC, vertexA, weight_C_A);
graph.AddEdge(vertexC, vertexB, weight_C_B);

var vertexA_Index_BeforeUpdate = vertexA.Index;
vertexA_Index_BeforeUpdate.Should().Be(0);
var neighborsA_BeforeUpdate = graph.GetNeighbors(vertexA).ToList();
neighborsA_BeforeUpdate.Should().HaveCount(2);
neighborsA_BeforeUpdate[0].Should().Be(vertexB);
neighborsA_BeforeUpdate[1].Should().Be(vertexC);

var vertexB_Index_BeforeUpdate = vertexB.Index;
vertexB_Index_BeforeUpdate.Should().Be(1);
var neighborsB_BeforeUpdate = graph.GetNeighbors(vertexB).ToList();
neighborsB_BeforeUpdate.Should().HaveCount(2);
neighborsB_BeforeUpdate[0].Should().Be(vertexA);
neighborsB_BeforeUpdate[1].Should().Be(vertexC);

var vertexC_Index_BeforeUpdate = vertexC.Index;
vertexC_Index_BeforeUpdate.Should().Be(2);
var neighborsC_BeforeUpdate = graph.GetNeighbors(vertexC).ToList();
neighborsC_BeforeUpdate.Should().HaveCount(2);
neighborsC_BeforeUpdate[0].Should().Be(vertexA);
neighborsC_BeforeUpdate[1].Should().Be(vertexB);

var weight_A_B_BeforeUpdate = graph.AdjacentDistance(vertexA, vertexB);
var weight_A_C_BeforeUpdate = graph.AdjacentDistance(vertexA, vertexC);
var weight_B_A_BeforeUpdate = graph.AdjacentDistance(vertexB, vertexA);
var weight_B_C_BeforeUpdate = graph.AdjacentDistance(vertexB, vertexC);
var weight_C_A_BeforeUpdate = graph.AdjacentDistance(vertexC, vertexA);
var weight_C_B_BeforeUpdate = graph.AdjacentDistance(vertexC, vertexB);
weight_A_B_BeforeUpdate.Should().Be(weight_A_B);
weight_A_C_BeforeUpdate.Should().Be(weight_A_C);
weight_B_A_BeforeUpdate.Should().Be(weight_B_A);
weight_B_C_BeforeUpdate.Should().Be(weight_B_C);
weight_C_A_BeforeUpdate.Should().Be(weight_C_A);
weight_C_B_BeforeUpdate.Should().Be(weight_C_B);

graph.RemoveVertex(vertexB);
var vertexD = graph.AddVertex('D');
graph.AddEdge(vertexA, vertexD, weight_A_D);
graph.AddEdge(vertexC, vertexD, weight_C_D);
graph.AddEdge(vertexD, vertexA, weight_D_A);
graph.AddEdge(vertexD, vertexC, weight_D_C);

var vertexA_Index_AfterUpdate = vertexA.Index;
vertexA_Index_AfterUpdate.Should().Be(0);
var neighborsA_AfterUpdate = graph.GetNeighbors(vertexA).ToList();
neighborsA_AfterUpdate.Should().HaveCount(2);
neighborsA_AfterUpdate[0].Should().Be(vertexC);
neighborsA_AfterUpdate[1].Should().Be(vertexD);

var vertexC_Index_AfterUpdate = vertexC.Index;
vertexC_Index_AfterUpdate.Should().Be(1);
var neighborsC_AfterUpdate = graph.GetNeighbors(vertexC).ToList();
neighborsC_AfterUpdate.Should().HaveCount(2);
neighborsC_AfterUpdate[0].Should().Be(vertexA);
neighborsC_AfterUpdate[1].Should().Be(vertexD);

var vertexD_Index_AfterUpdate = vertexD.Index;
vertexD_Index_AfterUpdate.Should().Be(2);
var neighborsD_AfterUpdate = graph.GetNeighbors(vertexD).ToList();
neighborsD_AfterUpdate.Should().HaveCount(2);
neighborsD_AfterUpdate[0].Should().Be(vertexA);
neighborsD_AfterUpdate[1].Should().Be(vertexC);

var weight_A_C_AfterUpdate = graph.AdjacentDistance(vertexA, vertexC);
var weight_A_D_AfterUpdate = graph.AdjacentDistance(vertexA, vertexD);
var weight_C_A_AfterUpdate = graph.AdjacentDistance(vertexC, vertexA);
var weight_C_D_AfterUpdate = graph.AdjacentDistance(vertexC, vertexD);
var weight_D_A_AfterUpdate = graph.AdjacentDistance(vertexD, vertexA);
var weight_D_C_AfterUpdate = graph.AdjacentDistance(vertexD, vertexC);
weight_A_D_AfterUpdate.Should().Be(weight_A_D);
weight_A_C_AfterUpdate.Should().Be(weight_A_C);
weight_D_A_AfterUpdate.Should().Be(weight_D_A);
weight_D_C_AfterUpdate.Should().Be(weight_D_C);
weight_C_A_AfterUpdate.Should().Be(weight_C_A);
weight_C_D_AfterUpdate.Should().Be(weight_C_D);
}

[Test]
public void GraphRemoveVertexTest_ShouldThrowVertexNotInGraph()
{
Expand Down
44 changes: 40 additions & 4 deletions DataStructures/Graph/DirectedWeightedGraph.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,49 @@ public void RemoveVertex(Vertex<T> vertex)
{
ThrowIfVertexNotInGraph(vertex);

Vertices[vertex.Index] = null;
int indexToRemove = vertex.Index;
vertex.Index = -1;
vertex.SetGraphNull();

for (var i = 0; i < Count; i++)
// Update the vertex array and the index of vertices.
for (int i = indexToRemove; i < Count - 1; i++)
{
adjacencyMatrix[i, vertex.Index] = 0;
adjacencyMatrix[vertex.Index, i] = 0;
Vertices[i] = Vertices[i + 1];
Vertices[i] !.Index = i;
}

Vertices[Count - 1] = null;

// Update adjacency matrix to remove the row and column of the removed vertex.
for (int i = 0; i < Count; i++)
{
for (int j = 0; j < Count; j++)
{
if (i < indexToRemove && j < indexToRemove)
{
continue;
}
else if (i < indexToRemove && j >= indexToRemove && j < Count - 1)
{
adjacencyMatrix[i, j] = adjacencyMatrix[i, j + 1];
}
else if (i >= indexToRemove && i < Count - 1 && j < indexToRemove)
{
adjacencyMatrix[i, j] = adjacencyMatrix[i + 1, j];
}
else if (i >= indexToRemove && i < Count - 1 && j >= indexToRemove && j < Count - 1)
{
adjacencyMatrix[i, j] = adjacencyMatrix[i + 1, j + 1];
}
else if (i == Count - 1 || j == Count - 1)
{
adjacencyMatrix[i, j] = 0;
}
else
{
throw new InvalidOperationException();
}
}
}

Count--;
Expand Down
2 changes: 1 addition & 1 deletion DataStructures/Graph/Vertex.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class Vertex<T>
/// <summary>
/// Gets an index of the vertex in graph adjacency matrix.
/// </summary>
public int Index { get; }
public int Index { get; internal set; }

/// <summary>
/// Gets reference to the graph this vertex belongs to.
Expand Down