TIL(38) Graph

codedotΒ·2021λ…„ 8μ›” 28일
0

Graph(κ·Έλž˜ν”„) ✍🏻

Graph(κ·Έλž˜ν”„)πŸ“


  • μ—¬λŸ¬κ°œμ˜ 점듀이 μ„œλ‘œ λ³΅μž‘ν•˜κ²Œ μ—°κ²°λ˜μ–΄ μžˆλŠ” 관계λ₯Ό ν‘œν˜„ν•œ 자료ꡬ쑰
  • 직접적인 관계가 μžˆλŠ” 경우 두 점 사이λ₯Ό μ΄μ–΄μ£ΌλŠ” 선이 있고, 가넙적인 관계라면 λͺ‡ 개의 점과 선에 걸쳐 이어진닀.
  • ν•˜λ‚˜μ˜ 점을 κ·Έλž˜ν”„μ—μ„œλŠ” 정점(vertex)이라 ν‘œν˜„ν•˜κ³ , ν•˜λ‚˜μ˜ 선은 κ°„μ„ (edge)라 ν•œλ‹€.

κ·Έλž˜ν”„μ˜ μ‹€μ‚¬μš© 예제 πŸ“Œ

  • ν¬νƒˆ μ‚¬μ΄νŠΈμ˜ 검색 엔진, SNSμ—μ„œ μ‚¬λžŒλ“€κ³Όμ˜ 관계, λ„€μ΄κ²Œμ΄μ…˜(κΈΈμ°ΎκΈ°) λ“±μ—μ„œ μ‚¬μš©ν•˜λŠ” μžλ£Œκ΅¬μ‘°κ°€ κ·Έλž˜ν”„λ‹€.
  • μ„Έ 가지 λͺ¨λ‘ 수 λ§Žμ€ 정점을 가지고 있고, μ„œλ‘œ 관계가 μžˆλŠ” 정점은 κ°„μ„ μœΌλ‘œ 이어져 μžˆλ‹€.

μ•Œμ•„λ‘¬μ•Ό ν•  κ·Έλž˜ν”„ μš©μ–΄λ“€ πŸ“Œ

  • 단방ν–₯κ·Έλž˜ν”„(directed graph) : λ„€μ΄κ²Œμ΄μ…˜μ€ 단방ν–₯ κ·Έλž˜ν”„μ΄λ‹€. μ„œμšΈμ—μ„œ λΆ€μ‚°μœΌλ‘œ 갈 수 μžˆλ“―, λ°˜λŒ€λ‘œ λΆ€μ‚°μ—μ„œ μ„œμšΈλ‘œ κ°€λŠ”κ²ƒλ„ κ°€λŠ₯ν•˜λ‹€. ν•˜μ§€λ§Œ 단방ν–₯(directed) κ·Έλž˜ν”„λ‘œ κ΅¬ν˜„λ˜λ‹€λ©΄ μ„œμšΈμ—μ„œ 뢀산을 갈 수 μžˆμ§€λ§Œ, λΆ€μ‚°μ—μ„œ μ„œμšΈλ‘œ κ°€λŠ” 것은 λΆˆκ°€λŠ₯ν•˜λ‹€(ν˜Ήμ€ κ·Έ λ°˜λŒ€). λ§Œμ•½ 두 지점이 일방톡행 λ„λ‘œλ‘œ 이어져 μžˆλ‹€λ©΄ 단방ν–₯인 κ°„μ„ μœΌλ‘œ ν‘œν˜„ν•  수 μžˆλ‹€.

  • μ§„μž…μ°¨μˆ˜(in-degree) / μ§„μΆœμ°¨μˆ˜ (out-degree) : ν•œ 정점에 μ§„μž…(λ“€μ–΄μ˜€λŠ” κ°„μ„ )ν•˜κ³  μ§„μΆœ(λ‚˜κ°€λŠ” κ°„μ„ )ν•˜λŠ” 간선이 λͺ‡ κ°œμΈμ§€λ₯Ό λ‚˜νƒ€λ‚Έλ‹€.

  • 인접(adjacency) : 두 정점간에 간선이 직접 이어져 μžˆλ‹€λ©΄ 이 두 정점은 μΈμ ‘ν•œ μ •μ μž…λ‹ˆλ‹€.

  • 자기 루프(self loop) : μ •μ μ—μ„œ μ§„μΆœν•˜λŠ” 간선이 κ³§λ°”λ‘œ 자기 μžμ‹ μ—κ²Œ μ§„μž…ν•˜λŠ” 경우 자기 루프λ₯Ό κ°€μ‘Œλ‹€ 라고 ν‘œν˜„ν•œλ‹€. λ‹€λ₯Έ 정점을 κ±°μΉ˜μ§€ μ•ŠλŠ”λ‹€λŠ” 것이 νŠΉμ§•

  • 사이클(cycle) : ν•œ μ •μ μ—μ„œ μΆœλ°œν•˜μ—¬ λ‹€μ‹œ ν•΄λ‹Ή μ •μ μœΌλ‘œ λŒμ•„κ°ˆ 수 μžˆλ‹€λ©΄ 사이클이 μžˆλ‹€κ³  ν‘œν˜„ν•œλ‹€.
    λ‚΄λΉ„κ²Œμ΄μ…˜ κ·Έλž˜ν”„λŠ” μ„œμšΈ -> λŒ€μ „ -> λΆ€μ‚° -> μ„œμšΈ 둜 이동이 κ°€λŠ₯ν•˜λ―€λ‘œ, 사이클이 μ‘΄μž¬ν•˜λŠ” κ·Έλž˜ν”„ 이닀.


