본 포스팅은 아래의 출처를 참고하여 정리한 것입니다.
https://www.youtube.com/watch?v=PIidtIBCjEg&list=PLsMufJgu5933ZkBCHS7bQTx0bncjwi4PK&index=1
G=(V,E)
V
: vertex(node) set, 정점E
: edge, 링크degree(인접성): 노드의 edge 개수, ex) degree(4)=3, degree(1)=2, ... ➡️ degree(G)=3 (max값)
edge(4, 5) = 노드 4와 노드 5는 인접하다 (adjacent)
경로(path): ex) 3에서 5로 가는 path는 [3 ➡️ 2 ➡️ 5], [3 ➡️ 2 ➡️ 1 ➡️ 5], ...
사이클(cycle): 어떤 노드에서 출발해서 제자리로 돌아오는 닫힌 경로, ex) [3 ➡️ 2 ➡️ 5 ➡️ 4 ➡️ 3]
그래프에서 사이클이 없을 수도 있고, 많을 수도 있다
사이클이 없는 그래프 = 트리: 부모-자식 관계의 edge만 존재하므로
방향성이 없는 그래프(=양방향 그래프): undirected graph
방향성이 있는 그래프(=방향 그래프): directed graph, edge에 화살표가 존재
2. 인접 리스트 (adjacency list) (이때 list는 연결리스트)
- 각 vertex가 자기 만의 연결 리스트를 가지고 있음 (자신과 인접한 vertex들)
- 존재하는 edge만 표현돼 edge 개수의 2배 -> 무방향 그래프라서
G=(V,E)=(노드 집합, 에지 집합)
|V| = n
|E| = m
memory:
의 edge가 존재하느냐
G[u][v]==1 or G[u][v] > 0
: (상수 시간에 가능)에 인접한 모드 노드 에 대해 (어떤 action): for v in range(1, n+1): do with G[u][v]
➡️
새로운 에지 (u,v)
삽입: G[u][v]=1 (or weight)
기존 (u,v)
삭제: G[u][v]=0
1. memory:
2. 의 edge가 존재하느냐
G[u].search(v)
: (최악의 경우 모든 노드가 에 연결되어있을 수 있음)에 인접한 모드 노드 에 대해 (어떤 action): for each edge in G[u]: do something
G
안의 each edge
== each node
➡️ 새로운 에지 (u,v)
삽입: G[u].pushFront(v)
➡️
.append()
를 통해 상수 시간 보장 가능기존 (u,v)
삭제: x=G[u].search(v)
G[u].remove(x)
➡️ (삭제할 노드 찾는데 걸리는 최악의 시간)
메모리 측면에서는 인접 행렬 () << 인접 리스트 ()
sparse graph: 노드 개수에 비해 에지 개수가 상당히 적은 경우 ↔️ dense graph