그래프(데이터 구조)를 Python으로 표현
어떻게 하면 파이썬에서 그래프를 깔끔하게 표현할 수 있습니까? (처음부터 시작합니다. 즉, 라이브러리가 없습니다!)
어떤 데이터 구조(예: dict/tuples/dict(tuples))가 빠르면서도 메모리 효율적입니까?
그것에 대해 다양한 그래프 연산을 할 수 있어야 합니다.
지적했듯이 다양한 그래프 표현이 도움이 될 수 있습니다.Python에서 이를 구현하려면 어떻게 해야 합니까?
도서관에 관해서는, 이 질문은 꽤 좋은 답을 가지고 있습니다.
비록 이것이 다소 오래된 질문이긴 하지만, 저는 이것을 우연히 발견한 사람들을 위해 실용적인 대답을 해줄 것이라고 생각했습니다.
연결에 대한 입력 데이터를 다음과 같은 튜플 목록으로 가져온다고 가정합니다.
[('A', 'B'), ('B', 'C'), ('B', 'D'), ('C', 'D'), ('E', 'F'), ('F', 'C')]
파이썬에서 그래프에 가장 유용하고 효율적인 데이터 구조는 집합의 딕트입니다.이것이 우리의 기본 구조가 될 것입니다.Graph
클래스. 또한 이러한 연결이 호(방향 지정, 단방향 연결)인지 에지(방향 지정, 양방향 연결)인지 알아야 합니다.다음을 추가하여 처리하겠습니다.directed
매개변에 대한 Graph.__init__
. 유용한 다른 유용한 방법도 추가할 것입니다.
import pprint
from collections import defaultdict
class Graph(object):
""" Graph data structure, undirected by default. """
def __init__(self, connections, directed=False):
self._graph = defaultdict(set)
self._directed = directed
self.add_connections(connections)
def add_connections(self, connections):
""" Add connections (list of tuple pairs) to graph """
for node1, node2 in connections:
self.add(node1, node2)
def add(self, node1, node2):
""" Add connection between node1 and node2 """
self._graph[node1].add(node2)
if not self._directed:
self._graph[node2].add(node1)
def remove(self, node):
""" Remove all references to node """
for n, cxns in self._graph.items(): # python3: items(); python2: iteritems()
try:
cxns.remove(node)
except KeyError:
pass
try:
del self._graph[node]
except KeyError:
pass
def is_connected(self, node1, node2):
""" Is node1 directly connected to node2 """
return node1 in self._graph and node2 in self._graph[node1]
def find_path(self, node1, node2, path=[]):
""" Find any path between node1 and node2 (may not be shortest) """
path = path + [node1]
if node1 == node2:
return path
if node1 not in self._graph:
return None
for node in self._graph[node1]:
if node not in path:
new_path = self.find_path(node, node2, path)
if new_path:
return new_path
return None
def __str__(self):
return '{}({})'.format(self.__class__.__name__, dict(self._graph))
" "습를한을 " 것입니 " 길남다 " 로것" " ▁a▁reader니 "을 만드는 것은 "를 위한 find_shortest_path
기타 방법.
하지만 이것이 실행되는 것을 봅시다.
>>> connections = [('A', 'B'), ('B', 'C'), ('B', 'D'),
('C', 'D'), ('E', 'F'), ('F', 'C')]
>>> g = Graph(connections, directed=True)
>>> pretty_print = pprint.PrettyPrinter()
>>> pretty_print.pprint(g._graph)
{'A': {'B'},
'B': {'D', 'C'},
'C': {'D'},
'E': {'F'},
'F': {'C'}}
>>> g = Graph(connections) # undirected
>>> pretty_print = pprint.PrettyPrinter()
>>> pretty_print.pprint(g._graph)
{'A': {'B'},
'B': {'D', 'A', 'C'},
'C': {'D', 'F', 'B'},
'D': {'C', 'B'},
'E': {'F'},
'F': {'E', 'C'}}
>>> g.add('E', 'D')
>>> pretty_print.pprint(g._graph)
{'A': {'B'},
'B': {'D', 'A', 'C'},
'C': {'D', 'F', 'B'},
'D': {'C', 'E', 'B'},
'E': {'D', 'F'},
'F': {'E', 'C'}}
>>> g.remove('A')
>>> pretty_print.pprint(g._graph)
{'B': {'D', 'C'},
'C': {'D', 'F', 'B'},
'D': {'C', 'E', 'B'},
'E': {'D', 'F'},
'F': {'E', 'C'}}
>>> g.add('G', 'B')
>>> pretty_print.pprint(g._graph)
{'B': {'D', 'G', 'C'},
'C': {'D', 'F', 'B'},
'D': {'C', 'E', 'B'},
'E': {'D', 'F'},
'F': {'E', 'C'},
'G': {'B'}}
>>> g.find_path('G', 'E')
['G', 'B', 'D', 'C', 'F', 'E']
NetworkX는 멋진 Python 그래프 라이브러리입니다.당신은 당신이 필요로 하는 것이 이미 필요하지 않은 것을 찾는 데 어려움을 겪을 것입니다.
그리고 그것은 오픈 소스이기 때문에 그들이 어떻게 알고리즘을 구현했는지 알 수 있습니다.알고리즘을 추가할 수도 있습니다.
https://github.com/networkx/networkx/tree/master/networkx/algorithms
첫째, 고전적 리스트 대 행렬 표현의 선택은 목적에 따라 달라집니다(표현으로 무엇을 할 것인가에 따라).잘 알려진 문제와 알고리즘은 선택과 관련이 있습니다.추상적 표현의 선택은 그것이 어떻게 구현되어야 하는지를 결정합니다.
둘째, 문제는 꼭짓점과 모서리가 존재의 관점에서만 표현되어야 하는지, 아니면 추가적인 정보를 가지고 있는지 여부입니다.
Python에 내장된 데이터 유형의 관점에서 다른 곳에 포함된 모든 값은 대상 개체에 대한 (숨겨진) 참조로 표현됩니다.변수(예: 명명된 참조)인 경우 이름과 참조는 항상 (내부) 사전에 저장됩니다.이름이 필요하지 않으면 참조를 사용자 자신의 컨테이너에 저장할 수 있습니다. 여기서 Python 목록은 목록에 항상 추상화로 사용됩니다.
Python 목록은 동적 참조 배열로 구현되고, Python 튜플은 일정한 내용을 가진 정적 참조 배열로 구현됩니다(참조 값은 변경할 수 없음).그것 때문에 그것들은 쉽게 색인화될 수 있습니다.이러한 방식으로 목록을 행렬 구현에도 사용할 수 있습니다.
매트릭스를 표현하는 또 다른 방법은 표준 모듈에 의해 구현된 어레이입니다.array
저장된 유형, 균질한 값과 관련하여 더 제약을 받습니다.요소는 값을 직접 저장합니다. 대신 값 개체에 대한 참조를 목록에 저장합니다.이렇게 하면 메모리 효율성이 향상되고 값에 대한 액세스 속도도 빨라집니다.
때때로, 당신은 훨씬 더 제한된 표현이 유용하다는 것을 발견할 수 있습니다.bytearray
.
두 개의 훌륭한 그래프 라이브러리 Network X와 igraph가 있습니다.GitHub에서 두 라이브러리 소스 코드를 모두 찾을 수 있습니다.기능이 어떻게 작성되는지 항상 확인할 수 있습니다.하지만 저는 네트워크X가 이해하기 쉽기 때문에 선호합니다.
그들이 어떻게 기능을 만드는지 알기 위해 그들의 코드는 다음과 같습니다.여러 아이디어를 얻은 다음 데이터 구조를 사용하여 그래프를 만드는 방법을 선택할 수 있습니다.
언급URL : https://stackoverflow.com/questions/19472530/representing-graphs-data-structure-in-python
'programing' 카테고리의 다른 글
NLTK 토큰라이저를 사용하여 구두점을 제거하는 방법은 무엇입니까? (0) | 2023.07.17 |
---|---|
Oracle: 열 순서가 인덱스에서 중요합니까? (0) | 2023.07.17 |
onAuthStateChanged를 사용한 Float을 사용한 Firebase 로그인 (0) | 2023.07.17 |
오라클 번호 형식의 원치 않는 선행 공백 (0) | 2023.07.07 |
에서 포스트백 사용 안 함 (0) | 2023.07.07 |