κ·Έλž˜ν”„μ˜ ν‘œν˜„ 방식 (인접 ν–‰λ ¬ & 인접 리슀트)

인접 ν–‰λ ¬

  • 두 정점을 λ°”λ‘œ 이어 μ£ΌλŠ” 간선이 μžˆλ‹€λ©΄ 이 두 정점은 μΈμ ‘ν•˜λ‹€.
  • 인접 행렬은 μ„œλ‘œ λ‹€λ₯Έ 정점듀이 μΈμ ‘ν•œ μƒνƒœμΈμ§€λ₯Ό ν‘œμ‹œν•œ ν–‰λ ¬λ‘œ 2차원 λ°°μ—΄μ˜ ν˜•νƒœλ‘œ λ‚˜νƒ€λ‚Έλ‹€.
  • λ§Œμ•½ AλΌλŠ” 정점과 BλΌλŠ” 정점이 이어져 μžˆλ‹€λ©΄ 1(true), 이어져 μžˆμ§€ μ•Šλ‹€λ©΄ 0(false)으둜 ν‘œμ‹œν•œ μΌμ’…μ˜ ν‘œ
  • λ§Œμ•½ κ°€μ€‘μΉ˜ κ·Έλž˜ν”„λΌλ©΄ 1 λŒ€μ‹  κ΄€κ³„μ—μ„œ 의미 μžˆλŠ” 값을 μ €μž₯ν•œλ‹€.

인접 리슀트

  • 보톡은 μ€‘μš”ν•˜μ§€ μ•Šλ‹€.
  • κ·Έλž˜ν”„, 트리, μŠ€νƒ, 큐 λ“± λͺ¨λ“  자료 κ΅¬μ‘°λŠ” κ΅¬ν˜„ν•˜λŠ” μ‚¬λžŒμ˜ νŽΈμ˜μ™€ λͺ©μ μ— 따라 κΈ°λŠ₯을 μΆ”κ°€/μ‚­μ œν•  수 μžˆλ‹€.
  • κ·Έλž˜ν”„λ₯Ό 인접 리슀트둜 κ΅¬ν˜„ν•  λ•Œ, μ •μ λ³„λ‘œ μ‚΄νŽ΄λ΄μ•Ό ν•  μš°μ„  μˆœμœ„λ₯Ό κ³ λ €ν•΄ κ΅¬ν˜„ν•  수 μžˆλ‹€. μ΄λ•Œ, λ¦¬μŠ€νŠΈμ— 담겨진 정점을 μš°μ„  μˆœμœ„λ³„λ‘œ μ •λ ¬ν•  수 μžˆλ‹€. μš°μ„  μˆœμœ„κ°€ μ—†λ‹€λ©΄, μ—°κ²°λœ 정점듀을 λ‹¨μˆœν•˜κ²Œ λ‚˜μ—΄ν•œ λ¦¬μŠ€νŠΈκ°€ λœλ‹€.
  • μš°μ„  μˆœμœ„λ₯Ό 닀뀄야 ν•œλ‹€λ©΄ 더 μ ν•©ν•œ 자료ꡬ쑰(ex. queue, heap)λ₯Ό μ‚¬μš©ν•˜λŠ” 것이 합리적이닀. λ”°λΌμ„œ 보톡은 μ€‘μš”ν•˜μ§€ μ•Šλ‹€. (μ–Έμ œλ‚˜ μ˜ˆμ™ΈλŠ” μžˆλ‹€...)

