#!/usr/bin/env python3
"""
Author: Vikram Nithyanandam
Description:
The following implementation is a robust unweighted Graph data structure
implemented using an adjacency matrix. This vertices and edges of this graph can be
effectively initialized and modified while storing your chosen generic
value in each vertex.
Adjacency Matrix: https://mathworld.wolfram.com/AdjacencyMatrix.html
Potential Future Ideas:
- Add a flag to set edge weights on and set edge weights
- Make edge weights and vertex values customizable to store whatever the client wants
- Support multigraph functionality if the client wants it
"""
from __future__ import annotations
import random
import unittest
from pprint import pformat
from typing import Generic, TypeVar
import pytest
T = TypeVar("T")
class GraphAdjacencyMatrix(Generic[T]):
def __init__(
self, vertices: list[T], edges: list[list[T]], directed: bool = True
) -> None:
"""
Parameters:
- vertices: (list[T]) The list of vertex names the client wants to
pass in. Default is empty.
- edges: (list[list[T]]) The list of edges the client wants to
pass in. Each edge is a 2-element list. Default is empty.
- directed: (bool) Indicates if graph is directed or undirected.
Default is True.
"""
self.directed = directed
self.vertex_to_index: dict[T, int] = {}
self.adj_matrix: list[list[int]] = []
# Falsey checks
edges = edges or []
vertices = vertices or []
for vertex in vertices:
self.add_vertex(vertex)
for edge in edges:
if len(edge) != 2:
msg = f"Invalid input: {edge} must have length 2."
raise ValueError(msg)
self.add_edge(edge[0], edge[1])
def add_edge(self, source_vertex: T, destination_vertex: T) -> None:
"""
Creates an edge from source vertex to destination vertex. If any
given vertex doesn't exist or the edge already exists, a ValueError
will be thrown.
"""
if not (
self.contains_vertex(source_vertex)
and self.contains_vertex(destination_vertex)
):
msg = (
f"Incorrect input: Either {source_vertex} or "
f"{destination_vertex} does not exist"
)
raise ValueError(msg)
if self.contains_edge(source_vertex, destination_vertex):
msg = (
"Incorrect input: The edge already exists between "
f"{source_vertex} and {destination_vertex}"
)
raise ValueError(msg)
# Get the indices of the corresponding vertices and set their edge value to 1.
u: int = self.vertex_to_index[source_vertex]
v: int = self.vertex_to_index[destination_vertex]
self.adj_matrix[u][v] = 1
if not self.directed:
self.adj_matrix[v][u] = 1
def remove_edge(self, source_vertex: T, destination_vertex: T) -> None:
"""
Removes the edge between the two vertices. If any given vertex
doesn't exist or the edge does not exist, a ValueError will be thrown.
"""
if not (
self.contains_vertex(source_vertex)
and self.contains_vertex(destination_vertex)
):
msg = (
f"Incorrect input: Either {source_vertex} or "
f"{destination_vertex} does not exist"
)
raise ValueError(msg)
if not self.contains_edge(source_vertex, destination_vertex):
msg = (
"Incorrect input: The edge does NOT exist between "
f"{source_vertex} and {destination_vertex}"
)
raise ValueError(msg)
# Get the indices of the corresponding vertices and set their edge value to 0.
u: int = self.vertex_to_index[source_vertex]
v: int = self.vertex_to_index[destination_vertex]
self.adj_matrix[u][v] = 0
if not self.directed:
self.adj_matrix[v][u] = 0
def add_vertex(self, vertex: T) -> None:
"""
Adds a vertex to the graph. If the given vertex already exists,
a ValueError will be thrown.
"""
if self.contains_vertex(vertex):
msg = f"Incorrect input: {vertex} already exists in this graph."
raise ValueError(msg)
# build column for vertex
for row in self.adj_matrix:
row.append(0)
# build row for vertex and update other data structures
self.adj_matrix.append([0] * (len(self.adj_matrix) + 1))
self.vertex_to_index[vertex] = len(self.adj_matrix) - 1
def remove_vertex(self, vertex: T) -> None:
"""
Removes the given vertex from the graph and deletes all incoming and
outgoing edges from the given vertex as well. If the given vertex
does not exist, a ValueError will be thrown.
"""
if not self.contains_vertex(vertex):
msg = f"Incorrect input: {vertex} does not exist in this graph."
raise ValueError(msg)
# first slide up the rows by deleting the row corresponding to
# the vertex being deleted.
start_index = self.vertex_to_index[vertex]
self.adj_matrix.pop(start_index)
# next, slide the columns to the left by deleting the values in
# the column corresponding to the vertex being deleted
for lst in self.adj_matrix:
lst.pop(start_index)
# final clean up
self.vertex_to_index.pop(vertex)
# decrement indices for vertices shifted by the deleted vertex in the adj matrix
for inner_vertex in self.vertex_to_index:
if self.vertex_to_index[inner_vertex] >= start_index:
self.vertex_to_index[inner_vertex] = (
self.vertex_to_index[inner_vertex] - 1
)
def contains_vertex(self, vertex: T) -> bool:
"""
Returns True if the graph contains the vertex, False otherwise.
"""
return vertex in self.vertex_to_index
def contains_edge(self, source_vertex: T, destination_vertex: T) -> bool:
"""
Returns True if the graph contains the edge from the source_vertex to the
destination_vertex, False otherwise. If any given vertex doesn't exist, a
ValueError will be thrown.
"""
if not (
self.contains_vertex(source_vertex)
and self.contains_vertex(destination_vertex)
):
msg = (
f"Incorrect input: Either {source_vertex} "
f"or {destination_vertex} does not exist."
)
raise ValueError(msg)
u = self.vertex_to_index[source_vertex]
v = self.vertex_to_index[destination_vertex]
return self.adj_matrix[u][v] == 1
def clear_graph(self) -> None:
"""
Clears all vertices and edges.
"""
self.vertex_to_index = {}
self.adj_matrix = []
def __repr__(self) -> str:
first = "Adj Matrix:\n" + pformat(self.adj_matrix)
second = "\nVertex to index mapping:\n" + pformat(self.vertex_to_index)
return first + second
class TestGraphMatrix(unittest.TestCase):
def __assert_graph_edge_exists_check(
self,
undirected_graph: GraphAdjacencyMatrix,
directed_graph: GraphAdjacencyMatrix,
edge: list[int],
) -> None:
assert undirected_graph.contains_edge(edge[0], edge[1])
assert undirected_graph.contains_edge(edge[1], edge[0])
assert directed_graph.contains_edge(edge[0], edge[1])
def __assert_graph_edge_does_not_exist_check(
self,
undirected_graph: GraphAdjacencyMatrix,
directed_graph: GraphAdjacencyMatrix,
edge: list[int],
) -> None:
assert not undirected_graph.contains_edge(edge[0], edge[1])
assert not
没有合适的资源?快使用搜索试试~ 我知道了~
python曲线图-graphs.rar
共62个文件
py:62个
需积分: 1 0 下载量 192 浏览量
2024-09-25
07:57:42
上传
评论
收藏 72KB RAR 举报
温馨提示
python曲线图-graphs.rar
资源推荐
资源详情
资源评论
收起资源包目录
graphs.rar (62个子文件)
graphs
even_tree.py 1KB
__init__.py 0B
g_topological_sort.py 946B
boruvka.py 6KB
deep_clone_graph.py 2KB
a_star.py 4KB
kahns_algorithm_long.py 772B
finding_bridges.py 3KB
bidirectional_breadth_first_search.py 6KB
edmonds_karp_multiple_source_and_sink.py 6KB
ant_colony_optimization_algorithms.py 8KB
frequent_pattern_graph_miner.py 7KB
basic_graphs.py 10KB
bellman_ford.py 2KB
multi_heuristic_astar.py 8KB
minimum_spanning_tree_prims2.py 9KB
greedy_best_first.py 5KB
graph_list.py 6KB
eulerian_path_and_circuit_for_undirected_graph.py 2KB
dijkstra_alternate.py 3KB
karger.py 3KB
dijkstra_2.py 2KB
graph_adjacency_list.py 21KB
prim.py 3KB
directed_and_undirected_weighted_graph.py 15KB
articulation_points.py 1KB
dijkstra_algorithm.py 15KB
tests
__init__.py 0B
test_min_spanning_tree_kruskal.py 667B
test_min_spanning_tree_prim.py 1001B
minimum_spanning_tree_prims.py 5KB
connected_components.py 1KB
graphs_floyd_warshall.py 3KB
strongly_connected_components.py 2KB
minimum_path_sum.py 2KB
scc_kosaraju.py 1KB
depth_first_search_2.py 3KB
tarjans_scc.py 3KB
depth_first_search.py 1KB
check_bipatrite.py 6KB
breadth_first_search_shortest_path_2.py 3KB
breadth_first_search_2.py 2KB
bidirectional_a_star.py 8KB
breadth_first_search_zero_one_shortest_path.py 5KB
kahns_algorithm_topo.py 817B
graph_adjacency_matrix.py 22KB
dinic.py 3KB
minimum_spanning_tree_kruskal2.py 4KB
matching_min_vertex_cover.py 2KB
bi_directional_dijkstra.py 3KB
dijkstra_binary_grid.py 3KB
page_rank.py 1KB
minimum_spanning_tree_boruvka.py 6KB
greedy_min_vertex_cover.py 2KB
breadth_first_search.py 2KB
random_graph_generator.py 2KB
markov_chain.py 2KB
breadth_first_search_shortest_path.py 3KB
gale_shapley_bigraph.py 2KB
check_cycle.py 2KB
minimum_spanning_tree_kruskal.py 1KB
dijkstra.py 3KB
共 62 条
- 1
资源评论
蜡笔小流
- 粉丝: 2335
- 资源: 1186
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- C语言-leetcode题解之28-implement-strstr.c
- C语言-leetcode题解之27-remove-element.c
- C语言-leetcode题解之26-remove-duplicates-from-sorted-array.c
- C语言-leetcode题解之24-swap-nodes-in-pairs.c
- C语言-leetcode题解之22-generate-parentheses.c
- C语言-leetcode题解之21-merge-two-sorted-lists.c
- java-leetcode题解之Online Stock Span.java
- java-leetcode题解之Online Majority Element In Subarray.java
- java-leetcode题解之Odd Even Jump.java
- 计算机毕业设计:python+爬虫+cnki网站爬
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功