스택 스택 활용 큐 활용 JS로 구현 📝 문제풀이
◀ 이전 📋 목차 CH 04 ▶
🥞 CHAPTER 03 · 자료구조

넣고 빼는 순서가 정해진 두 그릇, 스택과 큐

데이터를 어떤 순서로 꺼낼지만 다를 뿐인데, 쓰임새가 완전히 갈려요. 맨 위에서만 꺼내는 스택(LIFO)줄 선 순서대로 꺼내는 큐(FIFO), 이 둘의 감을 확실히 잡아봐요.

🎯 이 장을 끝내면
🥞
스택
스택 = 맨 위에서만 넣고 빼는 그릇 (LIFO)
접시 쌓기를 떠올리면 한 번에 이해돼요.

스택(Stack)LIFO(Last In First Out, 후입선출) 방식이에요. 마지막에 넣은 것이 가장 먼저 나와요. 접시를 쌓을 때처럼, 맨 위에서만 새로 올리고(push) 맨 위 것부터 내려요(pop).

🔤
LIFO(Last In First Out) — "나중에 넣은 게 먼저 나온다"는 뜻이에요. 접시를 쌓아 올렸다가 위에서부터 하나씩 집어 드는 모습을 떠올리면 쉬워요. 스택(Stack)이 바로 이 방식으로 동작하는 자료구조예요.
🍽️ 접시 쌓기로 그려보면 접시를 쌓으면 맨 위 접시부터 집게 되죠. 아래 접시를 빼려면 위에 쌓인 걸 먼저 치워야 해요. 스택도 똑같이 가장 나중에 넣은 것부터 나와요.

  push(3)      pop() → 3
   ┌───┐        ┌───┐
   │ 3 │ ←맨위   │   │
   ├───┤        ├───┤
   │ 2 │        │ 2 │ ←이제 맨위
   ├───┤        ├───┤
   │ 1 │        │ 1 │
   └───┘        └───┘
💡 넣고 빼는 곳이 한 곳(맨 위)뿐이라는 게 핵심이에요. 그래서 마지막에 넣은 게 제일 먼저 나오는 거예요.
연산하는 일복잡도
push(x)맨 위에 x를 올린다O(1)
pop()맨 위 것을 꺼내 없앤다 (그 값을 반환)O(1)
peek()맨 위 것을 보기만 한다 (빼지 않음)O(1)
스택 LIFO push pop peek 후입선출
↩️
스택 활용
"되돌리기"가 필요한 곳엔 스택이 있어요
최근 것부터 처리해야 하는 문제라면 스택이 딱이에요.

스택은 "가장 최근 것부터 되짚어야 하는" 상황에서 힘을 발휘해요. 대표적인 쓰임새를 볼게요.

활용왜 스택인가
괄호 짝 검사여는 괄호를 push하고, 닫는 괄호가 오면 pop해서 짝이 맞는지 확인
실행 취소(undo)가장 최근 작업부터 되돌려야 하므로 마지막에 쌓인 것부터 꺼냄
함수 호출 스택가장 나중에 호출된 함수가 먼저 끝나고 반환됨 (call stack)
브라우저 뒤로가기방문한 페이지를 쌓아두고, 뒤로가기 시 가장 최근 페이지부터 되돌아감
🧱 JS 배열로 push / pop
const stack = [];
stack.push(1);   // [1]
stack.push(2);   // [1, 2]
stack.push(3);   // [1, 2, 3]

const top = stack.pop();  // 3 을 꺼냄 → stack은 [1, 2]
console.log(top);         // 3  (마지막에 넣은 것!)
console.log(stack[stack.length - 1]); // 2  ← peek (보기만)
💡 pop()맨 뒤(=맨 위) 요소를 꺼내 없애고 그 값을 돌려줘요. 위 코드에서 마지막에 넣은 3이 가장 먼저 나오죠.
🚶
큐 = 줄 선 순서대로 꺼내는 그릇 (FIFO)
매표소 줄서기를 떠올리면 바로 감이 와요.

큐(Queue)FIFO(First In First Out, 선입선출) 방식이에요. 먼저 넣은 것이 먼저 나와요. 줄서기처럼 뒤로 들어와서(enqueue) 앞에서 빠져나가요(dequeue).

