당신은 주제를 찾고 있습니까 “파이썬 그래프 구현 – [자료구조 알고리즘] Graph 검색 DFS, BFS 구현 in Java“? 다음 카테고리의 웹사이트 you.tfvp.org 에서 귀하의 모든 질문에 답변해 드립니다: https://you.tfvp.org/blog/. 바로 아래에서 답을 찾을 수 있습니다. 작성자 엔지니어대한민국 이(가) 작성한 기사에는 조회수 90,584회 및 좋아요 1,819개 개의 좋아요가 있습니다.
파이썬 그래프 구현 주제에 대한 동영상 보기
여기에서 이 주제에 대한 비디오를 시청하십시오. 주의 깊게 살펴보고 읽고 있는 내용에 대한 피드백을 제공하세요!
d여기에서 [자료구조 알고리즘] Graph 검색 DFS, BFS 구현 in Java – 파이썬 그래프 구현 주제에 대한 세부정보를 참조하세요
[선행학습자료]Linked List 개념 https://youtu.be/DzGnME1jIwY단방향/양방향 Linked List 개념 https://youtu.be/G4IIDyfoHeY
단방향 Linked List 구현 in Java https://youtu.be/C1SDkdPvQPA
Stack 구현하기 in Java https://youtu.be/whVUYv0Leg0
Queue 구현하기 in Java https://youtu.be/W3jNbNGyjMs
Tree의 종류 https://youtu.be/LnxEBW29DOw
Binary Tree의 3가지 순회방법 구현하기 https://youtu.be/QN1rZYX6QaA
그래프(Graph)에 대해서 https://youtu.be/fVcKN42YXXI
파이썬 그래프 구현 주제에 대한 자세한 내용은 여기를 참조하세요.
Python의 그래프 구현 – Techie Delight
이 포스트는 그래프의 인접 목록 표현을 사용하여 파이썬에서 가중치 및 가중치가 없는 방향성 그래프 데이터 구조를 구현합니다. 여기서 그래프의 각 정점은 인접 …
Source: www.techiedelight.com
Date Published: 10/16/2021
View: 7058
자료구조] 9. 그래프(Graph) – 파이썬 – gongsam21
무방향 그래프의 경우 전치행렬이 되어도 값이 같다. 인접 리스트 기반 그래프. 인접 행렬이 행렬을 이용한것과는 달리 인접 리스트로 구현한다. 파이썬 …
Source: rhdtka21.tistory.com
Date Published: 4/25/2021
View: 8794
2. 그래프(Graph) – 파이썬 사전(하면서 필요한 거 위주로 …
본격적으로 DFS, BFS를 공부하기 전에 그래프 구조가 무엇인지 알아야 한다. 여기서부터는 쉽지 않다… 사실 이론과 그림을 이해하는 것은 크게 어렵지 않으나,, 구현 …
Source: wikidocs.net
Date Published: 6/4/2021
View: 3875
그래프_구현하기 – muntari Log
먼저, 그래프의 노드를 구현하는 방법이다. 1. 동적 배열 / 파이썬 리스트 구현 방법. 그래프는 노드라는 기본 데이터 단위를 가지며 리스트의 요소로 …
Source: codermun-log.tistory.com
Date Published: 6/28/2022
View: 6086
[Python]자료구조 6.그래프 – velog
1-2) 구현. Graph: def __init__(self, vertex_num = …
Source: velog.io
Date Published: 1/19/2021
View: 1185
[파이썬 알고리즘] 그래프 구현, DFS, BFS, 인접 행렬, 최소 신장 …
[파이썬 알고리즘] 그래프 구현, DFS, BFS, 인접 행렬, 최소 신장 트리 … 그래프는 정점을 연결하는 간선의 방향성 여부에 따라.Source: blog.naver.com
Date Published: 9/29/2021
View: 8345
[Python] 그래프(Graph) – 별의 블로그
트리도 그래프의 일종이지만, 트리와 그래프를 구현하는 코드 등이 … 그래프는 정점을 연결하는 간선의 방향성 여부에 따라 방향 그래프와 무방향 …
Source: starrykss.tistory.com
Date Published: 7/25/2022
View: 5534
파이썬에서 그래프(Graph) 구현하기 – 준화의 개발일기
그래프를 파이썬에서 구현해보는 포스팅을 하겠습니다. 그래프(Graph) 자료구조란? Graph는 정점(Vertex, 혹은 Node) …
Source: develop-story.tistory.com
Date Published: 8/25/2021
View: 6839
[파이썬(python) 자료구조] 그래프 (Graph) – 유진’s 공부로그
그래프 : 연결되어 있는 객체 간의 관계를 표현하는 비선형 자료구조 가장 … 파이썬은 포인터가 따로 존재하지 않으므로, 연결리스트를 구현하기 …
Source: daebaq27.tistory.com
Date Published: 7/20/2022
View: 4252
[Python & Data Structure] Graph – 이것저것 공부방
하나의 리스트는 자신과 인접한 다른 정점을 담고 있다. 가중치 그래프의 인접리스트 표현. 간단한 구조의 그래프는 인접행렬로 구현이 가능 …
Source: duckracoon.tistory.com
Date Published: 6/4/2021
View: 375
주제와 관련된 이미지 파이썬 그래프 구현
주제와 관련된 더 많은 사진을 참조하십시오 [자료구조 알고리즘] Graph 검색 DFS, BFS 구현 in Java. 댓글에서 더 많은 관련 이미지를 보거나 필요한 경우 더 많은 관련 기사를 볼 수 있습니다.
주제에 대한 기사 평가 파이썬 그래프 구현
- Author: 엔지니어대한민국
- Views: 조회수 90,584회
- Likes: 좋아요 1,819개
- Date Published: 2017. 12. 28.
- Video Url link: https://www.youtube.com/watch?v=_hxFgg7TLZQ
Python의 그래프 구현
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
# 그래프 객체를 나타내는 클래스 class Graph : # 그래프를 구성하는 생성자 def __init__ ( self , edges , n ) : # 인접 목록을 나타내는 목록 목록 self . adjList = [ None ] * n # 인접 목록에 대한 메모리 할당 for i in range ( n ) : self . adjList [ i ] = [ ] #는 방향 그래프에 간선을 추가합니다. for ( src , dest , weight ) in edges : #는 인접 목록의 노드를 src에서 dest로 할당합니다. self . adjList [ src ] . append ( ( dest , weight ) ) # 그래프의 인접 목록 표현을 인쇄하는 기능 def printGraph ( graph ) : for src in range ( len ( graph . adjList ) ) : # 현재 정점과 모든 인접 정점을 인쇄합니다. for ( dest , weight ) in graph . adjList [ src ] : print ( f ‘({src} —> {dest}, {weight}) ‘ , end = ” ) print ( ) if __name__ == ‘__main__’ : # 입력: 가중 이중 그래프의 에지(위 다이어그램에 따름) # Edge (x, y, w)는 가중치가 `w`인 `x`에서 `y`까지의 에지를 나타냅니다. edges = [ ( 0 , 1 , 6 ) , ( 1 , 2 , 7 ) , ( 2 , 0 , 5 ) , ( 2 , 1 , 4 ) , ( 3 , 2 , 10 ) , ( 4 , 5 , 1 ) , ( 5 , 4 , 3 ) ] # 꼭짓점 수(0에서 5까지 레이블 지정) n = 6 #는 주어진 간선 목록에서 그래프를 구성합니다. graph = Graph ( edges , n ) # 그래프의 인접 목록 인쇄 printGraph ( graph )
[파이썬 | 자료구조] 9. 그래프(Graph)
9. 그래프(Graph)
9.1 그래프의 개념
그래프란 정점과 간선들로 이루어진 집합으로 표현되는 자료구조
트리도 일종의 그래프라고 할 수 있다.
9.2 그래프의 종류
무방향 그래프 : 간선이 방향을 가지지 않음
방향 그래프 : 간선이 방향을 가지고 있음
가중치 그래프 : 각 간선에 가중치 정보가 포함됨. 가중치는 거리, 비용 등으로 표현 할 수 있다.
9.3 그래프의 구현
인접 행렬 기반 그래프 각 정점간의 가중치나 간선의 유무를 행렬로 표현한다. 무방향 그래프의 경우 전치행렬이 되어도 값이 같다.
인접 리스트 기반 그래프 인접 행렬이 행렬을 이용한것과는 달리 인접 리스트로 구현한다.
파이썬에서는 그냥 딕셔너리 자료형에 리스트를 넣어 쉽게 인접 리스트처럼 구현하여 사용할 수 있다.
BFS
BFS는 너비 우선 탐색으로, 현재 Node(Vertex)에서 연결된 Node로 우선적으로 탐색하는 것을 뜻한다.
즉 아래 그림에서 A에서 BFS를 시작한다고 하면, B, E, I를 우선적으로 탐색하고, 그 후 B, E, I에 연결된 Node를 탐색한다.
즉 방문하는 순서는 [‘A’, ‘B’, ‘E’, ‘I’, ‘C’, ‘F’, ‘H’, ‘J’, ‘D’, ‘G’] 순이 된다.
queue를 이용해서 구현할 수 있다.
DFS
BFS는 깊이 우선 탐색으로, 현재 Node(Vertex)에서 연결된 Node중에서 하나를 골라 더이상 진행할 수 없을때까지 탐색한다. 그 후 더이상 진행이 불가능하면, 진행이 가능한 Node 까지 되돌아 와서 탐색을 한다.
즉 아래 그림에서 A에서 BFS를 시작한다고 하면, B를 우선적으로 탐색하고, 그 후 B에 연결된 Node를 탐색한다.
즉 방문하는 순서는 [‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’, ‘G’, ‘H’, ‘I’, ‘J’] 순이 된다.
stack을 이용해서 구현할 수 있고, 함수의 재귀호출을 이용해서 구현할 수도 있다.
2. 그래프(Graph)
본격적으로 DFS, BFS를 공부하기 전에 그래프 구조가 무엇인지 알아야 한다. 여기서부터는 쉽지 않다… 사실 이론과 그림을 이해하는 것은 크게 어렵지 않으나,, 구현이 매우 어려운거 같다…
백트랙킹 문제에서 며칠째 정체하고 있다…
그래프 구조
vertex (정점) (node)과 edge (간선) 으로 이루어진 자료구조다. (비선형 구조)
degree (차수)
: node에 연결된 edge의 수. ex) A의 차수 1 B의 차수 2
경로
Node 표현: A – B – C
Edge 표현: (A, B) (B, C)
– 단순 경로 : node를 최대 한 번만 지나는 경로
– Cycle : 시작과 끝의 node가 같은 경로
– DAG(Directed Acycle Graph)
▶Undirected Graph
▶Directed Graph 방향 o
In-degree (진입차수) : 방향이 향하는 edge 수 (ex) B의 진입차수 1)
Out-degree (진출차수) : 방향이 나가는 edge 수 (ex) A의 진출차수 1 진입차수 0)
▶Weighted Graph 방향 o 가중치 o
Adjacency (인접)
두 개의 정점(node)이 연결된 상태를 인접하다고 한다. (Directed graph에서는 방향이 향하는 쪽 node가 인접한 정점이다.) – 완전 그래프: 모두 Adjacency한 그래프
Edge의 수 :
Undirected ${n(n-1)} \over 2$
directed $n(n-1)$ – 부분 그래프
그래프 구조 구현
1. 인접 ✳ 행렬(adjacency matrix)
adjacency matrix: 인접한 정점들의 상태를 행렬(2차원 배열)로 구성.
인접하면 1이다.
같은 노드끼리는 0이다.
연결되지 않은 노드끼리는 0 또는 무한대 inf로 표현한다.
adjac_matrix = [[0, 1, 1, 0, 0, 0, 0], [1, 0, 0, 1, 0, 0, 0], [1, 0, 0, 0, 1, 1, 0], [0, 1, 0, 0, 0, 0, 1], [0, 0, 1, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0]]
Directed graph의 경우 진입차수(방향을 맞은?방향)의 차수를 입력한다.
Undirected의 인접행렬은 대칭행렬(symmetric matrix)다.
😥Node가 많아지면 메모리가 $n^2$ 배로 필요해진다.
2. 인접 ✳리스트 vertex & edge list
유튜브 참고 했습니다. (설명을 매우 잘해주시더라구요!)
# vertext list vert_lst = [‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’] # edge list edge_lst = [(0, 1), (1, 0), (1, 3), (3, 1), (3, 6), (6, 3), (0, 2), (2, 0), (2, 4), (4, 2), (2, 5), (5, 2)] # adjacency list adjac_lst = [[] for vert in vert_lst] for edge in edge_lst: adjac_lst[edge[0]].append(edge[1]) print(adjac_lst) # [[1, 2], [0, 3], [0, 4, 5], [1, 6], [2], [2], [3]]
결과로 정점 0 부터 6까지 인접한 정점들의 집합이 나온다.
이 인접한 정점들의 집합과 스택 쿠조를 이용하여 visited(flag) list를 만들어 그래프를 모두 탐색한다.
def stack_graph(adjac_lst): stack = [0] visit_vert = [] while stack: current = stack.pop() for neighbor in adjac_lst[current]: if neighbor not in visit_vert: stack.append(neighbor) visit_vert.append(current) return visit_vert
구현하기 :: muntari Log
728×90
그래프 구현하기
그래프를 구현하는 방법은 크게 2가지로 나누어 알아보자.
1. 그래프의 노드를 구현하는 방법
– 배열 또는 동적 배열 => 파이썬의 리스트로 구현이 가능하다.
– 해시 테이블 => 파이썬의 딕셔너리로 구현이 가능하다.
2. 그래프의 에지를 구현하는 방법
– 인접 행렬
– 인접 리스트
먼저, 그래프의 노드를 구현하는 방법이다.
1. 동적 배열 / 파이썬 리스트 구현 방법
그래프는 노드라는 기본 데이터 단위를 가지며 리스트의 요소로 단순 값이 아닌 노드 자체를 요소로 하는 리스트를 만드는 방법이다.
이때 노드는 특정 인덱스 값을 부여받는데, 인덱스를 이용해 리스트의 O(1)으로 효율적인 접근이 가능하며, 노드 안의 인스턴스에 대한 접근도 그만큼 효율적으로 할 수 있게 되는 것이다.
class StationNode: “””간단한 지하철 역 노드 클래스””” def __init__(self, station_name, location): self.station_name = station_name self.location = location A = StationNode(“당고개역”, “서울”) B = StationNode(“오이도역”, “경기”) C = StationNode(“부산역”, “부산”) list_1 = [“당고개역”, “오이도역”, “부산역”] list_2 = [A, B, C] print(list_1) print(list_2[1].station_name) # 오이도역 print(list_2[1].location) # 경기
2. 헤시테이블 / 파이썬 딕셔너리 구현 방법
위 방법과 비슷하게 역 이름 자체를 Key 값으로 사용하고 역 노드를 Value 값으로 사용하는 것이다.
이때 주의할점은 해시 테이블에서 동일한 key값은 존재할 수 없다는 점이며, 중복이 이루어지지 않는 고윳값(이메일, 핸드폰 번호 등등)을 Key 값으로 사용해야 한다.
역 이름의 경우 중복되는 역 이름은 존재하지 않으므로 역 이름을 Key 값으로 사용해도 무방하다.
해시 테이블도 Key 값만 있다면 Value는 평균적으로 O(1)으로 가져올 수 있기에 효율적으로 사용이 가능하다.
class StationNode: “””간단한 지하철 역 노드 클래스””” def __init__(self, station_name, location): self.station_name = station_name self.location = location A = StationNode(“당고개역”, “서울”) B = StationNode(“오이도역”, “경기”) C = StationNode(“부산역”, “부산”) my_dict = {} my_dict[“당고개역”] = A my_dict[“오이도역”] = B my_dict[“부산역”] = C print(my_dict) # {‘당고개역’: <__main__.StationNode object at 0x7fdf45868700>, ‘오이도역’: <__main__.StationNode object at 0x7fdf458d4490>, ‘부산역’: <__main__.StationNode object at 0x7fdf458d4520>} print(my_dict[“당고개역”].station_name) # 당고개역 print(my_dict[“당고개역”].location) # 서울
그래프의 엣지를 구현하는 방법
1. 인접 행렬
인접은 두 노드가 서로 연결되어 있다는 의미이고,
행렬은 2차원 배열 또는 2차원 리스트라는 의미이다, 파이썬에서의 리스트 안에 리스트가 들어가 있는 matrix형태를 떠올리면 되겠다.
즉, 요소의 갯수에 따라 행렬을 만들고 이 행렬에 각 노드들끼리 어떻게 연결되었는지를 표시하는 방법이다.
인접 행렬의 목표는 어떤 노드가 어떤 노드와 연결되어 있는지? 를 확인하기 위함이라 할 수 있겠다.
인접 행렬을 아래와 같이 정리할 수 있다.
– 각 노드를 리스트에 저장해 노드는 고유 정수 인덱스 값을 갖는다.
– 노드 수 X 노드 수 크기의 행렬을 만든다.
– 노드들의 엣지 유무 및 가중치에 따라 행렬의 요소를 채운다.
인접 행렬은 무방향 그래프, 방향 그래프, 가중치 그래프일 때 각각 다르기 때문에 그래프 별로 알아보자.
– 무방향 그래프
아래의 예시로 엣지를 구현해보도록 하자.
list_1 = [“영훈”, “동욱”, “현승”, “지웅”, “소원”]
각 노드 간의 연결 관계를 저장하기 위해 노드의 개수만큼의 행렬을 만들어 준다. (5 x 5)
각 노드는 인덱스라는 고유 값을 갖게 되므로 이를 이용해 서로 간의 연결 관계를 정의할 수 있는데
인접 행렬에서는 모든 노드는 스스로와 연결이 되지 않은 상태로 나타낸다. (0)
영훈의 경우 0번째 인덱스로 동욱, 현승과 인접 관계에 있다.
이를 행렬로 나타내면 아래와 같다.
무방향 그래프에서의 영훈 – 동훈 에지는 동훈 – 영훈 에지와 같기 때문에
0행 1열(영훈, 동훈) = 1 / 1행 0열(동훈, 영훈) = 1
0행 2열(영훈, 현승) = 1 / 2행 0열(현승, 영훈) = 1
모든 노드에 위와 같이 관계를 정의해주면 아래와 같은 행렬이 되며,
모든 노드는 스스로와 연결이 되지 않은 상태이기에 대각선을 기준으로 대칭 구조가 된다.
– 방향 그래프
위 예시에 방향성만 추가한다.
방향 그래프에서는 엣지가 방향성을 갖기 때문에 영훈- 현승 에지와 현승 -영훈 에지가 다르다.
0행 1열 (영훈, 현승) = 0 / 1행 0열 (현승, 영훈) = 1
0행 2열 (영훈, 동욱) = 0 / 2행 0열 (동욱, 영훈) = 1
모든 노드에 위와 같이 관계를 정의해주면 아래와 같은 행렬이 되며,
무방향에서와 달리 대칭 구조를 이루지 않는다.
– 가중치 그래프
엣지가 추가 정보를 갖는 가중치 그래프
여기서는 연결 상태 표시를 가중치로 해주면 된다.
위에서 연결 상태 = 1로 표기하였다면 연결 상태 = 가중치로 표기해주면 되는 것이다.
당연히 기본 단위인 노드의 인스턴스는 위 예시와 다르다.
인접 행렬의 목표는 어떤 노드가 어떤 노드와 연결되어 있는지?를 알기 위함이었다.
특정 노드 사이에 서로 인접해 있는지 여부를 확인하는 방법을 알아보자.
영훈과 동욱이 서로 인접해 있는지 확인하기 위해서는
영훈의 인덱스 값 0과 동욱의 인덱스 값 1을 이용해 행렬의 데이터를 찾으면 된다.
즉, 0행 1열의 값 또는 1행 0열의 값을 찾아 서로 인접해 있는지 아닌지 여부를 확인할 수 있다.
matrix[0][1] or matrix[1][0]
특정 노드와 인접해 있는 모든 노드를 확인하고 싶을 때는 특정 노드의 인덱스 값을 이용해 해당 노드의 행 전체를 가져오면 된다.
영훈과 인접해 있는 모든 노드를 확인하고 싶을 때는 아래와 같이 확인할 수 있으며
결과로 동욱, 현승과 인접 관계라는 점을 확인 할 수 있게 된다.
matrix[0]
2. 인접 리스트
인접 행렬의 경우 노드들의 인접 데이터를 행렬에 저장했다면,
인접 리스트의 경우, 말그대로 노드들의 인접 데이터를 리스트에 저장하는 방법이다.
(리스트는 순서 데이터를 저장하는 자료구조이나, 인접 리스트에서는 노드들의 순서는 큰 의미가 없다. 모두 동등한 관계이자 위치에 있기 때문이다.)
인접 리스트는 각 노드마다 스스로 인접한 노드들에 대한 레퍼런스를 리스트로 저장하여 에지를 구현하는 방법이다.
인접 행렬을 아래와 같이 정리할 수 있다.
– 각 노드의 엣지를 리스트에 저장하는 방법.
아래 지하철 역 예시를 통해 더 자세히 알아보자.
강남역의 경우
교대, 역삼, 양재와 인접해있으며, 이 인접 관계를 배열 or 파이썬의 리스트에 저장하는 방법으로
특정 노드에 어떤 노드들이 인접해 있는지 알 수 있게 된다.
인접 행렬에서의 노드 인스턴스에 빈 배열의 인스턴스를 추가하고
이 빈 배열에 연결된 노드들에 대한 레퍼런스를 저장한다!
(이는, 링크드 리스트의 노드에서 다음 노드에 대한 레퍼런스를 저장하는 것과 트리에서 노드가 자식 노드에 대한 레퍼런스를 저장하는 것과 동일하다!!)
class StationNode: “””간단한 지하철 역 노드 클래스””” def __init__(self, station_name, location): self.station_name = station_name self.location = location self.adjacent_stations = []
따라서 그래프의 강남 노드는 아래와 같은 인접 리스트를 갖는다!
인접 리스트를 사용하는 방법
그래프에 따라 인접 리스트를 사용하는 방법에 차이가 있다.
1. 무방향 그래프
A와 B가 인접 관계라면 A의 인접 리스트에 B를 넣고 + B의 인접 리스트에 A를 넣는다.
에지의 방향성이 없기에 A – B 에지와 B – A 에지는 같기 때문이다.
2. 방향 그래프
A와 B가 인접 관계라면 A의 인접 리스트에 B를 넣고, B의 인접 리스트에 A를 넣지 않는다.
엣지의 방향성이 있어, A – B 에지와 B – A 에지는 같지 않기 때문이다.
3. 가중치 그래프
가중치 그래프의 경우 튜플을 사용하여 인접 노드와 가중치를 함께 저장해주면 된다.
만약, 가중치 그래프에서 에지의 방향성이 있다면 위와 마찬가지로 B의 인접 리스트에 A를 넣지 않으면 된다.
그래프는 각 언어별로 아래와 같은 방법으로 구현한다고 한다.
C++ => Vector
JAVA => Arraylist
Python => List
구현의 경우 여태껏 구현하였던 자료구조 중 제일 복잡하였덧 것 같아 코드를 참고하여 공부한다면 더 잘 이해가 될 것 같아 공유한다!
Python_Javascript_CTEST/DataStructure/used_dict_adjacency_list at main · Muntari29/Python_Javascript_CTEST (github.com)
출처 : 코드 잇(자료구조)
자료 구조 | 코드 잇 (codeit.kr)
728×90
[Python]자료구조 6.그래프
6.1. 용어
그래프는 정점(vertex)의 집합 V(G)와 에지(Edge)의 집합 E(G)로 정의 G = (V, E)
6.1.1. 무방향 그래프
G = (V, E)
V(G) = {0, 1, 2, 3}
E(G) = {(0,1), (0,2), (0,3), (2,3)}
정점의 개수가 n인 경우, 최대 에지의 개수 : n(n-1)/2
에지 : 정점과 정점을 잇는 선
6.1.2. 방향 그래프
G =
V(G) = {0, 1, 2, 3}
E(G) = {<0,1>, <0,2>, <1,2>, <2,3>, <3,2>}
정점의 개수가 n인 경우, 최대 에지의 개수 : n(n-1)
<0,1> : 0이 head, 1이 tail
6.1.3. 자기 간선
정점이 head이자 tail
6.1.4. 멀티그래프
중복 에지 인정
6.1.5. 인접
정점 u, v 사이에 에지 (u, v) 가 있는 경우, u와 v는 인접하다
u ∈ V(G), v ∈ V(G)고 (u, v) ∈ E(G)이면 u와 v는 adjacent
6.1.6. 경로
경로(path) : (v1, v2), (v2, v3), (v3, v4)가 집합 E(G)의 원소일 때 v1에서 v4까지 정점 순서 v1->v2->v3->v4
경로의 길이 = 에지의 개수
6.1.6.1. 단순 경로
처음과 마지막 경로가 다름
6.1.6.2. 사이클
단순 경로에서 처음과 마지막 경로가 같음
v2->v3->v4->v2
6.1.7. 연결된 그래프(connected graph)
어떤 임의의 정점 u와 다른 어떤 임의의 정점 v를 골랐을 때 정점 사이에 경로가 있으면 이를 연결되었다(connected)
G = (V, E)
V(G) = {0, 1, 2, 3, 4, 5, 6, 7}
E(G) = {(0, 3), (0, 4), (1, 2), (1, 5), (2, 5), (3, 4), (4, 6), (5, 7)} 연결요소 : 정점 집합 {0, 3, 4, 6}과 {1, 2, 5, 7}을 각각 연결 요소(connected component)임.
6.1.8. 차수(degree)
1) 무방향 그래프의 차수
어떤 정점 v의 차수 d(v)는 정점 v가 부속된 에지 개수
부속되었다(incident) : 정점 u와 정점 v 사이에 에지 (u, v)가 존재할 때 에지 (u, v)를 정점 u에 부속되었다, 정점 v에 부속되었다
2) 방향 그래프의 차수
방향그래프의 차수 : 진입차수 + 진출차수 = d(v)
진입 차수(in-degree) : 정점 v가 head인 경우 = 정점 v로 들어오는 에지 개수 진입차수 : in-d(v)
진출 차수(out-degree) : tail인 경우 = 정점 v에서 나가는 에지 개수 진출 차수 : out-d(v)
6.1.9. 부분 그래프, 신장 부분 그래프
1) 부분 그래프
그래프 G’가 G에 대해 V(G’) ⊆ (G)고 E(G’) ⊆ E(G)면 그래프 G’는 그래프 G의 부분 그래프
2) 신장 부분 그래프(spanning subgraph)
그래프 G’가 그래프 G에 대해 V’=V고 E(G’) ⊆ E(G)를 만족
ex) G’는 V’=V를 만족하므로 신장 부분 그래프이지만, G”에는 정점 3이 누락되었으므로 V’=V를 만족하지 못해서 부분 그래프이지만 신장 부분 그래프는 아님
6.2. 그래프 표현 방법 : 인접리스트, 인접 행렬
1) 인접 리스트(adjacency list)
배열 1개와 연결리스트들로 구성
배열의 인덱스 = 정점
연결리스트 : 해당 정점에 인접한 정점의 집합
ex) 정점 0에 연결된 정점이 1,3 인 경우 리스트 요소는 1,3 O(d(v))
1) 어떤 정점 v에 대해 인접한 모든 노드를 탐색 : 해당 정점을 인덱스로 삼아 해당되는 연결리스트를 통해 순회하므로, 모든 정점을 조사할 필요 없이 해당 정점의 인접한 정점들만 조사
2) 정점 u에 대해 (u, v) ∈ E(G)인지를 검사 : 해당 정점을 인덱스로 연결 리스트를 가져와 인접한 모든 노드를 순회해야 함.
1-1) ADT
1. Object
정점 집합 V와 정점 집합 V에 속하는 u, v에 대해 (u, v)가 속하는 에지 집합 E로 구성된 튜플 G = (V, E)
2. Operation
G.is_empty() : Boolean G.add_vertex() : 정점 추가하고 정점 인덱스 반환(Integer) G.delete_vertex(v) : 정점 v 삭제 G.add_edge(u, v) : 에지 (u, v) 추가 G.delete_edge(u, v) : 에지 (u, v) 삭제 G.adj(v) : 정점 v에 인접한 정점 집합을 동적 배열로 반환
1-2) 구현
class Graph : def __init__ ( self , vertex_num = None ) : self . adj_list = [ ] self . vtx_num = 0 self . vtx_arr = [ ] if vertex_num : self . vtx_num = vertex_num self . vtx_arr = [ True for _ in range ( self . vtx_num ) ] self . adj_list = [ [ ] for _ in range ( self . vtx_num ) ]
vtx_arr : delete_vertex() 사용 시 도중에 있던 정점이 사라질 수 있기 때문에 이를 방지하기 위한 배열
def is_empty ( self ) : if self . vtx_num == 0 : return True return False def add_vertex ( self ) : for i in range ( len ( self . vtx_arr ) ) : if self . vtx_arr [ i ] == False : self . vtx_num += 1 self . vtx_arr [ i ] = True return i self . adj_list . append ( [ ] ) self . vtx_num += 1 self . vtx_arr . append ( True ) return self . vtx_num – 1
add_vertex() : 모든 정점을 순회하면서 비활성화된 정점이 있다면 사용하고, 모두 사용 중이라면 정점을 추가함.
def delete_vertex ( self , v ) : if v >= self . vtx_num : raise Exception ( f”There is no vertex of { v } ” ) if self . vtx_arr [ v ] : self . adj_list [ v ] = [ ] self . vtx_num -= 1 self . vtx_arr [ v ] = False for adj in self . adj_list : for vertex in adj : if vertex == v : adj . remove ( vertex )
정점 v 삭제 = 비활성화
if self.vtx_arr[v] : self.adj_list[v] = [] :해당 정점이 있다면 인접리스트 초기화
:해당 정점이 있다면 인접리스트 초기화 self.vtx_arr[v] = False : 해당 정점 비활성화, 추후 활성화하여 사용 가능하도록 비활성화
: 해당 정점 비활성화, 추후 활성화하여 사용 가능하도록 비활성화 for adj in self.adj_list: for vertex in adj:
: 이중루프를 돌면서 해당 정점과 이어져 있던 에지들 삭제
def add_edge ( self , u , v ) : self . adj_list [ u ] . append ( v ) self . adj_list [ v ] . append ( u ) def delete_edge ( self , u , v ) : self . adj_list [ u ] . remove ( v ) self . adj_list [ v ] . remove ( u )
인접리스트의 에지 추가 : 인접리스트의 각 정점 마지막 요소에 추가
인접리스트의 에지 삭제 : 해당 정점(동적 배열)의 요소 삭제
def adj ( self , v ) : return self . adj_list [ v ]
해당 정점 v에 인접한 모든 노드 집합을 리스트로 반환
2) 인접 행렬(adjacency matrix)
행 : 정점
열 : 자신을 포함한 다른 정점
ex) 1행 2열 = 정점 1과 정점 2의 관계 : 해당 값이 0인 경우, 인접하지 않다
ex) 1행 2열 = 정점 1과 정점 2의 관계 : 해당 값이 0인 경우, 인접하지 않다 이차원 배열 adj_matrix : 에지 (0,1)이 있다면 adj_matrix[0][1] = 1, 없다면 0
무방향 그래프의 경우, (0,1), (1,0) 모두 존재하므로 행렬에서는 모두 1 : 대각선에 대해 대칭 O(n)
1) 어떤 정점 v에 대해 인접한 모든 노드를 탐색 : v행에 대하여 모든 열 탐색
O(1)
2) (u, v)가 있는지 여부를 확인하는 연산 : adj_matrix[u][v] 유무 확인
5.3. 그래프 순회(traversal) : 그래프의 모든 노드 방문
1) 너비 우선 탐색(Breadth First Search, BFS) : 큐 기반
ex) 출발 정점이 3인 경우, 출발 정점을 지나 인접 정점 모두 탐색, 이후 인접 정점들의 인접 정점 탐색 순으로 탐색함
from queue import Queue class Graph : def __init__ ( self , vertex_num ) : self . adj_list = [ [ ] for _ in range ( vertex_num ) ] self . visited = [ False for _ in range ( vertex_num ) ] def add_edge ( self , u , v ) : self . adj_list [ u ] . append ( v ) self . adj_list [ v ] . append ( u ) def init_visited ( self ) : for i in range ( len ( self . visited ) ) : self . visited [ i ] = False
인접 리스트로 구현
visited 변수 : 정점의 방문 여부 확인 -> 각 정점 방문 시, True 반환, 미방문 시 False 반환
def bfs ( self , v ) : q = Queue ( ) self . init_visited ( ) q . put ( v ) self . visited [ v ] = True while not q . empty ( ) : v = q . get ( ) print ( v , end = ‘=’ ) adj_v = self . adj_list [ v ] for u in adj_v : if not self . visited [ u ] : q . put ( u ) self . visited [ u ] = True
큐 생성 후, 매개변수로 전달된 시작 정점을 삽입하고 큐가 비기 전까지 while문을 통해 모든 정점을 방문함.
q = Queue() : 큐 생성
: 큐 생성 self.init_visited() : 모든 정점에 대해 방문 기록 초기화
: 모든 정점에 대해 방문 기록 초기화 q.put(v) : 정점 v를 q에 넣음
: 정점 v를 q에 넣음 self.visited[v] = True : 해당 정점 방문 완료
: 해당 정점 방문 완료 while not q.empty(): : q가 빌 때까지 while 루프를 돌면서 모든 정점 방문
: q가 빌 때까지 while 루프를 돌면서 모든 정점 방문 v = q.get() : get()을 통해 dequeue로 q의 front값을 pop하면서 그 값을 다음 정점으로 선정
: get()을 통해 dequeue로 q의 front값을 pop하면서 그 값을 다음 정점으로 선정 adj_v = self.adj_list[v] : adj_v는 해당 정점 v에 대한 인접한 모든 정점
: adj_v는 해당 정점 v에 대한 인접한 모든 정점 for문을 순회하며 방문하지 않은 정점을 큐에 넣고, 최초 v의 인접 정점의 방문 여부 True로 변경함.
ex) 0-2-1-3으로 된 그래프에서 2가 시작점이었다면, 2를 dequeue 하면서 queue에는 0과 1이 삽입됨. 0이 dequeue될 때는 0과 연결된 인접 정점이 없으므로 그대로 dequeue되며, 1의 경우 3을 삽입 후 dequeue됨. 3이 dequeue될 경우에도 인접 정점이 없으므로 dequeue된 후, 큐는 비게 되어 루프 종료 = 모든 정점 방문 완료
2) 깊이 우선 탐색(Depth First Search, DFS) : 스택 기반
시작 정점을 기준으로 인접한 모든 노드를 방문 후, 다시 시작 정점으로 돌아와 가보지 않은 방향으로 다시 방문
2-1) 재귀 함수를 이용(스택프레임)
def __dfs_recursion ( self , v ) : print ( v , end = ‘=’ ) self . visited [ v ] = True adj_v = self . adj_list [ v ] for u in adj_v : if not self . visited [ u ] : self . __dfs_recursion ( u ) def dfs ( self , v ) : self . init_visited ( ) self . __dfs_recursion ( v )
dfs : 재귀함수를 돌기 전 방문리스트를 초기화함.
__dfs_recursion : 매개변수 v를 먼저 방문 후, v와 인접한 adj_v의 리스트에 있는 모든 정점을 방문함. 방문하지 않은 정점을 만날 때는 재귀 함수 호출
ex) 0-1-2-3으로 된 그래프에서 2를 시작 정점으로 하는 경우 : dfs_rec(2)를 시작하면서 True로 변경, adj[2] = {1,3}이며 for 루프를 돌면서 dfs_rec(1), dfs_rec(0)을 돈 후, dfs_rec(3)까지 방문 후 종료.
-> 스택프레임 구조 : dfs_rec(2)-dfs_rec(1)-dfs_rec(0) -> dfs_rec(2)-dfs_rec(3) -> dfs_rec(2) -> None
ex) 0-1-2-3으로 된 그래프에서 2를 시작 정점으로 하는 경우 : dfs_rec(2)를 시작하면서 True로 변경, adj[2] = {1,3}이며 for 루프를 돌면서 dfs_rec(1), dfs_rec(0)을 돈 후, dfs_rec(3)까지 방문 후 종료. -> 스택프레임 구조 : dfs_rec(2)-dfs_rec(1)-dfs_rec(0) -> dfs_rec(2)-dfs_rec(3) -> dfs_rec(2) -> None 재귀 함수가 끝난 경우 반드시 시작 정점으로 돌아가며, 더이상 방문할 곳이 없는 경우 종료됨
2-2) 스택과 반복문 이용
def iter_dfs ( self , v ) : s = Stack ( ) self . init_visited ( ) s . push ( v ) self . visited [ v ] = True print ( v , end = ‘=’ ) is_visited = False while not s . empty ( ) : is_visited = False v = s . peak ( ) adj_v = self . adj_list [ v ] for u in adj_v : if not self . visited [ u ] : s . push ( u ) self . visited [ u ] = True is_visited = True break if not is_visited : s . pop ( )
s.push(v) : 최초 방문한 정점을 stack에 쌓음
: 최초 방문한 정점을 stack에 쌓음 is_visited = False : 아직 방문하지 않은 정점을 방문하였는가?
: 아직 방문하지 않은 정점을 방문하였는가? v = s.peak() : dfs와는 다르게 dequeue를 통해 정점을 가져오지 않고 peak 메서드 사용하여 스택에는 정점이 그대로 쌓여있음
: dfs와는 다르게 dequeue를 통해 정점을 가져오지 않고 peak 메서드 사용하여 스택에는 정점이 그대로 쌓여있음 is_visited = True break : 인접 정점들에 대해 순회하며 방문하지 않은 정점을 만난 경우 True로 변경 후, 방문하지 않았던 정점에 대하여 for문을 빠져나가 while 루프를 다시 돈다.
: 인접 정점들에 대해 순회하며 방문하지 않은 정점을 만난 경우 True로 변경 후, 방문하지 않았던 정점에 대하여 for문을 빠져나가 while 루프를 다시 돈다. for 문 빠져나가는 법
1) is_visited = True : 방문하지 않은 정점을 발견하여 이동한 경우 -> 스택에는 이동한 정점이 쌓여 있음. -> 다음 모든 정점 방문 후 pop()을 통해 해당 정점을 삭제 후 이전 정점으로 이동할 수 있음.
2) is_visited = False : adj[v]의 모든 노드를 방문한 상태 -> 이전 정점으로 이동해야하므로 현재 정점을 pop해야함
2-3) 그래프가 연결되어 있지 않은 경우
def dfs_all ( self ) : self . init_visited ( ) for i in range ( len ( self . visited ) ) : if not self . visited [ i ] : self . __dfs_recursion ( i )
[파이썬 알고리즘] 그래프 구현, DFS, BFS, 인접 행렬, 최소 신장 트리
파이썬 [파이썬 알고리즘] 그래프 구현, DFS, BFS, 인접 행렬, 최소 신장 트리 이재윤 ・ URL 복사 본문 기타 기능 공유하기 신고하기 그래프란? – 여러 노드가 서로 연결된 자료구조 – 여러 노드가 연결될 수 있음 – 그래프는 정점을 연결하는 간선의 방향성 여부에 따라 방향 그래프와, 무방향 그래프로 나눈다. – 트리의 노드에 해당하는 용어는 그래프에선 정점(Vertex) 이다. – 정점을 연결하는 선은 간선(Edge)이다. – 그래트는 정점과 간선의 집합이다. 무방향 그래프 위에 사진에서 정점의 집합 V(G) = {A,B,C,D} 이다. 간선의 집합 E(G) = { (A,B), (A,C), (A,D), (B,C), (C,D) } * (A,B) , (B,A) 는 중복이므로 한 번만 표기한다. 방향 그래프 – 위에 사진처럼 방향성이 있는 그래프이다. 화살표로 간선 방향을 표기하고, 그래프의 정점 집합이 무방향 그래프와 같다. 정점의 집합 V(G) = {A,B,C,D} 이다. 간선의 집합 E(G) = { , ,
, } * 방향 그래프에선 <> 로 표기 가중치 그래프 – 간선마다 가중치가 다르게 부여된 그래프이다. – 무방향 가중치 그래프, 방향 가중치 그래프가 있다. 그래프 순회 – 그래프의 모든 정점을 한 번씩 방문하는 것을 의미 – 깊이 우선 탐색 (Depth First Serch, DFS) – 너비 우선 탐색(Breadth First Serch, BFS) 인접 행렬 (Adjacency Matrix) – 그래프를 코드로 구현 하는 방법 – 정방형으로 구성된 행렬이다. – 정점이 n개인 그래프는 n * n 인접행렬로 표현한다. 위와 같이 인접 행렬에서는 연결되었다면 1, 연결되지 않으면 0으로 표시하고, 출발점과 도착점이 같은 자기 자신은 0으로 표시한다. * 무방향 그래프에서 인접 행렬은 대각선을 기준으로 서로 대칭한다. 무방향 그래프 G1과 방향 그래프 G3의 구현 코드 ## 무방향 그래프 G1과 방향 그래프 G3의 구현 ## ## 함수 선언 부분 ## class Graph() : # 인접 행렬을 2차원 배열로 구현 def __init__ (self, size) : self.SIZE = size self.graph = [[0 for _ in range(size)] for _ in range(size)] ## 전역 변수 선언 부분 ## G1 = None # 무방향 그래프 G3 = None # 방향 그래프 ## 메인 코드 부분 ## G1 = Graph(4) G1.graph[0][1] = 1; G1.graph[0][2] = 1; G1.graph[0][3] = 1 G1.graph[1][0] = 1; G1.graph[1][2] = 1 G1.graph[2][0] = 1; G1.graph[2][1] = 1; G1.graph[2][3] = 1 G1.graph[3][0] = 1; G1.graph[3][2] = 1 print(‘## G1 무방향 그래프 ##’) for row in range(4) : for col in range(4) : print(G1.graph[row][col], end = ‘ ‘) print() G3 = Graph(4) G3.graph[0][1] = 1; G3.graph[0][2] = 1 G3.graph[3][0] = 1; G3.graph[3][2] = 1 print(‘## G3 방향 그래프 ##’) for row in range(4) : for col in range(4) : print(G3.graph[row][col], end = ‘ ‘) print() ## 실행결과 ## ## G1 무방향 그래프 ## 0 1 1 1 1 0 1 0 1 1 0 1 1 0 1 0 ## G3 방향 그래프 ## 0 1 1 0 0 0 0 0 0 0 0 0 1 0 1 0 – 깊이 우선 탐색 (Depth First Serch, DFS) 구현하기 – 스택을 사용해야한다. – 방문한 정점을 스택에 푸시하고, 방문할 곳이 막다른 곳이라면 스택에서 팝하는 방식 이용 – 기존에 방문했는지 여부를 확인하고자 방문한 곳을 기록하는 배열을 사용 ## 깊이 우선 탐색 (Depth First Serch, DFS) 구현 ## ## 클래스와 함수 선언 부분 ## class Graph() : def __init__ (self, size) : self.SIZE = size self.graph = [[0 for _ in range(size)] for _ in range(size)] ## 전역 변수 선언 부분 ## G1 = None stack = [] visitedAry = [] # 방문한 정점 ## 메인 코드 부분 ## G1 = Graph(4) G1.graph[0][2] = 1; G1.graph[0][3] = 1 G1.graph[1][2] = 1 G1.graph[2][0] = 1; G1.graph[2][1] = 1; G1.graph[2][3] = 1 G1.graph[3][0] = 1; G1.graph[3][2] = 1 print(‘## G1 무방향 그래프 ##’) for row in range(4): for col in range(4): print(G1.graph[row][col], end = ‘ ‘) print() current = 0 # 시작 정점 stack.append(current) visitedAry.append(current) while (len(stack) != 0) : next = None for vertex in range(4) : if G1.graph[current][vertex] == 1 : if vertex in visitedAry : # 방문한 적이 있는 정점이면 탈락 pass else : # 방문한 적이 없으면 다음 정점으로 지정 next = vertex break if next != None : # 다음에 방문할 정점이 있는 경우 current = next stack.append(current) visitedAry.append(current) else : # 다음에 방문할 정점이 없는 경우 current = stack.pop() print(‘방문 순서 –>’, end = ‘ ‘) for i in visitedAry : print(chr(ord(‘A’)+i), end = ‘ ‘) ## 실행 결과 ## ## G1 무방향 그래프 ## 0 0 1 1 0 0 1 0 1 1 0 1 1 0 1 0 방문 순서 –> A C B D 최소 신장 트리 – 신장 트리란 최소 간선으로 그래프의 모든 정점이 연결되는 그래프이다. * 신장 트리의 특징으로 간선 개수 = 정점 개수 – 1 이다. 그래프의 간선에 가중치가 있는 그래프를 가중치 그래프라고 한다. 가중치 그래프에서 만들 수 있는 신장 트리 중 합계가 최소인 것을 최소 비용 신장 트리 라고 한다. 최소 비용 신장 트리를 구현하는 방법으로 프림(Prim), 크루스컬(Kruskal) 알고리즘이 있다. 가중치 그래프 구현하기 가중치가 없는 무방향 그래프는 간선이 연결되면1, 안되면 0으로 처리한 반면에, 가중치 그래프는 간선이 연결되면 1 대신 가중치 값을 넣고, 연결되지 않으면 0을 넣는다. ## 최소 비용으로 자전거 도로를 건설하는 코드 ## ## 클래스와 함수 선언 부분 ## class Graph() : def __init__ (self, size) : self.SIZE = size self.graph = [[0 for _ in range(size)] for _ in range(size)] def printGraph(g) : print(‘ ‘, end = ‘ ‘) for v in range(g.SIZE) : print(nameAry[v], end = ‘ ‘) print() for row in range(g.SIZE) : print(nameAry[row], end = ‘ ‘) for col in range(g.SIZE) : print(g.graph[row][col], end = ‘ ‘) print() print() def findVertex(g, findVtx) : # 정점이 그래프에 연결되어 있는지 확인하는 함수 stack = [] visitedAry = [] # 방문한 정점 current = 0 # 시작 정점 stack.append(current) visitedAry.append(current) while (len(stack) != 0) : next = None for vertex in range(gSize) : if g.graph[current][vertex] != 0 : if vertex in visitedAry : # 방문한 적이 있는 정점이면 탈락 pass else : # 방문한 적이 없으면 다음 정점으로 지정 next = vertex break if next != None : # 다음에 방문할 정점이 있는 경우 current = next stack.append(current) visitedAry.append(current) else : # 다음에 방문할 정점이 없는 경우 current = stack.pop() if findVtx in visitedAry : return True else : return False ## 전역 변수 선언 부분 ## G1 = None nameAry = [‘춘천’, ‘서울’, ‘속초’ ,’대전’, ‘광주’, ‘부산’] 춘천, 서울, 속초, 대전, 광주, 부산 = 0, 1, 2, 3, 4, 5 ## 메인 코드 부분 ## gSize = 6 G1 = Graph(gSize) G1.graph[춘천][서울] = 10; G1.graph[춘천][속초] = 15 G1.graph[서울][춘천] = 10; G1.graph[서울][속초] = 40; G1.graph[서울][대전] = 11 G1.graph[서울][광주] = 50 G1.graph[속초][춘천] = 15; G1.graph[속초][서울] = 40; G1.graph[속초][대전] = 12 G1.graph[대전][서울] = 11; G1.graph[대전][속초] = 12; G1.graph[대전][광주] = 20 G1.graph[대전][부산] = 30 G1.graph[광주][서울] = 50; G1.graph[광주][대전] = 20; G1.graph[광주][부산] = 25 G1.graph[부산][대전] = 30; G1.graph[부산][광주] = 25 print(‘## 자전거 도로 건설을 위한 전체 연결도 ##’) printGraph(G1) ## 가중치 간선 목록 ## edgeAry = [] for i in range(gSize) : for k in range(gSize) : if G1.graph[i][k] != 0 : edgeAry.append([G1.graph[i][k], i, k]) from operator import itemgetter edgeAry = sorted(edgeAry, key=itemgetter(0), reverse=True) newAry = [] for i in range(0, len(edgeAry), 2) : newAry.append(edgeAry[i]) index = 0 while (len(newAry) > gSize-1) : # 간선 개수가 ‘점점 개수-1’ 일 때까지 반복 start = newAry[index][1] end = newAry[index][2] saveCost = newAry[index][0] G1.graph[start][end] = 0 G1.graph[end][start] = 0 startYN = findVertex(G1, start) endYN = findVertex(G1, end) if startYN and endYN : del(newAry[index]) else : G1.graph[start][end] = saveCost G1.graph[end][start] = saveCost index += 1 print(‘## 최소 비용의 자전거 도로 연결도 ##’) printGraph(G1) ## 실행 결과 ## ## 자전거 도로 건설을 위한 전체 연결도 ## 춘천 서울 속초 대전 광주 부산 춘천 0 10 15 0 0 0 서울 10 0 40 11 50 0 속초 15 40 0 12 0 0 대전 0 11 12 0 20 30 광주 0 50 0 20 0 25 부산 0 0 0 30 25 0 ## 최소 비용의 자전거 도로 연결도 ## 춘천 서울 속초 대전 광주 부산 춘천 0 10 0 0 0 0 서울 10 0 0 11 0 0 속초 0 0 0 12 0 0 대전 0 11 12 0 20 0 광주 0 0 0 20 0 25 부산 0 0 0 0 25 0 인쇄
별의 블로그 :: [Python] 그래프(Graph)
728×90
728×170
그래프(Graph)
그래프(Graph)의 기본
그래프의 개념
그래프(Graph) : 여러 노드가 서로 연결된 자료구조
: 여러 노드가 서로 연결된 자료구조 루트에서 하위 노드 방향으로만 이어지는 트리 와 달리, 여러 노드가 연결되어 있을 수 있다.
와 달리, 여러 노드가 연결되어 있을 수 있다. 트리도 그래프의 일종이지만, 트리와 그래프를 구현하는 코드 등이 확연히 다르기 때문에 이 둘은 별도로 생각하는 편이 낫다.
트리(왼쪽)와 그래프(오른쪽)
그래프의 종류
그래프는 정점을 연결하는 간선 의 방향성 여부 에 따라 방향 그래프 와 무방향 그래프 로 나눈다.
에 따라 와 로 나눈다. 간선에 가중치(Weight)를 부여하여 가중치 그래프도 만들 수 있다.
무방향 그래프
트리의 노드(Node) 에 해당하는 용어가 그래프에서는 정점(Vertex) 이다.
에 해당하는 용어가 그래프에서는 이다. 정점을 연결하는 선 은 간선(Edge)이므로 그래프는 정점과 간선의 집합으로 볼 수 있다.
무방향 그래프 형태
그래프에서 정점은 Vertex의 V 로, 간선은 Edge의 E 로, 그래프는 Graph의 G 로 표기한다.
로, 간선은 Edge의 로, 그래프는 Graph의 로 표기한다. 따라서 정점 집합을 V(G)로, 간선 집합을 E(G)로 표기한다.
V(G1) = { A, B, C, D } V(G2) = { A, B, C, D }
무방향 그래프 의 간선은 연결하는 두 정점을 ( ) 괄호 로 표현한다. 정점 A와 B의 간선을 (A, B)로 표현한다.
의 간선은 연결하는 두 정점을 로 표현한다.
E(G1) = { (A, B), (A, C), (A, D), (B, C), (C, D) } E(G2) = { (A, B), (B, D), (D, C) }
방향 그래프
방향성이 있는 그래프는 화살표로 간선 방향을 표기하고, 그래프의 정점 집합이 무방향 그래프와 같다.
방향 그래프의 형태
V(G1) = { A, B, C, D } V(G2) = { A, B, C, D }
방향 그래프의 간선은 연결하는 두 정점을 < > 로 묶어 표현한다. 정점 A와 B의 간선을 로 표현한다.
로 묶어 표현한다. 그리고 방향성이 있어 와 는 서로 다른 간선이다.
E(G1) = { , ,
, } E(G2) = { , , } 가중치 그래프
간선 마다 가중치가 다르게 부여된 그래프 를 가중치 그래프(Weight Graph)라고 한다.
무방향 가중치 그래프와 방향 가중치 그래프
깊이 우선 탐색(Depth First Search, DFS)
그래프 순회(Graph Traversal) : 그래프의 모든 정점을 한 번씩 방문하는 것
그래프의 모든 정점을 한 번씩 방문하는 것 그래프 순회 방식 깊이 우선 탐색(Depth First Search, DFS) 너비 우선 탐색(Breath First Search, BFS)
깊이 우선 탐색의 예
그래프는 트리와 달리 부모와 자식 개념이 없으므로, 어떤 정점에서 시작해도 결과는 같다.
모든 노드를 방문한 것처럼 보이지만, 그래프는 정점마다 연결된 선이 여러 개 있을 수 있기 때문에 반드시 시작 정점까지 돌아가야 한다.
그래프의 인접 행렬 표현
그래프를 코드로 구현할 때는 일반적으로 인접 행렬(Adjacent Matrix) 을 사용한다.
을 사용한다. 인접 행렬은 정방향으로 구성된 행렬 로, 정점이 4개인 그래프는 4×4 인접 행렬 로 표현한다.
로, 정점이 4개인 그래프는 로 표현한다. 출발점과 도착점이 연결되었다면 1로, 연결되지 않았다면 0으로 표시한다.
출발점과 도착점이 같은 자기 자신 은 모두 0으로 표시된다.
무방향 그래프의 인접 행렬
무방향 그래프의 인접 행렬은 대각선을 기준으로 서로 대칭 된다.
방향 그래프의 인접 행렬
방향 그래프는 무방향 그래프와 달리 대각선을 기준으로 대칭되지 않는다. 도착점과 출발점이 대칭되지 않아 는 와 다르다.
그래프의 구현
① 그래프의 정점 생성
class Graph : def __init__(self, size) : self.SIZE = size self.graph = [[0 for _ in range(size)] for _ in range(size)] G1 = Graph(4)
② 그래프의 정점 연결
G1.graph[0][1] = 1 # (A, B) 간선 G1.graph[0][2] = 1 # (A, C) 간선 G1.graph[0][3] = 1 # (A, D) 간선
G1.graph[1][0] = 1 # (B, A) 간선 G1.graph[1][2] = 1 # (B, C) 간선
G1.graph[2][0] = 1 # (C, A) 간선 G1.graph[2][1] = 1 # (C, B) 간선 G1.graph[2][3] = 1 # (C, D) 간선 G1.graph[3][0] = 1 # (D, A) 간선 G1.graph[3][2] = 1 # (D, C) 간선
구현 : 무방향 그래프
class Graph() : def __init__ (self, size) : self.SIZE = size self.graph = [ [0 for _ in range(size)] for _ in range(size) ] G1, G3 = None, None G1 = Graph(4) G1.graph[0][1] = 1; G1.graph[0][2] = 1; G1.graph[0][3] = 1 G1.graph[1][0] = 1; G1.graph[1][2] = 1 G1.graph[2][0] = 1; G1.graph[2][1] = 1; G1.graph[2][3] = 1 G1.graph[3][0] = 1; G1.graph[3][2] = 1 print(‘## G1 무방향 그래프 ##’) for row in range(4) : for col in range(4) : print(G1.graph[row][col], end=’ ‘) print() G3 = Graph(4) G3.graph[0][1] = 1; G3.graph[0][2] = 1 G3.graph[3][0] = 1; G3.graph[3][2] = 1 print(‘## G3 방향 그래프 ##’) for row in range(4) : for col in range(4) : print(G3.graph[row][col], end=’ ‘) print()
더보기 ## G1 무방향 그래프 ## 0 1 1 1 1 0 1 0 1 1 0 1 1 0 1 0 ## G3 방향 그래프 ## 0 1 1 0 0 0 0 0 0 0 0 0 1 0 1 0
그래프 개선
무방향 그래프를 인접 행렬로 구성할 때 0, 1, 2, … 숫자 로 구성했다.
로 구성했다. 하지만, 실제 그래프는 사람 이름, 도시 이름 등으로 구성하기도 한다.
변수 이름을 정점 번호 로 지정하면 더 직관적이다.
로 지정하면 더 직관적이다. 변수 이름은 한글도 지원된다.
문별, 솔라, 휘인, 쯔위 = 0, 1, 2, 3 G1.graph[문별][솔라] = 1; G1.graph[문별][쯔위] = 1 G1.graph[솔라][문별] = 1; G1.graph[솔라][쯔위] = 1
주석을 추가하여 그래프를 표현할 수 있다.
nameAry = [‘문별’, ‘솔라’, ‘휘인’, ‘쯔위’, ‘선미’, ‘화사’] print(‘\t’, end = ”) for v in range(g.SIZE) : print(nameAry[v], end = ‘\t’) print() for row in range(g.SIZE) : print(nameAry[row], end = ‘\t’) for col in range(g.SIZE) : print(g.graph[row][col], end= ‘\t’) print() print()
구현 : 개선된 무방향 그래프
class Graph() : def __init__ (self, size) : self.SIZE = size self.graph = [[0 for _ in range(size)] for _ in range(size)] def printGraph(g) : print(‘\t’, end = ”) for v in range(g.SIZE) : print(nameAry[v], end = ‘\t’) print() for row in range(g.SIZE) : print(nameAry[row], end = ‘\t’) for col in range(g.SIZE) : print(g.graph[row][col], end= ‘\t’) print() print() G1 = None nameAry = [‘문별’, ‘솔라’, ‘휘인’, ‘쯔위’, ‘선미’, ‘화사’] 문별, 솔라, 휘인, 쯔위, 선미, 화사 = 0, 1, 2, 3, 4, 5 gSize = 6 G1 = Graph(gSize) G1.graph[문별][솔라] = 1; G1.graph[문별][휘인] = 1 G1.graph[솔라][문별] = 1; G1.graph[솔라][쯔위] = 1 G1.graph[휘인][문별] = 1; G1.graph[휘인][쯔위] = 1 G1.graph[쯔위][솔라] = 1; G1.graph[쯔위][휘인] = 1; G1.graph[쯔위][선미] = 1; G1.graph[쯔위][화사] = 1 G1.graph[선미][쯔위] = 1; G1.graph[선미][화사] = 1 G1.graph[화사][쯔위] = 1; G1.graph[화사][선미] = 1 print(‘## G1 무방향 그래프 ##’) printGraph(G1)
더보기 ## G1 무방향 그래프 ## 문별 솔라 휘인 쯔위 선미 화사 문별 0 1 1 0 0 0 솔라 1 0 0 1 0 0 휘인 1 0 0 1 0 0 쯔위 0 1 1 0 1 1 선미 0 0 0 1 0 1 화사 0 0 0 1 1 0
728×90
그리드형
파이썬에서 그래프(Graph) 구현하기
이번 포스팅에서는 그래프(Graph) 자료구조 포스팅(https://junwha0511.blog.me/221698233962)에 이어
그래프를 파이썬에서 구현해보는 포스팅을 하겠습니다.
그래프(Graph) 자료구조란?
Graph는 정점(Vertex, 혹은 Node)과정점들을 연결하는 간선(Edge)으로 이루어진 자료구조입니다.
그래프 구조는 파이썬에서 딕셔너리 자료형(https://junwha0511.blog.me/221698243080)으로 구현할 수 있습니다.
바로 이중 딕셔너리를 사용하는 방법인데요,
예를 들어 A, B 정점이 있고 가중치가 5인 간선으로 이어져 있다면
weight = {‘A’:{‘B’:5}, ‘B’:{‘A’:5}}
위와 같이 A와 B의 상호 관계를 이중 딕셔너리를 사용해 표현할 수 있습니다.
하나하나 관계를 입력하는 것은 매우 시간이 오래 걸리는 작업이기 때문에
아래와 같이 ‘A-B=3’과 같은 형식으로 입력을 자동화하는 코드를 구현하였습니다.
weight = {‘A’:{}, ‘Z’:{}} flag={‘A’:True, ‘Z’:False} dist={‘A’:0, ‘Z’:float(‘inf’)} route=[‘Z’] ptd=’Z’ print(‘input Graph(like A-B=1, but always A is start node and Z is destination)’) print(‘if you like to stop, input END’) while True: while True: line = input() if line == ‘END’: break else: node1 = line[line.index(‘-‘)-1] node2 = line[line.index(‘-‘)+1] weightValue = int(line[line.index(‘=’)+1:]) if not (node1 in weight): weight[node1] = {} flag[node1] = False dist[node1] = float(‘inf’) if not (node2 in weight): weight[node2] = {} flag[node2] = False dist[node2] = float(‘inf’) weight[node1][node2] = weightValue weight[node2][node1] = weightValue print(‘Below is your graph, you like to stop? [Y/N]’) print(weight) print(flag) print(dist) isYes = input() if isYes==’Y’: break while not flag[‘Z’]: nextDist=float(‘inf’) nextNode=None for key in flag.keys(): if flag[key]: for node in weight[key]: if not flag[node]: cDist=dist[key]+weight[key][node] if cDist
[파이썬(python) 자료구조] 그래프 (Graph)
그래프
: 연결되어 있는 객체 간의 관계를 표현하는 비선형 자료구조
가장 일반적인 자료구조의 형태로, tree도 그래프의 특수한 경우이다. 예를 들면, 전기회로의 소자 간 연결 상태나 혹은 운영체제의 프로세스와 자원 관계 또한 그래프로 표현이 가능하다.
그래프의 정의
그래프 G는 (V,E)로 표시하며, 이때 V는 정점 vertex의 집합을 E는 간선 edge의 집합을 의미함.
(그림 A)
– vertex (정점)
: 여러 가지 특성을 가질 수 있는 객체를 의미함. 노드(node)라고도 함.
– edge (간선)
: 정점들 간의 관계를 의미. link라고도 함.
그래프의 종류
1) 무향 그래프 (undirected graph)
: 무향 에지는 양방향의 의미임. 예컨대 조합(combination)처럼 (A,B) = (B,A)로 순서에 의미가 없다는 것.
2) 방향 그래프 (directed graph)
: 에지를 통해서 한쪽 방향으로만 갈 수 있다는 특징. 즉,
≠ 라는 특성을 보임. (그림 B)
cf.) 가중치 그래프: 각 간선에 가중치를 부여한 형태의 그래프. 예를 들면 edge에 비용을 부과하는 형식으로 가중치가 부과될 수 있음.
그래프 관련 특성
인접 정점
: 어떤 정점에서 에지에 의해 직접 연결된 정점. 위의 그림 A를 참고했을 때, 정점4의 인접 정점은 정점 3이다.
그래프 차수
1) 무향 그래프
하나의 정점에 연결된 다른 정점의 수 (인접 정점의 수)
그림 A에서 정점 4의 차수는 1, 정점 3의 차수는 3.
무향 그래프 정점들의 모든 차수의 합은 에지 개수의 2배이다.
2) 유향 그래프
유향 그래프에서의 차수는 진입 차수와 진출 차수 두 가지로 구분된다. 진입 차수(in-degree)는 외부에서 오는 에지의 수이며, 진출 차수(out-degree)는 외부로 향하는 에지의 수이다.
그림 B에서의 유향 그래프에서 정점 B의 진입 차수는 1이고, 진출 차수는 2이다.
방향 그래프의 모든 진입(또는 진출) 차수의 합은 에지의 수와 같다. 즉, 진입 차수의 합 == 진출 차수의 합 == 그래프 내 모든 에지의 수라고 할 수 있다.
그래프의 경로
: 그래프의 경로라 함은, 그래프 내의 정점 s로부터 정점 t까지의 경로를 의미하며, 두 정점 간의 경로 상의 모든 정점의 나열을 통해 표현된다.
ex. s→v1→v2→…→vk→t
이때 나열된 정점들 간에 반드시 에지 (s,v1), (v1, v2), …, (vk,t)가 존재한다. 여기서는 무향 그래프의 표현 방식을 따랐지만 이는 유향 그래프의 경우에도 동일하게 적용이 된다.
해당 경로의 길이는 경로를 구성하는 에지의 수로 정의되며, 사이클(순환)은 경로의 시작 정점과 끝 정점이 동일한 경로를 의미한다. 여기서의 경로는 경로 중에서 반복되는 정점 및 에지가 없는 경로인 단순 경로로 한정하도록 한다.
그래프의 연결성 (connectivity)
연결 그래프 (connected graph)
무향 그래프 G에 있는 모든 정점 쌍에 대하여 경로가 존재할 경우, 무향 그래프 G는 연결 그래프이다. 여기서 주의할 점은, 모든 정점 쌍에 대하여 경로가 존재한다는 것은 임의의 두 정점 간에 edge가 존재한다는 걸 의미하는 게 아니다. 하나의 정점에서 다른 정점으로 갈 수 있느냐 없느냐의 문제이다. 그래프가 네트워크를 의미하는 경우 그래프의 연결성은 네트워크의 reliability와 밀접한 연관이 있는 개념이라고 할 수 있다.
트리(tree)
그래프의 특수한 형태로서, 무순환 연결 그래프이다 (connected acyclic graph). 시작 정점에서 다시 시작 정점으로 돌아올 때 이미 방문한 엣지를 무조건 다시 방문하지 않고서는 불가능한 구조이다.
연결성의 입장에서는 최소로 연결이 되어있다. 최소로 연결되어 있다는 것은 하나의 edge만 삭제해도 연결그래프가 아니게 된다는 의미이다.
완전 그래프 (complete graph)
모든 정점이 서로 연결되어 있는 그래프.
n개의 정점을 가지는 완전 그래프의 에지 개수
→ (무향): n(n-1)/2, (유향): n(n-1)
그래프의 표현 방법
인접 행렬
정점의 개수를 k라고 했을 때, kXk matrix를 정의함. 각 row는 해당 정점의 연결 상태를 의미함.
공간 복잡도는 O(n^2)으로 희소 그래프인 경우 매우 비효율적이다.
[sudo code]for i=1~n_row for j=1~n_row if (edge exists) A[i][j] = 1 else A[i][j] = 0
자가 루프가 없는 단순 그래프의 경우 인접 행렬의 대각선 성분은 모두 0이 된다. 무향 그래프의 인접 행렬은 대칭행렬이다.
그래프 인접 행렬이 대칭행렬이라는 것은, upper or lower triangular matrix만 사용하여 표현이 가능하다는 것을 의미하고 이 경우 메모리 사용량을 save할 수 있다.
보통 0,1값을 갖는 행렬로 표현하지만 가중치 그래프의 경우 행렬의 성분에 가중치를 입력하는 형식으로 표현이 가능하다.
if ((i,j) exists) A[i][j] = W_ij else if (i==j) A[i][j] = 0 else A[i][j] = infinity // i,j 간 에지가 존재하지 않는 경우
인접 리스트
– 각 정점에 인접한 정점들을 연결 리스트로 표현한다. 정점이 n개인 그래프라면 n개의 연결리스트로 구성한다. 각 연결리스트마다 포인터 변수가 리스트의 처음 노드를 가리키며 연결리스트가 없는 경우, 즉 차수가 0인 경우 포인터 변수의 값은 null이 된다.
– 공간복잡도: $O(n+m)$
정점의 개수가 n, 에지의 개수가 m이라고 가정하자.
1) 무향그래프: n+2m
n개의 포인터 변수가 있어야 하고, 2m개의 일반 노드가 필요하다.
2m개의 일반 노드가 필요한 이유: 앞서 무향 그래프는 “양방향”의 의미라고 하였다. 따라서 정점0과 정점1간의 에지를 표현하고자 할 때, 정점0을 의미하는 포인터 변수에서 정점0→정점1 을 표현함과 동시에 정점1을 의미하는 포인터 변수에서 정점1→정점0을 표현해주어야 한다.
2) 방향그래프: n+m
n개의 포인터 변수와 m개의 일반 노드.
m개의 일반 노드가 필요한 이유: 일방향이기 때문에 하나의 에지로 연결된 두 정점에 대해 중복으로 표기하는 것이 아니다. 따라서, 시작 정점에서 끝 정점만 연결해주면 되므로 에지 하나당 하나의 노드만 필요하다.
만약 그래프 G가 완전 그래프이고 이를 인접 리스트로 표현하고자 한다면, 이는 $O(n^2)$의 비용이 들 것이다. (인접 리스트여도 완전 그래프를 표현하고자 한다면 인접 행렬과 동일한 비용이 든다는 것)
– 인접리스트의 구현 in Python
파이썬은 포인터가 따로 존재하지 않으므로, 연결리스트를 구현하기 까다롭다. 따라서 인접 리스트를 출발 노드를 키로, 도착 노드를 값으로 표현하는 딕셔너리 형태로 표현한다. 도착 노드의 경우에는 여러 개의 노드가 가능하므로 값은 리스트 형태로 표현한다.
graph = { 0: [1], 1: [0,2], 2: [] } # 인접 리스트 그림 (c)를 파이썬으로 표현한 형태
반응형
[Python & Data Structure] Graph
728×90
반응형
✏️ Graph (그래프의 개념)
연결되어 있는 객체간의 관계를 표현하는 비선형 자료구조
가장 일반적인 자료구조의 형태이며, Tree 도 그래프의 특수한 경우이다.
하나의 점을 Vertex 라고 한다.
라고 한다. 하나의 선을 Edge 라고 한다. Link 라고도 함.
✏️ Graph (용어)
비가중치 그래프 / 가중치 그래프
: 비가중치 그래프는 각 vertex 간의 연결 유무만을 판단한다. 가중치 그래프는 각 간선(edge)에 가중치를 부여한 형태로 예를 들면 edge에 비용을 부과하는 형식으로 가중치가 부과될 수 있다. 위의 그림은 가중치 그래프이다.
무향(undirected) 그래프 / 유향(directed) 그래프
: 무향 edge는 양방향의 의미를 가진다. (A,B)=(B,A) 로 순서에 의미를 가지지 않는다. 방향 그래프는 edge를 통해서 한 방향으로만 갈 수 있다. =/= .
인접(adjacency) 정점
: 한 vertex에서 edge로 직접 연결된 vertex. ‘그래프의 개념’에서 이용한 그래프를 참고한다면 vertex 4 의 인접정점은 vertex 3 이다.
그래프의 차수(degree)
1) 무향 그래프 : 그래프의 차수는 인접 정점의 수와 같다. 따라서 모든 차수의 합은 edge 개수의 2배라는 특성을 가진다.
2) 유향 그래프 : 집입차수 (in-degree) 와 진출차수 (out-degree)로 구분된다. 진입차수는 외부에서 오는 간선의 수이며, 진출 차수는 외부로 향하는 간선의 수이다. 방향 그래프의 모든 진입차수 또는 진출차수의 합은 에지의 수와 같다. 즉, 진입차수의 합 = 진출차수의 합 = 그래프 내 모든 간선의 수.
✏️ Graph (용어)
비가중치 그래프 / 가중치 그래프
: 비가중치 그래프는 각 vertex 간의 연결 유무만을 판단한다. 가중치 그래프는 각 간선(edge)에 가중치를 부여한 형태로 예를 들면 edge에 비용을 부과하는 형식으로 가중치가 부과될 수 있다. 위의 그림은 가중치 그래프이다.
무향(undirected) 그래프 / 유향(directed) 그래프
: 무향 edge는 양방향의 의미를 가진다. (A,B)=(B,A) 로 순서에 의미를 가지지 않는다. 방향 그래프는 edge를 통해서 한 방향으로만 갈 수 있다. =/= .
인접(adjacency) 정점
: 한 vertex에서 edge로 직접 연결된 vertex. ‘그래프의 개념’에서 이용한 그래프를 참고한다면 vertex 4 의 인접정점은 vertex 3 이다.
그래프의 차수(degree)
1) 무향 그래프 : 그래프의 차수는 인접 정점의 수와 같다. 따라서 모든 차수의 합은 edge 개수의 2배라는 특성을 가진다.
2) 유향 그래프 : 집입차수 (in-degree) 와 진출차수 (out-degree)로 구분된다. 진입차수는 외부에서 오는 간선의 수이며, 진출 차수는 외부로 향하는 간선의 수이다. 방향 그래프의 모든 진입차수 또는 진출차수의 합은 에지의 수와 같다. 즉, 진입차수의 합 = 진출차수의 합 = 그래프 내 모든 간선의 수.
자기루프 (self loop)
정점에서 출발한 간선이 바로 자기자신에게 진입하는 경우. 다른 정점을 거치지 않는다.
사이클 (cycle)
한 정점에서 출발해 다시 해당 정점으로 돌아갈 수 있는 경우.
✏️ Graph의 표현 : 인접행렬과 인접리스트
인접행렬
만약 A라는 점과 B라는 정점이 연결되어있다면 1, 아니면 0으로 표시한 행렬
만약 가중치 그래프라면 1 대신 가중치를 저장한다.
최단경로문제에서 주로 사용된다
인접행렬
[Sudo code]for i in range(n_row) for j in range(n_row) if (edge exists): A[i][j] = 1 else: A[i][j] = 0
* self loop가 없다면 단순그래프의 인접행렬의 대각성 성분은 모두 0 이 된다. 또한 무향 그래프의 인접행렬은 대칭 행렬이다.
인접리스트
인접리스트는 각 vertex가 어떤 정점과 인접한지를 리스트의 형태로 표현한 것이다.
각 정점마다 하나의 리스트를 가진다.
하나의 리스트는 자신과 인접한 다른 정점을 담고 있다.
가중치 그래프의 인접리스트 표현
간단한 구조의 그래프는 인접행렬로 구현이 가능하지만 시간복잡도 O(n^2)가 걸리기 때문에 그래프의 vertex가 많다면 O(n)이 걸리는 인접리스트로 구현하는 것이 효율적이다. 복잡하고 어려운 상황의 그래프에서는 인접리스트가 더 효율적으로 그래프를 저장, 탐색하도록 해준다.
[파이썬에서 인접리스트의 구현]파이썬은 포인터가 따로 존재하지 않는다. 따라서 출발노드를 키로, 도착노드를 값으로 표현하는 딕셔너리 형태로 표현한다.
G = { 0: [1], 1: [0, 2], 2: [] }
DFS와 BFS 까지 설명하고 구현하려했는데 따로 쓰는게 좋을 것 같아서 다음 글에 이어서 작성하려한다.
728×90
반응형
키워드에 대한 정보 파이썬 그래프 구현
다음은 Bing에서 파이썬 그래프 구현 주제에 대한 검색 결과입니다. 필요한 경우 더 읽을 수 있습니다.
이 기사는 인터넷의 다양한 출처에서 편집되었습니다. 이 기사가 유용했기를 바랍니다. 이 기사가 유용하다고 생각되면 공유하십시오. 매우 감사합니다!
사람들이 주제에 대해 자주 검색하는 키워드 [자료구조 알고리즘] Graph 검색 DFS, BFS 구현 in Java
- Coding Interview
- 코딩 인터뷰
- Java
- 자바
- Algorithm
- 자료구조
- Data structure
- 알고리즘
- Graph Search
- 그래프 검색
- Graph
- 그래프
- DFS
- BFS
- 깊이우선검색
- 넓이우선검색
YouTube에서 파이썬 그래프 구현 주제의 다른 동영상 보기
주제에 대한 기사를 시청해 주셔서 감사합니다 [자료구조 알고리즘] Graph 검색 DFS, BFS 구현 in Java | 파이썬 그래프 구현, 이 기사가 유용하다고 생각되면 공유하십시오, 매우 감사합니다.