[자바스크립트 자료구조] 힙(Heap) - 힙 정렬 / 힙 시간복잡도
2021. 3. 25. 10:16ㆍFront-end/자료구조
728x90
반응형
힙 정렬
- 지난 시간 까지 힙 클래스를 생성했으니 힙을 사용해서 정렬을 하는 것은 간단함
- 정렬된 배열을 얻기 위해 힙이 빈 상태가 될 때까지 힙에 대해 .pop()을 호출하면서 꺼낸 객체를 저장하기만 하면 된다.
- 삼투(bubbleUp, bubbleDown)가 O(logN)가 걸리고 정렬이 n개의 항목들을 꺼내야 하기 때문에 힙 정렬의 시간 복잡도는 O(NlogN)이다.
- 최소 힙을 이용하면 오름차순 정렬이 가능할 것이고, 최대 힙을 이용하면 내림차순 정렬이 가능할 것이다.
두가지 모두 sort()라는 메소드를 추가하면 된다. (MinHeap 클래스에 추가하면 MaxHeap은 상속받을 것이다)
sort(){
let sort = [];
const count = this.items.length;
for(let i = 0; i < count; i++){
sort.push(this.poll());
}
return sort;
}
요약
🎁 힙은 배열을 사용해 표현한 트리와 같은 자료 구조
- 최솟값, 최댓값을 빨리 찾아내고 이를 이용해 정렬을 하기 쉬움
🎁 힙 노드 인덱스
노드 |
인덱스 |
자기 자신 |
N |
부모 |
(N-1) / 2 이 때 소수점은 버리므로 |
왼쪽 자식 |
(N*2) + 1 |
오른쪽 자식 |
(N*2) + 2 |
🎁 힙은 삼투를 통해 자신의 구조를 유지
- bubbleUp : 노드가 삽입됐을 때 힙의 구조가 올바르게 될 때까지 항목들을 반복적으로 교환하면서 노드를 위로 이동시킴
- bubbleDown : 노드를 삭제할 때 루트 노드를 삭제하고 맨 마지막에 삽입했던 노드를 위로 올린 후 힙의 구조가 올바르게 될 때까지 항목들을 반복적으로 교환하면서 노드가 아래로 내려감
🎁 힙 연산 시간 복잡도
연산 |
시간 복잡도 |
삭제(아래로 이동) |
O(logN) |
삽입(위로 이동) |
O(logN) |
힙 정렬 |
O(NlogN) |
전체 코드
class Heap{
constructor(){
this.items = [];
}
//값을 서로 바꾸는 메소드
swap(index1, index2){
let temp = this.items[index1]; // items의 index1의 값을 temp(임시공간)에 담음
this.items[index1] = this.items[index2]; // index1에 index2의 값을 저장
this.items[index2] = temp; // index2에 아까 index1의 값을 temp에 넣어놓은 값을 저장
}
//부모 인덱스 구하는 메소드
parentIndex(index){
return Math.floor((index-1) / 2);
}
//왼쪽 자식 인덱스 구하는 메소드
leftChildIndex(index){
return index * 2 + 1;
}
//오른쪽 자식 인덱스 구하는 메소드
rightChildIndex(index){
return index * 2 + 2;
}
//부모 노드 구하는 메소드
parent(index){
return this.items[this.parentIndex(index)];
}
//왼쪽 자식 노드 구하는 메소드
leftChild(index){
return this.items[this.leftChildIndex(index)];
}
//오른쪽 자식 노드 구하는 메소드
rightChild(index){
return this.items[this.rightChildIndex(index)];
}
//최대 힙의 경우 최댓값을 반환하고 최소 힙의 경우 최솟값을 반환하는 메소드
peek(){
return this.items[0];
}
//힙의 크기(항목 개수)를 반환하는 메소드
size(){
return this.items.length;
}
}
class MinHeap extends Heap{
// MinHeap 클래스는 Heap 클래스를 상속받았으므로 Heap 클래스의 메소드를 모두 사용할 수 있다.
bubbleUp(){
let index = this.items.length-1;
while(this.parent(index) !== undefined && this.parent(index) > this.items[index]){
this.swap(index, this.parentIndex(index));
index = this.parentIndex(index);
}
}
bubbleDown(){
let index = 0;
while(this.leftChild(index) !== undefined && (this.leftChild(index) < this.items[index] || this.rightChild(index) < this.items[index]){
let smallerIndex = this.leftChildIndex(index);
if(this.rightChild(index) !== undefined && this.rightChild(index) < this.items[smallerIndex]){
smallerIndex = this.rightChildIndex(index);
}
this.swap(index, smallerIndex);
index = smallerIndex;
}
}
// 힙에 원소를 추가하는 함수
add(item){
this.items[this.items.length] = item;
this.bubbleUp();
}
// 힙에서 원소를 빼내는 함수
// 최소 힙이라면 최솟값이 빠져나올 것이고 최대힙이라면 최댓값이 빠져나온다.
poll(){
let item = this.items[0]; // 첫번째 원소 keep
this.items[0] = this.items[this.items.length - 1]; // 맨 마지막 원소를 첫번째 원소로 복사
this.items.pop(); // 맨 마지막 원소 삭제
this.bubbleDown();
return item; // keep해둔 값 반환
}
sort(){
let sort = [];
const count = this.items.length;
for(let i = 0; i < count; i++){
sort.push(this.poll());
}
return sort;
}
}
class MaxHeap extends MinHeap{
//MaxHeap의 경우 MinHeap을 상속받았으므로 MinHeap의 모든 함수를 사용할 수 있지만 bubbleUp과 bubbleDown은 Overriding(재정의)하였다.
bubbleUp(){
let index = this.items.length - 1;
while(this.parent(index) !== undefined && this.parent(index) < this.items[index]){
this.swap(index, this.parentIndex(index));
index = this.parentIndex(index);
}
}
bubbleDown(){
let index = 0;
while(this.leftChild(index) !== undefined && (this.leftChild(index) > this.items[index] || this.rightChild(index) > this.items[index]){
let largerIndex = this.leftChildIndex(index);
if(this.rightChild(index) !== undefined && this.rightChild(index) > this.items[largerIndex]){
largerIndex = this.rightChildIndex(index);
}
this.swap(largerIndex, index);
index = largerIndex;
}
}
}
//앞서 구현한 heap.js를 사용하는 코드!
//최소 힙을 사용하는 코드
const minheap = new MinHeap();
minheap.add(1);
minheap.add(10);
minheap.add(5);
minheap.add(100);
minheap.add(8);
console.log(minheap.items); //array(5) [1, 8, 5, 100, 10]
console.log(minheap.sort());
// //최대 힙을 사용하는 코드
const maxheap = new MaxHeap();
maxheap.add(1);
maxheap.add(10);
maxheap.add(5);
maxheap.add(100);
maxheap.add(8);
console.log(maxheap.items); //array(5) [100, 10, 5, 1, 8]
console.log(maxheap.sort()); // array(5) [100, 10, 8, 5, 1]
728x90
반응형
'Front-end > 자료구조' 카테고리의 다른 글
[자료구조] 그래프 (자바스크립트/javascript) (0) | 2021.05.18 |
---|---|
[자바스크립트 자료구조] 힙(heap) - 연습문제 (0) | 2021.03.25 |
[자바스크립트 자료구조] 힙(Heap) - (1) 최소힙, 최대힙 구현 (0) | 2021.03.24 |
[자료구조] 이진탐색트리 구현 - 삭제 (0) | 2021.03.17 |
[자료구조] 이진탐색트리 구현 - 최솟값, 최댓값 찾기 / 특정 값 찾기 (0) | 2021.03.17 |