mirror of
https://hub.njuu.cf/TheAlgorithms/Python.git
synced 2023-10-11 13:06:12 +08:00
Graph list patch (#4113)
* new implementation for adjacency list graph * add example code for undirected graph * reduce length to 88 columns max to fix build errors7 * fix pre commit issues * replace print_list method with __str__ * return object in add_edge method to enable fluent syntax * improve class docstring and include doctests * add end of file line * fix pre-commit issues * remove __str__ method * trigger build * Update graph_list.py * Update graph_list.py Co-authored-by: gnc <chidieberen1999@gmail.com> Co-authored-by: Christian Clauss <cclauss@me.com>
This commit is contained in:
parent
677d48d6c0
commit
03d34350f6
@ -1,44 +1,143 @@
|
||||
#!/usr/bin/python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Author: OMKAR PATHAK
|
||||
# Author: OMKAR PATHAK, Nwachukwu Chidiebere
|
||||
|
||||
# We can use Python's dictionary for constructing the graph.
|
||||
# Use a Python dictionary to construct the graph.
|
||||
|
||||
from pprint import pformat
|
||||
|
||||
|
||||
class AdjacencyList:
|
||||
def __init__(self):
|
||||
self.adj_list = {}
|
||||
class GraphAdjacencyList:
|
||||
"""
|
||||
Adjacency List type Graph Data Structure that accounts for directed and undirected
|
||||
Graphs. Initialize graph object indicating whether it's directed or undirected.
|
||||
|
||||
def add_edge(self, from_vertex: int, to_vertex: int) -> None:
|
||||
# check if vertex is already present
|
||||
if from_vertex in self.adj_list:
|
||||
self.adj_list[from_vertex].append(to_vertex)
|
||||
else:
|
||||
self.adj_list[from_vertex] = [to_vertex]
|
||||
Directed graph example:
|
||||
>>> d_graph = GraphAdjacencyList()
|
||||
>>> d_graph
|
||||
{}
|
||||
>>> d_graph.add_edge(0, 1)
|
||||
{0: [1], 1: []}
|
||||
>>> d_graph.add_edge(1, 2).add_edge(1, 4).add_edge(1, 5)
|
||||
{0: [1], 1: [2, 4, 5], 2: [], 4: [], 5: []}
|
||||
>>> d_graph.add_edge(2, 0).add_edge(2, 6).add_edge(2, 7)
|
||||
{0: [1], 1: [2, 4, 5], 2: [0, 6, 7], 4: [], 5: [], 6: [], 7: []}
|
||||
>>> print(d_graph)
|
||||
{0: [1], 1: [2, 4, 5], 2: [0, 6, 7], 4: [], 5: [], 6: [], 7: []}
|
||||
>>> print(repr(d_graph))
|
||||
{0: [1], 1: [2, 4, 5], 2: [0, 6, 7], 4: [], 5: [], 6: [], 7: []}
|
||||
|
||||
def print_list(self) -> None:
|
||||
for i in self.adj_list:
|
||||
print((i, "->", " -> ".join([str(j) for j in self.adj_list[i]])))
|
||||
Undirected graph example:
|
||||
>>> u_graph = GraphAdjacencyList(directed=False)
|
||||
>>> u_graph.add_edge(0, 1)
|
||||
{0: [1], 1: [0]}
|
||||
>>> u_graph.add_edge(1, 2).add_edge(1, 4).add_edge(1, 5)
|
||||
{0: [1], 1: [0, 2, 4, 5], 2: [1], 4: [1], 5: [1]}
|
||||
>>> u_graph.add_edge(2, 0).add_edge(2, 6).add_edge(2, 7)
|
||||
{0: [1, 2], 1: [0, 2, 4, 5], 2: [1, 0, 6, 7], 4: [1], 5: [1], 6: [2], 7: [2]}
|
||||
>>> u_graph.add_edge(4, 5)
|
||||
{0: [1, 2],
|
||||
1: [0, 2, 4, 5],
|
||||
2: [1, 0, 6, 7],
|
||||
4: [1, 5],
|
||||
5: [1, 4],
|
||||
6: [2],
|
||||
7: [2]}
|
||||
>>> print(u_graph)
|
||||
{0: [1, 2],
|
||||
1: [0, 2, 4, 5],
|
||||
2: [1, 0, 6, 7],
|
||||
4: [1, 5],
|
||||
5: [1, 4],
|
||||
6: [2],
|
||||
7: [2]}
|
||||
>>> print(repr(u_graph))
|
||||
{0: [1, 2],
|
||||
1: [0, 2, 4, 5],
|
||||
2: [1, 0, 6, 7],
|
||||
4: [1, 5],
|
||||
5: [1, 4],
|
||||
6: [2],
|
||||
7: [2]}
|
||||
"""
|
||||
|
||||
def __init__(self, directed: bool = True):
|
||||
"""
|
||||
Parameters:
|
||||
directed: (bool) Indicates if graph is directed or undirected. Default is True.
|
||||
"""
|
||||
|
||||
self.adj_list = {} # dictionary of lists
|
||||
self.directed = directed
|
||||
|
||||
def add_edge(self, source_vertex: int, destination_vertex: int) -> object:
|
||||
"""
|
||||
Connects vertices together. Creates and Edge from source vertex to destination
|
||||
vertex.
|
||||
Vertices will be created if not found in graph
|
||||
"""
|
||||
|
||||
if not self.directed: # For undirected graphs
|
||||
# if both source vertex and destination vertex are both present in the
|
||||
# adjacency list, add destination vertex to source vertex list of adjacent
|
||||
# vertices and add source vertex to destination vertex list of adjacent
|
||||
# vertices.
|
||||
if source_vertex in self.adj_list and destination_vertex in self.adj_list:
|
||||
self.adj_list[source_vertex].append(destination_vertex)
|
||||
self.adj_list[destination_vertex].append(source_vertex)
|
||||
# if only source vertex is present in adjacency list, add destination vertex
|
||||
# to source vertex list of adjacent vertices, then create a new vertex with
|
||||
# destination vertex as key and assign a list containing the source vertex
|
||||
# as it's first adjacent vertex.
|
||||
elif source_vertex in self.adj_list:
|
||||
self.adj_list[source_vertex].append(destination_vertex)
|
||||
self.adj_list[destination_vertex] = [source_vertex]
|
||||
# if only destination vertex is present in adjacency list, add source vertex
|
||||
# to destination vertex list of adjacent vertices, then create a new vertex
|
||||
# with source vertex as key and assign a list containing the source vertex
|
||||
# as it's first adjacent vertex.
|
||||
elif destination_vertex in self.adj_list:
|
||||
self.adj_list[destination_vertex].append(source_vertex)
|
||||
self.adj_list[source_vertex] = [destination_vertex]
|
||||
# if both source vertex and destination vertex are not present in adjacency
|
||||
# list, create a new vertex with source vertex as key and assign a list
|
||||
# containing the destination vertex as it's first adjacent vertex also
|
||||
# create a new vertex with destination vertex as key and assign a list
|
||||
# containing the source vertex as it's first adjacent vertex.
|
||||
else:
|
||||
self.adj_list[source_vertex] = [destination_vertex]
|
||||
self.adj_list[destination_vertex] = [source_vertex]
|
||||
else: # For directed graphs
|
||||
# if both source vertex and destination vertex are present in adjacency
|
||||
# list, add destination vertex to source vertex list of adjacent vertices.
|
||||
if source_vertex in self.adj_list and destination_vertex in self.adj_list:
|
||||
self.adj_list[source_vertex].append(destination_vertex)
|
||||
# if only source vertex is present in adjacency list, add destination
|
||||
# vertex to source vertex list of adjacent vertices and create a new vertex
|
||||
# with destination vertex as key, which has no adjacent vertex
|
||||
elif source_vertex in self.adj_list:
|
||||
self.adj_list[source_vertex].append(destination_vertex)
|
||||
self.adj_list[destination_vertex] = []
|
||||
# if only destination vertex is present in adjacency list, create a new
|
||||
# vertex with source vertex as key and assign a list containing destination
|
||||
# vertex as first adjacent vertex
|
||||
elif destination_vertex in self.adj_list:
|
||||
self.adj_list[source_vertex] = [destination_vertex]
|
||||
# if both source vertex and destination vertex are not present in adjacency
|
||||
# list, create a new vertex with source vertex as key and a list containing
|
||||
# destination vertex as it's first adjacent vertex. Then create a new vertex
|
||||
# with destination vertex as key, which has no adjacent vertex
|
||||
else:
|
||||
self.adj_list[source_vertex] = [destination_vertex]
|
||||
self.adj_list[destination_vertex] = []
|
||||
|
||||
return self
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return pformat(self.adj_list)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
al = AdjacencyList()
|
||||
al.add_edge(0, 1)
|
||||
al.add_edge(0, 4)
|
||||
al.add_edge(4, 1)
|
||||
al.add_edge(4, 3)
|
||||
al.add_edge(1, 0)
|
||||
al.add_edge(1, 4)
|
||||
al.add_edge(1, 3)
|
||||
al.add_edge(1, 2)
|
||||
al.add_edge(2, 3)
|
||||
al.add_edge(3, 4)
|
||||
import doctest
|
||||
|
||||
al.print_list()
|
||||
|
||||
# OUTPUT:
|
||||
# 0 -> 1 -> 4
|
||||
# 1 -> 0 -> 4 -> 3 -> 2
|
||||
# 2 -> 3
|
||||
# 3 -> 4
|
||||
# 4 -> 1 -> 3
|
||||
doctest.testmod()
|
||||
|
Loading…
Reference in New Issue
Block a user