🔤
FIFO(First In First Out) — "먼저 넣은 게 먼저 나온다"는 뜻이에요. 매표소나 은행 창구에서 먼저 줄 선 사람이 먼저 처리되는 모습을 떠올리면 쉬워요. 큐(Queue)가 바로 이 방식으로 동작해요. 앞서 배운 스택의 LIFO와 정반대라고 기억하면 돼요.
🔤
enqueue / dequeue — 큐에 넣고 빼는 동작의 이름이에요. enqueue는 줄의 맨 뒤에 새로 세우는 것(넣기), dequeue는 줄의 맨 앞 사람을 내보내는 것(빼기)이에요. 스택의 push/pop에 해당하는 큐 버전이라고 보면 돼요.
🎟️ 매표소 줄서기로 그려보면 먼저 줄 선 사람이 먼저 표를 사고 나가죠. 새로 온 사람은 맨 뒤에 서요. 큐도 똑같이 가장 먼저 넣은 것부터 나와요.

  enqueue →  [ 1 ][ 2 ][ 3 ]  → dequeue
   (뒤로 넣음)              (앞에서 뺌)

  dequeue() → 1  (가장 먼저 들어온 것!)
  남은 큐:      [ 2 ][ 3 ]
💡 스택은 넣고 빼는 곳이 같은 쪽, 큐는 넣는 곳(뒤)과 빼는 곳(앞)이 반대쪽이에요. 그래서 순서가 그대로 유지돼요.
연산하는 일
enqueue(x)뒤에 x를 넣는다
dequeue()앞에서 하나 꺼낸다 (가장 먼저 들어온 것)
FIFO enqueue dequeue 선입선출
📬
큐 활용
"들어온 순서대로 처리"할 땐 큐예요
공정한 순서가 중요할 때 큐가 등장해요.

큐는 "먼저 온 것을 먼저 처리한다"는 공정한 순서가 필요한 곳에 쓰여요.

활용왜 큐인가
작업 대기열프린터·요청 처리 등, 들어온 순서대로 하나씩 처리해야 공정해요
너비 우선 탐색(BFS)가까운 곳부터 먼저 발견한 순서대로 방문하려면 큐가 필수예요
버퍼·스트리밍먼저 도착한 데이터부터 순서대로 소비해요
🧭
BFS와 큐는 세트예요. 미로에서 출발점과 가까운 칸부터 순서대로 살펴볼 때, 발견한 순서대로 큐에 넣고 앞에서부터 꺼내 탐색하면 자연스럽게 "가까운 곳 먼저"가 돼요. 뒤 챕터에서 그래프 탐색 때 다시 만나요.
🧮
JS로 구현
JS 배열 하나로 스택도 큐도 흉내 내요
어느 쪽에서 빼느냐만 다르면 돼요.

JS의 배열은 push·pop·shift를 다 가지고 있어서, 빼는 위치만 바꾸면 스택도 큐도 만들 수 있어요.

🥞 스택 — push / pop (같은 쪽)
const stack = [];
stack.push('a');   // ['a']
stack.push('b');   // ['a', 'b']
stack.pop();       // 'b' 를 꺼냄 (맨 뒤) → LIFO
뒤에 넣고 뒤에서 빼요 → 마지막에 넣은 게 먼저 나옴.
🚶 큐 — push / shift (반대쪽)
const queue = [];
queue.push('a');   // ['a']
queue.push('b');   // ['a', 'b']
queue.shift();     // 'a' 를 꺼냄 (맨 앞) → FIFO
뒤에 넣고 앞에서 빼요 → 먼저 넣은 게 먼저 나옴. 💡 shift()맨 앞 요소를 꺼내요. 다만 앞을 빼면 뒤 요소를 다 당겨야 해서 O(n)이에요. 진짜 대량 처리에선 별도 큐 구조를 쓰지만, 코테 감 잡기엔 배열로 충분해요.
스택 (Stack)큐 (Queue)
순서LIFO · 후입선출FIFO · 선입선출
비유접시 쌓기줄서기
넣기push (맨 위/뒤)enqueue (뒤)
빼기pop (맨 위/뒤)dequeue (앞)
JS 배열push / poppush / shift
대표 쓰임undo·괄호검사·호출스택BFS·대기열·버퍼
🧪
이 과목의 실습 랩에서 지금 배운 스택·큐를 직접 짜고 실행·채점해볼 수 있어요. 상단 🧪 실습 버튼에서 열려요. 넣고 빼는 순서를 손으로 따라가 보면 훨씬 오래 남아요.
🧠 이 장 핵심 요약
📝
문제풀이 · 점검
배운 걸 가볍게 점검해봐요
시험이 아니라 "내가 이해했나" 확인용이에요. 틀려도 바로 해설이 나와요.
🧪
문제를 풀면 즉시 정답과 해설이 나오고, 위쪽 바에 점수가 쌓여요. 손으로 직접 짜보고 싶으면 상단 🧪 실습 랩으로!
CH 04 🔗 연결 리스트 — 노드를 이어 붙이는 자료구조, 배열과 뭐가 다를까