728x90
1. 다익스트라 알고리즘
다익스트라의 이름을 딴 알고리즘으로 그래프의 두 정점사이에 존재하는 최단경로를 찾는 알고리즘이다.
그래프를 가로지르면서 순회하고 우선순위큐를 사용한다.
gps, 네트워크 라우팅, 전염병 등등 많은 부분에서 씅니다.
2. 우선순위큐
class PriorityQueue {
constructor() {
this.values = [];
}
enqueue(val, priority) {
this.values.push({ val, priority });
this.sort();
}
dequeue() {
return this.values.shift();
}
sort() {
this.values.sort((a, b) => a.priority - b.priority);
}
}
3. 다익스트라 알고리즘
class PriorityQueue {
constructor() {
this.values = [];
}
enqueue(val, priority) {
this.values.push({ val, priority });
this.sort();
}
dequeue() {
return this.values.shift();
}
sort() {
this.values.sort((a, b) => a.priority - b.priority);
}
}
class WeightedGraph {
constructor() {
this.adjacencyList = {};
}
addVertex(vertex) {
if (!this.adjacencyList[vertex]) this.adjacencyList[vertex] = [];
}
addEdge(vertex1, vertex2, weight) {
this.adjacencyList[vertex1].push({ node: vertex2, weight });
this.adjacencyList[vertex2].push({ node: vertex1, weight });
}
Dijkstra(start, finish) {
const nodes = new PriorityQueue();
const distances = {};
const previous = {};
let path = []; //to return at end
let smallest;
for (let vertex in this.adjacencyList) {
if (vertex === start) {
distances[vertex] = 0;
nodes.enqueue(vertex, 0);
} else {
distances[vertex] = Infinity;
nodes.enqueue(vertex, Infinity);
}
previous[vertex] = null;
}
while (nodes.values.length) {
smallest = nodes.dequeue().val;
if (smallest === finish) {
while (previous[smallest]) {
path.push(smallest);
smallest = previous[smallest];
}
break;
}
if (smallest || distances[smallest] !== Infinity) {
for (let neighbor in this.adjacencyList[smallest]) {
// 근처 노드 찾기
let nextNode = this.adjacencyList[smallest][neighbor];
// 거리 계산하기
let candidate = distances[smallest] + nextNode.weight;
let nextNeighbor = nextNode.node;
if (candidate < distances[nextNeighbor]) {
// 거리 설정
distances[nextNeighbor] = candidate;
// 전에 방문했던 정점 설정
previous[nextNeighbor] = smallest;
// 우선순위큐에 집어넣기
nodes.enqueue(nextNeighbor, candidate);
}
}
}
}
return path.concat(smallest).reverse();
}
}
4. 우선순위큐 리팩터링
우선순위큐를 이진힙으로 바꾼다면 더 빠르게 작동시킬 수 있다.
class PriorityQueue {
constructor() {
this.values = [];
}
enqueue(val, priority) {
let newNode = new Node(val, priority);
this.values.push(newNode);
this.bubbleUp();
}
bubbleUp() {
let idx = this.values.length - 1;
const element = this.values[idx];
while (idx > 0) {
let parentIdx = Math.floor((idx - 1) / 2);
let parent = this.values[parentIdx];
if (element.priority >= parent.priority) break;
this.values[parentIdx] = element;
this.values[idx] = parent;
idx = parentIdx;
}
}
dequeue() {
const min = this.values[0];
const end = this.values.pop();
if (this.values.length > 0) {
this.values[0] = end;
this.sinkDown();
}
return min;
}
sinkDown() {
let idx = 0;
const length = this.values.length;
const element = this.values[0];
while (true) {
let leftChildIdx = 2 * idx + 1;
let rightChildIdx = 2 * idx + 2;
let leftChild, rightChild;
let swap = null;
if (leftChildIdx < length) {
leftChild = this.values[leftChildIdx];
if (leftChild.priority < element.priority) {
swap = leftChildIdx;
}
}
if (rightChildIdx < length) {
rightChild = this.values[rightChildIdx];
if (
(swap === null && rightChild.priority < element.priority) ||
(swap !== null && rightChild.priority < leftChild.priority)
) {
swap = rightChildIdx;
}
}
if (swap === null) break;
this.values[idx] = this.values[swap];
this.values[swap] = element;
idx = swap;
}
}
}
class Node {
constructor(val, priority) {
this.val = val;
this.priority = priority;
}
}
728x90
'개발 > 자료구조' 카테고리의 다른 글
[알고리즘] 동적 프로그래밍 (0) | 2022.12.12 |
---|---|
[자료구조] 그래프 (1) | 2022.12.08 |
[자료구조] 해시테이블 (0) | 2022.12.06 |
[자료구조] 우선순위큐 (0) | 2022.12.06 |
[자료구조] 이진힙 - BinaryHeap (0) | 2022.12.02 |