알고리즘, CS
알고리즘 특강 - 3. 스택, 큐
차돌박이츄베릅
2023. 6. 7. 12:01
스택
LIFO(Last In First Out) 성격을 가짐
StackOverflow: 반복문에서 종료 조건을 지정하지 않거나 잘못된 종료조건을 지정하여 무한 루프가 발생하면 메모리의 스택영역이 쌓이고 쌓이다 터짐
역순의 성질을 사용해야 될 때 유용함
모바일 앱을 사용하면 뒤로 가기 버튼을 꽤 많이 누르게 되는데 이때 활용하는 자료구조가 스택. 뒤로 가기 버튼을 누르면 직전에 호출했던 스크린을 호출해야되는 특성때문.
Undo/Redo와 같은 기능도 스택을 이용.
- 픽(peek): 스택의 Top(맨 위) 데이터를 보는 것
- 푸시: 스택에 원소를 삽입하는 행위! 원소는 Top에 들어감
- 팝: 스택의 Top에서 원소를 가져오는 행위! 방금 위에서 넣었던 푸시된 원소가 나오게 됨
[링크드리스트 기반 구현 예제]
class Node {
constructor(value) {
this.value = value;
this.next = null;
}
}
class Stack {
constructor() {
this.head = null;
}
peek() {
if (this.head === null) {
return null;
}
return this.head.value;
}
push(value) { // 현재 [4] 밖에 없다면
let newNode = new Node(value); // [3] 을 만들고!
newNode.next = this.head; // [3] -> [4] 로 만든다음에
this.head = newNode; // [3] -> [4] 로 만든다음에
}
pop() {
if (this.head === null) { // 스택이 비어있으면
return null; // 여기서도 메시지를 리턴하지말고 null 리턴!
}
let deleteHead = this.head; // 제거할 node 를 변수에 잡습니다.
this.head = this.head.next; // 그리고 head 를 현재 head 의 다음 걸로 잡으면 됩니다.
return deleteHead.value; // 그리고 제거할 node 반환
}
}
let stack = new Stack();
console.log(stack.peek()); // null, 스택이 비어 있음
stack.push(1);
console.log(stack.peek()); // 1
stack.push(2);
console.log(stack.peek()); // 2, 스택의 top이 2로 변경됨
console.log(stack.pop()); // 2, pop()으로 인해 2를 제거하고 반환
console.log(stack.peek()); // 1, 스택의 top이 1로 변경됨
console.log(stack.pop()); // 1, pop()으로 인해 1을 제거하고 반환
console.log(stack.peek()); // null, 스택이 비어 있음
console.log(stack.pop()); // null, 스택이 비어 있으므로 null 반환
큐
FIFO(First In First Out)의 성격을 가짐
서버 접속 대기열 큐, 인쇄 대기열 큐 등에서 이용
픽(peek): 큐의 Front(맨 앞) 데이터를 보는 것
enqueue(삽입) : 큐에 원소를 삽입하는 행위! 원소는 Rear(맨 뒤)에 들어감
dequeue (뽑기): 큐에서 원소를 뽑아오는 행위! FIFO 자료구조니 Front에 위치한 원소를 뽑아옴
[링크드리스트 기반 구현 예제]
class Node {
constructor(value) {
this.value = value;
this.next = null;
}
}
class Queue {
constructor() {
this.head = null;
this.tail = null;
}
enqueue(value) {
const newNode = new Node(value);
if (this.head === null) { // 만약 비어있다면,
this.head = newNode; // head(Front)에 new_node를
this.tail = newNode; // tail(Rear)에 new_node를 넣어줍니다!
} else { // 비어있지 않다면 기존 tail에 새 노드를 포인터로 연결하고요!
this.tail.next = newNode;
this.tail = newNode; // 새 노드를 tail로 설정해요!
}
}
dequeue() {
if (this.head === null) {
return null;
}
const deleteHead = this.head; // 제거할 node를 변수에 잡습니다.
this.head = this.head.next; // 그리고 head(Front)를 현재 head의 다음 걸로 잡으면 됩니다.
return deleteHead.value; // 그리고 제거할 node 반환을 해요!
}
}
const queue = new Queue();
queue.enqueue(1);
queue.enqueue(2);
queue.enqueue(3);
console.log(queue.dequeue()); // 1
console.log(queue.dequeue()); // 2
console.log(queue.dequeue()); // 3
console.log(queue.dequeue()); // null