[Java] 5. Stack과 Queue

김정란·2025년 5월 30일

Java

목록 보기
5/7

📋 목차

  1. Stack과 Queue 개념 정의
  2. Stack 상세 설명
  3. Queue 상세 설명
  4. 실제 구현 예제
  5. 주의사항 및 팁
  6. 마무리

1. Stack과 Queue 개념 정의

StackQueue는 Java에서 가장 기본적이면서도 중요한 선형 자료구조임. 둘 다 데이터를 순서대로 저장하지만, 데이터를 꺼내는 방식이 완전히 다름.

Stack의 핵심

  • LIFO(Last In First Out): 마지막에 들어간 것이 먼저 나옴
  • 실생활 예시: 접시 쌓기, 책 더미, 되돌리기(Undo) 기능

Queue의 핵심

  • FIFO(First In First Out): 먼저 들어간 것이 먼저 나옴
  • 실생활 예시: 대기줄, 프린터 대기열, 은행 번호표

2. Stack 상세 설명

Stack의 동작 원리

    ┌─────────┐
    │    3    │ ← push/pop 지점 (Top)
    ├─────────┤
    │    2    │
    ├─────────┤
    │    1    │ ← 바닥 (Bottom)
    └─────────┘

주요 메소드

  • push(): 스택 위에 데이터 추가
  • pop(): 스택 위에서 데이터 제거하고 반환
  • peek(): 스택 위의 데이터 확인 (제거하지 않음)
  • empty(): 스택이 비어있는지 확인

Stack 예제 코드

import java.util.Stack;

public class StackExample {
    public static void main(String[] args) {
        // Stack 생성
        Stack<Integer> stack = new Stack<>();
        
        // 데이터 추가 (push)
        stack.push(1);  // 바닥에 1 추가
        stack.push(2);  // 1 위에 2 추가  
        stack.push(3);  // 2 위에 3 추가
        
        System.out.println("현재 스택: " + stack); // [1, 2, 3]
        
        // 맨 위 데이터 확인 (peek)
        System.out.println("맨 위 데이터: " + stack.peek()); // 3
        
        // 데이터 제거 (pop) - LIFO 순서
        System.out.println("제거된 데이터: " + stack.pop()); // 3
        System.out.println("제거된 데이터: " + stack.pop()); // 2
        System.out.println("제거된 데이터: " + stack.pop()); // 1
        
        // 빈 스택 확인
        System.out.println("스택이 비어있음: " + stack.empty()); // true
    }
}

3. Queue 상세 설명

Queue의 동작 원리

    First                    Last
      ↓                       ↓
    ┌─────┬─────┬─────┬─────┬─────┐
    │  1  │  2  │  3  │     │     │
    └─────┴─────┴─────┴─────┴─────┘
      ↑                       ↑
   poll(제거)            offer(추가)
   
   ← 먼저 나감           나중에 들어감 →

주요 메소드

  • offer(): 큐 뒤쪽에 데이터 추가
  • poll(): 큐 앞쪽에서 데이터 제거하고 반환
  • peek(): 큐 앞쪽 데이터 확인 (제거하지 않음)
  • isEmpty(): 큐가 비어있는지 확인

Queue 예제 코드

import java.util.LinkedList;
import java.util.Queue;

public class QueueExample {
    public static void main(String[] args) {
        // Queue 생성 (LinkedList로 구현)
        Queue<Integer> queue = new LinkedList<>();
        
        // 데이터 추가 (offer)
        queue.offer(1);  // 1이 첫 번째
        queue.offer(2);  // 2가 두 번째
        queue.offer(3);  // 3이 세 번째
        
        System.out.println("현재 큐: " + queue); // [1, 2, 3]
        
        // 맨 앞 데이터 확인 (peek)
        System.out.println("맨 앞 데이터: " + queue.peek()); // 1
        
        // 데이터 제거 (poll) - FIFO 순서
        System.out.println("제거된 데이터: " + queue.poll()); // 1
        System.out.println("제거된 데이터: " + queue.poll()); // 2
        System.out.println("제거된 데이터: " + queue.poll()); // 3
        
        // 빈 큐 확인
        System.out.println("큐가 비어있음: " + queue.isEmpty()); // true
    }
}

4. 실제 구현 예제

