Skip to content

Commit b2d46fb

Browse files
committed
Graph with Adjecency map implementation
Graph with Adjecency map implementation lightweight however
1 parent 5f82e40 commit b2d46fb

File tree

1 file changed

+124
-0
lines changed

1 file changed

+124
-0
lines changed

Graphs/Graph.py

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
class Vertex:
2+
"""Lighweight vertex structure for a graph"""
3+
__slots__ = '_element'
4+
5+
def __init__(self, x):
6+
"""Should not call the constructor directly, instead we should use the insert_vertex(x) method
7+
to create the vertex object"""
8+
self._element = x
9+
10+
def element(self):
11+
"""return element associated with thi vertex"""
12+
return self._element
13+
14+
def __hash__(self): # will allow vertex to be a map/set key
15+
return hash(id(self))
16+
17+
class Edge:
18+
"""Lighweight edge structure for a graph"""
19+
20+
__slots__ = '_origin', '_destination', '_element'
21+
22+
def __init__(self, u, v, x):
23+
"""Should not call constructor directly use, insert_edge(u , v ,x) method from graph class to create
24+
edge object"""
25+
self._origin = u
26+
self._destination = v
27+
self._element = x
28+
29+
def element(self):
30+
"""return element associated with the edge"""
31+
return self._element
32+
33+
def endpoints(self):
34+
"""return the vertices (U,V) that are endpoints for this edge in a tuple form """
35+
return (self._origin, self._destination)
36+
37+
def opposite(self, v):
38+
"""Return the vertex opposite to v in this edge """
39+
40+
if v is self._origin:
41+
return self._destination
42+
else:
43+
return self._origin
44+
45+
def __hash__(self): # will allow wdge to be a map/set key
46+
return hash((self._origin, self._destination))
47+
48+
class Graph:
49+
"""Representation of a simple grahph using an adjacency map """
50+
51+
def __init__(self, directed=False):
52+
"""Create an empty graph, which is undirected by default
53+
54+
Graph is directed if we parameter driected is set to True in constructor call"""
55+
56+
self._outgoing = {} # map that will contain incident edges of vertex v
57+
# if map is directed we need an extra *in incident* map
58+
self._incoming = {} if directed else self._outgoing
59+
60+
def is_directed(self):
61+
"""Return true if the graph is a directed grph False otherwise
62+
63+
Property based on the original declaration of the graph, not its contents"""
64+
return self._incoming is not self._outgoing
65+
66+
def vertex_count(self):
67+
"""Return the number of vertices in the graph"""
68+
return len(self._outgoing)
69+
70+
def vertices(self):
71+
#return an iteration of vertices in the graph which are the keys to the incident map of outgoing endpoints
72+
return self._outgoing.keys()
73+
74+
def edge_count(self):
75+
"""Return the number of edges in the graph"""
76+
total = sum(len(self._outgoing[v]) for v in self._outgoing) # len of values for each key in incident map
77+
# for undirected graphs, do not double-count the edges
78+
return total if self.is_directed else total // 2
79+
80+
def edges(self):
81+
"""return a set of all edges of the graph"""
82+
result = set() # to avoid double-reporting edges of undirected graphs
83+
for secondary_map in self._outgoing.values():
84+
result.update(secondary_map.values) #Update a set with the union of itself and others.
85+
86+
return result
87+
88+
def get_edge(self, u, v):
89+
"""return the edge from u to v, or None if not adjacent"""
90+
return self._outgoing[u].get(v) #return None if v not adjacent
91+
92+
def degree(self, v, outgoing=True):
93+
"""Return the number of (outgoing) edges incident to vertex v in the graph
94+
95+
If graph is directed optional parameter used to count incoming edges """
96+
97+
adj = self._outgoing if outgoing else self._incoming
98+
99+
return len(adj[v])
100+
101+
def incident_edges(self, v, outgoing=True):
102+
"""Return all (outgoing) edges incident to vertex v in the graph
103+
104+
If graph is directed, optional parameter used to request incoming edges"""
105+
106+
adj = self._outgoing if outgoing else self._incoming
107+
for edge in adj[v].values():
108+
yield edge
109+
110+
def insert_vertex(self, x = None):
111+
"""Insert and return a new Vertex with element x"""
112+
113+
vertex = self.Vertex(x)
114+
self._outgoing[vertex] = {} # new vertex will contain empty map of icidency
115+
if self.is_directed():
116+
self._incoming[v] = {} # if directed graph 2 incidency maps are needed.
117+
118+
return vertex
119+
120+
def insert_edge(self, u, v, x = None):
121+
"""Inser and return a new Edge from u to v with auxiliary element x"""
122+
e = self.Edge(u, v, x)
123+
self._outgoing[u][v] = e
124+
self.incident_edges[v][u] = e

0 commit comments

Comments
 (0)