Skip to content

Commit 109a592

Browse files
committed
Implement undirected adjacency list with unit tests
1 parent 1226a9d commit 109a592

File tree

3 files changed

+133
-0
lines changed

3 files changed

+133
-0
lines changed

algorithms/data_structures/__init__.py

Whitespace-only changes.
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
"""
2+
undirected_adjacency_matrix.py
3+
4+
Implementation of a graph as an undirected adjacency matrix.
5+
6+
Undirected Adjacency Matrix Overview:
7+
--------------------------------------
8+
Edges are stored as a two-dimensional matrix of weights.
9+
Vertices are represented as the rows and columns of the matrix.
10+
Since the graph is undirected, for any two vertices x and y:
11+
edge(x,y) == edge(y,x)
12+
13+
14+
Time complexity:
15+
----------------
16+
V = Number of vertices
17+
18+
Storage: O(V**2)
19+
Add vertex: O(V**2)
20+
Add edge: O(1)
21+
Remove vertex: O(v**2)
22+
Remove edge: O(1)
23+
Query: O(1)
24+
25+
Graph comparison: http://en.wikipedia.org/wiki/Graph_(abstract_data_type)
26+
Wiki: http://en.wikipedia.org/wiki/Adjacency_matrix
27+
28+
"""
29+
30+
31+
class UndirectedAdjacencyMatrix:
32+
def __init__(self):
33+
self.edge = {}
34+
self.numVertices = 0
35+
36+
def addVertex(self, key):
37+
if key in self.edge:
38+
return
39+
self.edge[key] = {v: float('inf') for v in self.edge}
40+
for i in self.edge:
41+
self.edge[i][key] = float('inf')
42+
self.numVertices += 1
43+
44+
def removeVertex(self, key):
45+
if key not in self.edge:
46+
return
47+
del self.edge[key]
48+
for i in self.edge:
49+
del self.edge[i][key]
50+
self.numVertices -= 1
51+
52+
def addEdge(self, x, y, weight = 1):
53+
if all (v in self.edge for v in (x, y)):
54+
self.edge[x][y] = self.edge[y][x] = weight
55+
56+
def removeEdge(self, x, y):
57+
if all (v in self.edge for v in (x, y)):
58+
self.edge[x][y] = self.edge[y][x] = float('inf')
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
""" Unit Tests for data structures """
2+
import unittest
3+
from ..data_structures import undirected_adjacency_matrix
4+
5+
6+
class TestUndirectedAdjacencyMatrix(unittest.TestCase):
7+
"""
8+
Tests edge cases for Undirected Adjacency Matrix
9+
"""
10+
11+
def setUp(self):
12+
self.graph = undirected_adjacency_matrix.UndirectedAdjacencyMatrix()
13+
self.expected = []
14+
15+
#Test empty graph
16+
self.expected.append({})
17+
18+
#Test adding vertices
19+
self.expected.append({v: {i: float('inf') for i in range(20)}
20+
for v in range(20)})
21+
22+
#Test removing vertices
23+
self.expected.append({v: {i: float('inf') for i in range(0, 20, 2)}
24+
for v in range(0, 20, 2)})
25+
26+
#Test adding edges
27+
self.expected.append({v: {i: 1 for i in range(0, 20, 2)}
28+
for v in range(0, 20, 2)})
29+
30+
#Test removing edges
31+
self.expected.append({v: {i: 1 if (i < 10 and v < 10) or
32+
(i >= 10 and v >= 10) else float('inf')
33+
for i in range(0, 20, 2)}
34+
for v in range(0, 20, 2)})
35+
36+
#Test empty graph after removing all vertices
37+
self.expected.append({})
38+
39+
def test_undirected_adjacency_matrix(self):
40+
#Test empty graph
41+
self.assertEqual(self.expected[0], self.graph.edge)
42+
43+
#Test adding vertices
44+
#Should result in 20 vertices with no edges
45+
for i in range(20):
46+
self.graph.addVertex(i)
47+
self.assertEqual(self.expected[1], self.graph.edge)
48+
49+
#Test removing vertices
50+
#Should result in 10 even-numbered vertices with no edges
51+
for i in range(1, 20, 2):
52+
self.graph.removeVertex(i)
53+
self.assertEqual(self.expected[2], self.graph.edge)
54+
55+
#Test adding edges
56+
#Should result in a complete graph
57+
for i in range(0, 20, 2):
58+
for j in range(0, 20, 2):
59+
self.graph.addEdge(i, j)
60+
self.assertEqual(self.expected[3], self.graph.edge)
61+
62+
#Test removing edges
63+
#Should result in two complete components: vertices 0-8, 10-18
64+
for i in range(0, 10, 2):
65+
for j in range(10, 20, 2):
66+
self.graph.removeEdge(i ,j)
67+
for i in range(10, 20, 2):
68+
for j in range(0, 10, 2):
69+
self.graph.removeEdge(i, j)
70+
self.assertEqual(self.expected[4], self.graph.edge)
71+
72+
#Test empty graph after removing all vertices
73+
for i in range(0, 20, 2):
74+
self.graph.removeVertex(i)
75+
self.assertEqual(self.expected[5], self.graph.edge)

0 commit comments

Comments
 (0)