Graph 자료ꡬ쑰

// directed graph (λ°©ν–₯ κ·Έλž˜ν”„)
// unweighted (λΉ„κ°€μ€‘μΉ˜)
// adjacency matrix (인접 ν–‰λ ¬)
// 이해λ₯Ό 돕기 μœ„ν•΄ κΈ°μ‘΄ λ°°μ—΄μ˜ 인덱슀λ₯Ό μ •μ μœΌλ‘œ μ‚¬μš©ν•©λ‹ˆλ‹€ (0, 1, 2, ... --> 정점)

class GraphWithAdjacencyMatrix {
	constructor() {
		this.matrix = [];
	}

	addVertex() {
        //λ²„ν…μŠ€λ₯Ό μΆ”κ°€ν•©λ‹ˆλ‹€.
		const currentLength = this.matrix.length;
		for (let i = 0; i < currentLength; i++) {
			this.matrix[i].push(0);
		}
		this.matrix.push(new Array(currentLength + 1).fill(0));
	}

	contains(vertex) {
        //TODO: λ²„ν…μŠ€(인덱슀)κ°€ μžˆλŠ”μ§€ ν™•μΈν•©λ‹ˆλ‹€.
        if(0 <= vertex && vertex < this.matrix.length){ 
          return true;
        }
        return false;
	}

	addEdge(from, to) {
		const currentLength = this.matrix.length;
		if (from === undefined || to === undefined) {
			console.log("2개의 μΈμžκ°€ μžˆμ–΄μ•Ό ν•©λ‹ˆλ‹€.");
			return;
		}
        //TODO: 간선을 μΆ”κ°€ν•  수 μ—†λŠ” μƒν™©μ—μ„œλŠ” μΆ”κ°€ν•˜μ§€ 말아야 ν•©λ‹ˆλ‹€.
		if (from + 1 > currentLength || to + 1 > currentLength || from < 0 || to < 0) {
			console.log("λ²”μœ„κ°€ 맀트릭슀 밖에 μžˆμŠ΅λ‹ˆλ‹€.");
			return;
		}
        //TODO: 간선을 μΆ”κ°€ν•΄μ•Ό ν•©λ‹ˆλ‹€.
      this.matrix[from][to] = 1;
	}

	hasEdge(from, to) {
		//TODO: 두 λ²„ν…μŠ€ 사이에 간선이 μžˆλŠ”μ§€ ν™•μΈν•©λ‹ˆλ‹€.
    if(this.matrix[from][to] === 1){
      return true;
    }
    return false;
	}

	removeEdge(from, to) { //엣지 제거
		const currentLength = this.matrix.length;
		if (from === undefined || to === undefined) {
			console.log("2개의 μΈμžκ°€ μžˆμ–΄μ•Ό ν•©λ‹ˆλ‹€.");
			return;
		}
        //TODO: 간선을 μ§€μšΈ 수 μ—†λŠ” μƒν™©μ—μ„œλŠ” μ§€μš°μ§€ 말아야 ν•©λ‹ˆλ‹€.
		if (from + 1 > currentLength || to + 1 > currentLength || from < 0 || to < 0) { //from, to λ²”μœ„κ°€ λ„˜μ–΄μ„œλŠ” 경우 간선을 μ§€μšΈ 수 μ—†λ‹€.
      return;
		}
        //TODO: 간선을 μ§€μ›Œμ•Ό ν•©λ‹ˆλ‹€.
        this.matrix[from][to] = 0;
	}
}
profile
Loding...

0개의 λŒ“κΈ€

κ΄€λ ¨ μ±„μš© 정보