실생활 응용: 웹 브라우저 뒤로가기 기능 (Stack)

import java.util.Stack;

class WebBrowser {
    private Stack<String> history = new Stack<>();
    
    // 새 페이지 방문
    public void visitPage(String url) {
        history.push(url);
        System.out.println("방문: " + url);
    }
    
    // 뒤로가기
    public void goBack() {
        if (!history.empty()) {
            String currentPage = history.pop();
            System.out.println("뒤로가기: " + currentPage + "에서 나감");
            
            if (!history.empty()) {
                System.out.println("현재 페이지: " + history.peek());
            } else {
                System.out.println("더 이상 뒤로 갈 페이지가 없음");
            }
        }
    }
}

// 사용 예시
public class BrowserExample {
    public static void main(String[] args) {
        WebBrowser browser = new WebBrowser();
        
        browser.visitPage("google.com");
        browser.visitPage("naver.com");
        browser.visitPage("github.com");
        
        browser.goBack(); // github.com에서 나감, 현재: naver.com
        browser.goBack(); // naver.com에서 나감, 현재: google.com
    }
}

실생활 응용: 프린터 대기열 (Queue)

import java.util.LinkedList;
import java.util.Queue;

class PrintQueue {
    private Queue<String> printJobs = new LinkedList<>();
    
    // 인쇄 작업 추가
    public void addPrintJob(String document) {
        printJobs.offer(document);
        System.out.println("인쇄 대기열에 추가: " + document);
    }
    
    // 인쇄 실행
    public void processPrint() {
        if (!printJobs.isEmpty()) {
            String document = printJobs.poll();
            System.out.println("인쇄 중: " + document);
        } else {
            System.out.println("대기 중인 인쇄 작업이 없음");
        }
    }
    
    // 대기열 확인
    public void showQueue() {
        System.out.println("현재 대기열: " + printJobs);
    }
}

// 사용 예시
public class PrinterExample {
    public static void main(String[] args) {
        PrintQueue printer = new PrintQueue();
        
        printer.addPrintJob("이력서.pdf");
        printer.addPrintJob("보고서.docx");
        printer.addPrintJob("사진.jpg");
        
        printer.showQueue(); // [이력서.pdf, 보고서.docx, 사진.jpg]
        
        printer.processPrint(); // 이력서.pdf 인쇄
        printer.processPrint(); // 보고서.docx 인쇄
        
        printer.showQueue(); // [사진.jpg]
    }
}

5. 주의사항 및 팁

Stack 사용 시 주의사항

  1. EmptyStackException 주의: pop()이나 peek() 호출 전 반드시 empty() 확인
  2. 메모리 관리: 스택이 계속 커지면 StackOverflow 발생 가능
  3. Vector 기반: Stack은 Vector를 상속받아 성능상 불리할 수 있음
// 안전한 pop 사용법
if (!stack.empty()) {
    int value = stack.pop();
    // 사용...
} else {
    System.out.println("스택이 비어있음");
}

Queue 사용 시 주의사항

  1. null 반환 주의: poll()은 빈 큐에서 null 반환 (예외 발생 안 함)
  2. 구현체 선택: LinkedList, ArrayDeque 등 상황에 맞는 구현체 선택
  3. Deque 권장: 현재는 Deque 인터페이스 사용이 더 권장됨
// 안전한 poll 사용법
Integer value = queue.poll();
if (value != null) {
    // 사용...
} else {
    System.out.println("큐가 비어있음");
}

성능 비교 팁

  • ArrayDeque: 양쪽 끝 작업이 빈번할 때 가장 효율적
  • LinkedList: 중간 삽입/삭제가 많을 때 유리
  • Stack 대신 Deque: Deque<Integer> stack = new ArrayDeque<>()

6. 마무리

Stack과 Queue는 단순해 보이지만 프로그래밍에서 매우 중요한 자료구조임.

Stack은 함수 호출, 수식 계산, 되돌리기 기능 등에 활용되고, Queue는 작업 스케줄링, BFS 알고리즘, 캐시 구현 등에 필수적임.

두 자료구조의 핵심은 데이터 접근 순서를 이해하는 것임.

실제 개발에서는 Java Collections Framework의 구현체들을 적절히 선택해서 사용하되, 각각의 특성과 성능을 고려해서 결정하는 것이 중요함.

0개의 댓글