Skip to content

Commit

Permalink
Fix inconsistent index and count when removing vertex from Graph (#451)
Browse files Browse the repository at this point in the history
  • Loading branch information
AngLv committed May 5, 2024
1 parent f32c043 commit d28baa3
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 5 deletions.
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

0 comments on commit d28baa3

Please sign in to comment.