• 스택(Stack)과 큐(Queue) 개념 및 Java 코드 구현

    2021. 4. 17.

    by. SDev

    728x90

    본 포스팅은 jisikTank 스터디에 참여하며 정리한 문서입니다.
    jisikTank CS지식 Git Repository


    스택과 큐(Stack & Queue)

    스택(Stack)

    • 입력과 출력이 한 곳(방향)으로 제한
    • LIFO(Last In First Out, 후입선출): 가장 나중에 들어온 것이 가장 먼저 나옴

    언제 사용할까?

    • 함수의 콜스택, 문자열 역순 출력, 연산자 후위표기법 등

    Stack의 특징

    • 자주 사용하는 메소드로 push, pop, isEmpty, isFull 이 있다.
    • push, pop 과정에 다음 값이 들어갈 최상단 위치를 기억하는 스택 포인터(SP)가 필요(처음 기본값 -1)
    • 기본적으로 크기가 정적으로 구성되지만 연결리스트, 동적 배열을 활용해 최대 크기가 존재하지 않도록 구현할 수 있다.
    • 시간복잡도 삽입 O(1), 삭제 O(1), 탐색 O(n)

    java 코드로 스택 살펴보기

    public class BasicStack {
    static int MAX_SIZE = 1000;
    static Object stack[];
    class Stack{
    private int sp = -1;
    public void push(Object o) {
    if(isFull(o)) {
    return;
    }
    stack[++sp] = o;
    }
    public void pushDynamicArrayStack(Object o) {
    if(isFull(sp)) {
    Object[] arr = new Object[MAX_SIZE * 2];
    System.arraycopy(stack, 0, arr, 0, MAX_SIZE);
    stack = arr;
    MAX_SIZE *= 2; // 2배로 증가
    }
    stack[sp++] = o;
    }
    public Object pop() {
    if(isEmpty(sp)) {
    return null;
    }
    Object o = stack[sp--];
    return o;
    }
    private boolean isFull(Object o) {
    return sp + 1 == MAX_SIZE ? true : false;
    }
    private boolean isEmpty(int cnt) {
    return sp == -1 ? true : false;
    }
    }
    public static void main(String args[]){
    }
    }




    동적 크기 스택(Array형태로 구현)

    public class DynamicArrayStack {
    static int MAX_SIZE = 1000;
    static Object stack[];
    class Stack{
    private int sp = -1;
    // 일반 스택과 push method만 차이가 있음
    public void push(Object o) {
    if(isFull(sp)) {
    Object[] arr = new Object[MAX_SIZE * 2];
    System.arraycopy(stack, 0, arr, 0, MAX_SIZE);
    stack = arr;
    MAX_SIZE *= 2; // 2배로 증가
    }
    stack[sp++] = o;
    }
    public Object pop() {
    if(isEmpty(sp)) {
    return null;
    }
    Object o = stack[sp--];
    return o;
    }
    private boolean isFull(Object o) {
    return sp + 1 == MAX_SIZE ? true : false;
    }
    private boolean isEmpty(int cnt) {
    return sp == -1 ? true : false;
    }
    }
    }




    동적 크기 스택(LinkedList로 구현)

    public class DynamicLinkedListStack {
    public class Node {
    public int data;
    public Node next;
    public Node() {
    }
    public Node(int data) {
    this.data = data;
    this.next = null;
    }
    }
    public class Stack {
    private Node head;
    private Node top;
    public Stack() {
    head = top = null;
    }
    private Node createNode(int data) {
    return new Node(data);
    }
    private boolean isEmpty() {
    return top == null ? true : false;
    }
    public void push(int data) {
    if (isEmpty()) { // 스택이 비어있다면
    head = createNode(data);
    top = head;
    }
    else { //스택이 비어있지 않다면 마지막 위치를 찾아 새 노드를 연결시킨다.
    Node pointer = head;
    while (pointer.next != null)
    pointer = pointer.next;
    pointer.next = createNode(data);
    top = pointer.next;
    }
    }
    public int pop() {
    int popData;
    if (!isEmpty()) { // 스택이 비어있지 않다면!! => 데이터가 있다면!!
    popData = top.data; // pop될 데이터를 미리 받아놓는다.
    Node pointer = head; // 현재 위치를 확인할 임시 노드 포인터
    if (head == top) // 데이터가 하나라면
    head = top = null;
    else { // 데이터가 2개 이상이라면
    while (pointer.next != top) // top을 가리키는 노드를 찾는다.
    pointer = pointer.next;
    pointer.next = null; // 마지막 노드의 연결을 끊는다.
    top = pointer; // top을 이동시킨다.
    }
    return popData;
    }
    return -1; // -1은 데이터가 없다는 의미로 지정해둠.
    }
    }
    public static void main(String[] args) {
    }
    }


    큐(Queue)

    • 입력과 출력을 한 쪽 끝(front, rear)로 제한
    • FIFO(First In First Out, 선입선출): 가장 먼저 들어온 것이 가장 먼저 나옴

    언제 사용할까?

    • 버퍼, 마구 입력된 것을 처리하지 못하고 있는 상황, BFS

    Queue의 특징

    • 큐의 가장 첫 원소를 front, 끝 원소를 rear라고 부름

    • 접근은 가장 첫 원소와 끝 원소로만 가능

    • 자주 사용하는 메소드로 enQueue, deQueue, isEmpty, isFull이 있음

    • 시간복잡도 삽입 O(1), 삭제 O(1), 탐색 O(n)

    • 일반 큐(선형)는 빈 메모리가 남아 있어도, 꽉 차있는 것으로 판단할 수 있음(rear가 끝에 도달했을 때) -> 원형 큐


    원형 큐

    • 논리적으로 배열의 처음과 끝이 연결되어 있는 것으로 간주함
    • 초기 공백 상태일 때 front와 rear가 0
    • 공백, 포화 상태를 쉽게 구분하기 위해 자리 하나를 항상 비워둠

    (index + 1) % size로 순환시킨다


    java 코드로 큐 알아보기




    일반 정적 크기 큐 코드

    public class BasicQueue {
    class Queue{
    private int size = 0;
    private int rear = -1;
    private int front = -1;
    private Object queue[];
    Queue(int size) {
    this.size = size;
    this.queue = new Object[size];
    }
    public boolean isEmpty() {
    return front == rear;
    }
    public boolean isFull() {
    return (rear == size-1);
    }
    public void enQueue(Object o) {
    if(isFull()) {
    return;
    }
    queue[++rear] = o;
    }
    public Object deQueue() {
    if(isEmpty()) {
    return null;
    }
    Object o = queue[front];
    queue[front++] = null;
    return o;
    }
    }
    }


    java 원형 큐 코드

    public class Circular {
    public class Circular_Queue {
    int rear = 0; //최초 0에서부터 시작
    int front = 0; //최초 0에서부터 시작
    int maxsize = 0; //배열의 크기
    int[] circular_Queue; //배열
    public Circular_Queue(int maxsize)
    {
    this.maxsize = maxsize;
    circular_Queue = new int[this.maxsize];
    }
    public boolean Isempty() //배열이 공백 상태인지 체크하는 메서드입니다.
    {
    if(rear == front)
    {
    return true;
    }
    return false;
    }
    public boolean Isfull() //배열이 포화 상태인지 체크하는 메서드입니다.
    {
    if((rear+1)%maxsize == front)
    {
    return true;
    }
    return false;
    }
    public void EnQueue(int num)
    {
    if(Isfull()) //배열이 포화상태일경우
    {
    System.out.println("큐가 가득 찼습니다");
    }
    else //배열이 포화상태가 아닐경우
    {
    rear = (rear+1) % maxsize;
    circular_Queue[rear]=num;
    }
    }
    public int DeQueue()
    {
    if(Isempty()) //배열이 공백상태이면 -1반환
    {
    return -1;
    }
    else //배열이 공백상태가 아니라면
    {
    front = (front+1)%maxsize;
    return circular_Queue[front];
    }
    }
    }
    public static void main(String[] args) {
    }
    }

    Quiz

    • 기본적인 스택과 큐를 구현해보세요.
    • Stack과 Queue의 차이점은 무엇인가요?(N사 전화면접)
      https://devowen.com/285
















    참고 자료



    Quiz 모범 답안

    https://devowen.com/285

    cs9

    댓글