덱 개요
- 양쪽 끝에서 삽입과 삭제가 모두 가능합니다.
- 큐와 스택의 특징을 모두 가지고 있습니다.
덱 동작 원리
- addFirst(el) : 덱의 앞쪽에 데이터를 추가합니다.
- addLast(el) : 덱의 뒤쪽에 데이터를 추가합니다.
- removeFirst() : 덱의 앞쪽 데이터를 제거 후 반환합니다.
- removeLast() : 덱의 뒤쪽 데이터를 제거 후 반환합니다.
- peekFirst() : 덱의 앞쪽 데이터를 반환합니다.
- peekLast() : 덱의 뒤쪽 데이터를 반환합니다.
- isEmpty() : 덱이 비어있는지 확인합니다.
덱 배열 코드 예시
class Deque {
constructor() {
this.deque = []
}
isEmpty() {
return this.deque.length === 0
}
addFirst(el) {
this.deque.unshift(el)
}
addLast(el) {
this.deque.push(el)
}
peekFirst() {
if(this.isEmpty()) throw new Error('empty deque')
return this.deque[0]
}
peekLast() {
if(this.isEmpty()) throw new Error('empty deque')
return this.deque[this.deque.length - 1]
}
removeFirst() {
if(this.isEmpty()) throw new Error('empty deque')
return this.deque.shift()
}
removeLast() {
if(this.isEmpty()) throw new Error('empty deque')
return this.deque.pop()
}
}
위와 같이 배열로 덱 클래스를 작성하면 shift와 unshift일때 시간 복잡도가 O(n)이 됩니다.
이중 링크드 리스트로 구성해야 O(1)을 가집니다.
덱 이중 링크드 리스트 코드 예시
class Node {
constructor(el) {
this.item = el
this.next = null
this.prev = null
}
}
class Deque {
toggleDirection = {
'next': 'prev',
'prev': 'next
}
toggleDeque = {
'front': 'rear',
'rear': 'front'
}
constructor() {
this.front = null
this.rear = null
this.size = 0
}
isEmpty() {
return this.size === 0
}
addItem(el, deque, direction) {
const node = new Node(el)
if(this.isEmpty()) this.front = this.rear = node
else {
node[direction] = this[deque]
this[deque][this.toggleDirection[direction]] = node
this[deque] = node
}
this.size++
}
addFirst(el) {
this.addItem(el, 'front', 'next')
}
addLast(el) {
this.addItem(el, 'rear', 'prev')
}
peekFirst() {
if(this.isEmpty()) throw new Error('empty deque')
return this.front.item
}
peekLast() {
if(this.isEmpty()) throw new Error('empty deque')
return this.rear.item
}
removeItem(deque, direction) {
const item = deque === 'front' ? this.peekFirst() : this.peekLast()
this[deque] = this[deque][direction]
if(this[deque]) this[deque][this.toggleDirection[direction]] = null
else this[this.toggleDeque[deque]] = null
this.length--
return item
}
removeFirst() {
return this.removeItem('front', 'next')
}
removeLast() {
return this.removeItem('rear', 'prev')
}
}
덱 시간 복잡도
- 덱의 모든 연산은 시간 복잡도가 O(1)입니다.
- 배열로 코드를 구성하였을 경우 front관련 연산은 O(n)입니다.
덱 장점
- 양쪽 끝에서 삽입, 삭제 연산이 모두 가능합니다.
덱 단점
- 큐나 스택보다 구현이 복잡합니다.
- 데이터 중간 삽입, 삭제 연산이 힘듭니다.
덱 활용
- 동일한 단어가 되는지 회문(팰린드롬)을 체크할 수 있습니다.
'알고리즘 > 자료구조' 카테고리의 다른 글
배열 요소에 접근하는데 O(1)의 시간이 걸리는 이유 (0) | 2024.04.04 |
---|---|
행렬인가 무엇인가? (0) | 2024.04.04 |
배열이란 무엇인가? (0) | 2024.04.04 |
자료구조 알고리즘 - 큐 이해와 효율적인 구현 방법 (0) | 2024.03.20 |
자료구조 알고리즘 - 스택 이해와 효율적인 구현 방법 (0) | 2024.03.20 |