datastructure

최소 신장 트리

신장 트리란?

그래프에 순환 구조가 없이 모든 정점이 연결되어있는 트리

image

최소 신장 트리란?

간선의 길이가 가장 짧은 신장 트리를 말한다.

최소 신장 트리 = 최소 비용 신장 트리

최소 신장 트리를 구현하기 위한 두 가지 알고리즘이 존재한다.

  • 크루스칼 알고리즘
  • 프림 알고리즘

프림 알고리즘

매 순간 가장 가까운 정점을 찾아서 모든 정점을 가장 짧게 연결하는 알고리즘 ⊂ 탐욕 알고리즘

최단 경로 알고리즘인 다익스트라 알고리즘과 비슷하다

다익스트라 알고리즘은 최단 거리가 보장되지만, 프림 알고리즘은 최단 거리가 아닐 수 있다.

다익스트라프림
최단 거리 보장최소 비용 연결 (최단 거리 보장 X)
방향 그래프, 무방향 그래프 둘 다 동작무방향 그래프 동작

구현

class Prim{
	constructor(){
		this.all_cities = {};
	}
	
	registerCity(city) {
		this.all_cities[city.name] = city;
	}

	MST(start_city) {
		let visited_cities = {};
		let unvisited_cities= {};
		let mst_table = {};
	
		for(let city_name in this.all_cities) {
			unvisited_cities[city_name] = this.all_cities[city.name];
		}

		// 출발 도시가 등록되지 않은 경우 (없는 경우)
		if(unvisited_cities[start_city.name] == null) {
			return null;
		}else {
			// 순회하면서 모든 도시의 거리를 무한대로 설정
			for(let city_name in unvisited_cities) {
				// shortest_path_table[city_name] = Infinity;
				shortest_path_table[city_name] = {distance: Infinity, city: null};
			}
		}
		// 시작 도시는 거리 0
		// shortest_path_table[start_city.name] = 0;
		shortest_path_table[city_name] = {distance: 0, city: null};

		while(Object.keys(unvisited_cities).length > 0) {
			let closest_city_name = null;
			
			for(let city_name in unvisited_cities){
				// 
				if(closest_city_name == null || shortest_path_table[city_name].distance < shortest_path_table[closest_city_name].distance){
					closest_city_name = city_name;
				}
			}
	
			// 가장 가까운 도시를 방문한 도시로 설정하고 방문하지 않은 도시에서 제거
			visited_cities[closest_city_name] = unvisited_cities[closest_city_name];
			delete unvisited_cities[closest_city_name];

			for(let adjacent_city_name in visited_cities[closest_city_name].adjacent_cities) {
				if(unvisited_cities[adjacent_city_name] == null) {
					continue;
				}

				// 출발 도시에서 현재 도시까지의 거리 + 현재 도시에서 인접 도시까지의 거리
				// let distance = shortest_path_table[closest_city_name].distance +
				// visited_cities[closest_city_name].adjacent_cities[adjacent_cities_name];

				let distance = visited_cities[closest_city_name].adjacent_cities[adjacent_cities_name];

				// 만약 계산된 거리가 기존의 최소 거리보다 짧은 경우 최단 거리 갱신
				if(shortest_path_table[adjacent_cities_name].distance > distance) {
					shortest_path_table[adjacent_cities_name].distance = distance;
					shortest_path_table[adjacent_cities_name].cirt= visited_cities[closest_city_name];
				}
			}
		}
		console.log(mst_table);
	}
}