본문 바로가기
공부기록/알고리즘

Chapter 04-1. 스택과 큐_스택이란

by 루팽 2024. 8. 4.

스택(stack)

데이터를 일시적으로 쌓아 놓는 자료구조

데이터 입력과 출력 순서는 후입선출(LIFO, Last In First Out)로, 가장 나중에 넣은 데이터를 가장 먼저 꺼냄

데이터 넣는 작업 푸시(push), 꺼내는 작업 팝(pop)

자바 프로그램에서 메서드를 호출하고 실행할 때 프로그램 내부에서 스택 사용

 

int형 고정 길이 스택

package ch04_1;

// int형 고정 길이 스택
public class IntStack {
    private int[] stk; // 스택용 배열
    private int capacity; // 스택 용량
    private int ptr; // 스택 포인터 - 스택에 쌓여있는 데이터 수

    // 실행 시 예외 - 스택이 비어 있음
    public class EmptyIntStackException extends RuntimeException {
        public EmptyIntStackException() {}
    }

    // 실행 시 예외 - 스택이 가득 참
    public class OverflowStackException extends RuntimeException {
        public OverflowStackException() {}
    }

    // 생성자
    public IntStack(int maxlen) {
        ptr = 0;
        capacity = maxlen;
        try {
            // 스택 본체용 배열 생성
            stk = new int[capacity];
        } catch (OutOfMemoryError e) {
            // 배열을 생성할 수 없음
            capacity = 0;
        }
    }

    // 스택에 x를 푸시
    public int push(int x) throws OverflowStackException {
        // ptr == capacity와 같지만 안정성 향상을 위해 ptr >= capacity 사용
        if(ptr >= capacity) {
            // 스택이 가득 참
            throw new OverflowStackException();
        }
        return stk[ptr++] = x;
    }

    // 스택에서 데이터를 팝(가장 최근 데이터를 꺼냄)
    public int pop() throws EmptyIntStackException {
        if(ptr <= 0) {
            // 스택이 비어 있음
            throw new EmptyIntStackException();
        }
        return stk[--ptr];
    }

    // 스택에서 데이터를 피크(가장 최근 데이터 조회)
    public int peek() throws EmptyIntStackException {
        // ptr == 0 과 같지만 안정성 향상을 위해 ptr <= 0 사용
        if(ptr <= 0) {
            throw new EmptyIntStackException();
        }
        return stk[ptr - 1];
    }

    // 스택을 비움 - 스택포인터로 푸시, 팝 과정이 이루어지기에 배열 요솟값 변경 필요없음
    public void clear() {
        ptr = 0;
    }

    // 스택에서 x를 찾아 인덱스(없으면 -1)를 반환
    public int indexOf(int x) {
        // 가장 최근부터 선형 검색
        for (int i = ptr - 1; i >= 0; i--) {
            if(stk[i] == x) {
                return i; // 검색 성공
            }
        }
        return -1; // 검색 실패
    }

    // 스택의 용량을 반환
    public int getCapacity() {
        return capacity;
    }

    // 스택에 쌓여 있는 데이터 개수를 반환
    public int size() {
        return ptr;
    }

    // 스택이 비어 있는가?
    public boolean isEmpty() {
        return ptr <= 0;
    }

    // 스택이 가득 찼는가?
    public boolean isFull() {
        return ptr >= capacity;
    }

    // 스택 안의 모든 데이터를 바닥 -> 꼭대기(과거->최근) 순서로 출력
    public void dump() {
        if(ptr <= 0) {
            System.out.println("스택이 비어 있습니다.");
        } else {
            for (int i = 0; i < ptr; i++) {
                System.out.print(stk[i] + " ");
            }
            System.out.println();
        }
    }
}

 

int형 고정 길이 스택 사용 예

package ch04_1;

import java.util.Scanner;

// int형 고정 길이 스택 사용 예
public class Ex01_intStackTester {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        IntStack s = new IntStack(64); // 최대 64 푸시할 수 있는 스택

        while (true) {
            System.out.println(); // 메뉴 구분 위한 빈 행
            System.out.printf("현재 데이터 개수: %d / %d\\n", s.size(), s.getCapacity());
            System.out.print("(1) 푸시  (2) 팝  (3) 피크  (4) 덤프  (0) 종료: ");

            int menu = scanner.nextInt();
            if(menu == 0) break;

            int x;
            switch (menu) {
                case 1: // 푸시
                    System.out.print("데이터: ");
                    x = scanner.nextInt();
                    try {
                        s.push(x);
                    } catch (IntStack.OverflowStackException e) {
                        System.out.println("스택이 가득 찼습니다.");
                    }
                    break;

                case 2: // 팝
                    try {
                        x = s.pop();
                        System.out.println("팝한 데이터는 " + x + "입니다.");
                    } catch (IntStack.EmptyIntStackException e) {
                        System.out.println("스택이 비어 있습니다.");
                    }
                    break;

                case 3: // 피크
                    try {
                        x = s.peek();
                        System.out.println("피크한 데이터는 " + x + "입니다.");
                    } catch (IntStack.EmptyIntStackException e) {
                        System.out.println("스택이 비어 있습니다.");
                    }
                    break;

                case 4: // 덤프
                    s.dump();
                    break;
            }
        }
    }
}

/*
현재 데이터 개수: 0 / 64
(1) 푸시  (2) 팝  (3) 피크  (4) 덤프  (0) 종료: 1
데이터: 1

현재 데이터 개수: 1 / 64
(1) 푸시  (2) 팝  (3) 피크  (4) 덤프  (0) 종료: 1
데이터: 2

현재 데이터 개수: 2 / 64
(1) 푸시  (2) 팝  (3) 피크  (4) 덤프  (0) 종료: 1
데이터: 3

현재 데이터 개수: 3 / 64
(1) 푸시  (2) 팝  (3) 피크  (4) 덤프  (0) 종료: 1
데이터: 4

현재 데이터 개수: 4 / 64
(1) 푸시  (2) 팝  (3) 피크  (4) 덤프  (0) 종료: 3
피크한 데이터는 4입니다.

현재 데이터 개수: 4 / 64
(1) 푸시  (2) 팝  (3) 피크  (4) 덤프  (0) 종료: 4
1 2 3 4 

현재 데이터 개수: 4 / 64
(1) 푸시  (2) 팝  (3) 피크  (4) 덤프  (0) 종료: 2
팝한 데이터는 4입니다.

현재 데이터 개수: 3 / 64
(1) 푸시  (2) 팝  (3) 피크  (4) 덤프  (0) 종료: 2
팝한 데이터는 3입니다.

현재 데이터 개수: 2 / 64
(1) 푸시  (2) 팝  (3) 피크  (4) 덤프  (0) 종료: 4
1 2 

현재 데이터 개수: 2 / 64
(1) 푸시  (2) 팝  (3) 피크  (4) 덤프  (0) 종료: 0
 */

 

int형 고정 길이 스택 사용 예(IntStack 모든 메서드 사용)

package ch04_1;

import java.util.Scanner;

// int형 고정 길이 스택 사용 예(IntStack 모든 메서드 사용)
public class Ex02_intStackTesterEx {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        IntStack s = new IntStack(64); // 최대 64 푸시할 수 있는 스택

        while (true) {
            System.out.println(); // 메뉴 구분 위한 빈 행
            System.out.printf("현재 데이터 개수: %d / %d\\n", s.size(), s.getCapacity());
            System.out.print("(1) 푸시  (2) 팝  (3) 피크  (4) 덤프  (5) 검색  (6) 비움  (7) 출력  (0) 종료: ");

            int menu = scanner.nextInt();
            if(menu == 0) break;

            int x;
            switch (menu) {
                case 1: // 푸시
                    System.out.print("데이터: ");
                    x = scanner.nextInt();
                    try {
                        s.push(x);
                    } catch (IntStack.OverflowStackException e) {
                        System.out.println("스택이 가득 찼습니다.");
                    }
                    break;

                case 2: // 팝
                    try {
                        x = s.pop();
                        System.out.println("팝한 데이터는 " + x + "입니다.");
                    } catch (IntStack.EmptyIntStackException e) {
                        System.out.println("스택이 비어 있습니다.");
                    }
                    break;

                case 3: // 피크
                    try {
                        x = s.peek();
                        System.out.println("피크한 데이터는 " + x + "입니다.");
                    } catch (IntStack.EmptyIntStackException e) {
                        System.out.println("스택이 비어 있습니다.");
                    }
                    break;

                case 4: // 덤프
                    s.dump();
                    break;

                case 5: // 검색
                    System.out.print("검색할 데이터: ");
                    x = scanner.nextInt();
                    int n = s.indexOf(x);
                    if(n >= 0) System.out.println("꼭대기에서 " + (s.size() - n) + "번째에 있습니다.");
                    else System.out.println("그 데이터가 없습니다.");
                    break;

                case 6: // 비우기
                    s.clear();
                    break;

                case 7: // 데이터 출력
                    System.out.println("용량: " + s.getCapacity());
                    System.out.println("데이터수: " + s.size());
                    System.out.println("비어 " + (s.isEmpty() ? "있습니다." : "있지 않습니다."));
                    System.out.println("가득 " + (s.isFull() ? "차 있습니다" : "차 있지 않습니다."));
                    break;
            }
        }
    }
}

/*
현재 데이터 개수: 0 / 64
(1) 푸시  (2) 팝  (3) 피크  (4) 덤프  (5) 검색  (6) 비움  (7) 출력  (0) 종료: 1
데이터: 2

현재 데이터 개수: 1 / 64
(1) 푸시  (2) 팝  (3) 피크  (4) 덤프  (5) 검색  (6) 비움  (7) 출력  (0) 종료: 1
데이터: 4

현재 데이터 개수: 2 / 64
(1) 푸시  (2) 팝  (3) 피크  (4) 덤프  (5) 검색  (6) 비움  (7) 출력  (0) 종료: 1
데이터: 5

현재 데이터 개수: 3 / 64
(1) 푸시  (2) 팝  (3) 피크  (4) 덤프  (5) 검색  (6) 비움  (7) 출력  (0) 종료: 3
피크한 데이터는 5입니다.

현재 데이터 개수: 3 / 64
(1) 푸시  (2) 팝  (3) 피크  (4) 덤프  (5) 검색  (6) 비움  (7) 출력  (0) 종료: 4
2 4 5

현재 데이터 개수: 3 / 64
(1) 푸시  (2) 팝  (3) 피크  (4) 덤프  (5) 검색  (6) 비움  (7) 출력  (0) 종료: 2
팝한 데이터는 5입니다.

현재 데이터 개수: 2 / 64
(1) 푸시  (2) 팝  (3) 피크  (4) 덤프  (5) 검색  (6) 비움  (7) 출력  (0) 종료: 5
검색할 데이터: 2
꼭대기에서 2번째에 있습니다.

현재 데이터 개수: 2 / 64
(1) 푸시  (2) 팝  (3) 피크  (4) 덤프  (5) 검색  (6) 비움  (7) 출력  (0) 종료: 7
용량: 64
데이터수: 2
비어 있지 않습니다.
가득 차 있지 않습니다.

현재 데이터 개수: 2 / 64
(1) 푸시  (2) 팝  (3) 피크  (4) 덤프  (5) 검색  (6) 비움  (7) 출력  (0) 종료: 6

현재 데이터 개수: 0 / 64
(1) 푸시  (2) 팝  (3) 피크  (4) 덤프  (5) 검색  (6) 비움  (7) 출력  (0) 종료: 0
 */

 

제네릭 스택

package ch04_1;

// 제네릭 스택
public class Stack<E> {
    private E[] stk; // 스텍용 베열
    private int capacity; // 스택 용량
    private int ptr; // 스택 포인터

    // 실헬 시 예외: 스택이 비어있음
    public static class EmptyGstackException extends RuntimeException {
        public EmptyGstackException() {
        }
    }

    // 실행 시 예외: 스택이 가득 참
    public static class OverflowGstackException extends RuntimeException {
        public OverflowGstackException() {
        }
    }

    // 생성자
    public Stack(int maxlen) {
        this.ptr = 0;
        this.capacity = maxlen;
        try {
            this.stk = (E[]) new Object[capacity]; // 스택 본체용 배열 생성
        } catch (OutOfMemoryError e) {
            // 생성할 수 없음
            capacity = 0;
        }
    }

    // 스택에 x를 푸시
    public E push(E x) throws OverflowGstackException {
        // 스택이 가득 찼을 경우
        if (ptr >= capacity) throw new OverflowGstackException();
        return stk[ptr++] = x;
    }

    // 스택에서 데이터를 팝(꼭대기 데이터 꺼냄)
    public E pop() throws EmptyGstackException {
        // 스택이 비어있을 경우
        if (ptr <= 0) throw new EmptyGstackException();
        return stk[--ptr];
    }

    // 스택에서 데이터를 피크(꼭대기 데이터 들여다봄)
    public E peak() throws EmptyGstackException {
        // 스택이 비어있을 경우
        if (ptr <= 0) throw new EmptyGstackException();
        return stk[ptr - 1];
    }

    // 스택 비우기
    public void clear() {
        ptr = 0;
    }

    // 스택에서 x를 검색해 인덱스 반환(없으면 -1)
    public int indexOf(E x) {
        // 꼭대기부터 선형검색
        for (int i = ptr - 1; i >= 0; i--) {
            if (stk[i].equals(x)) return i; // 검색 성공
        }
        return -1; // 검색 실패
    }

    // 스택 용량 반환
    public int getCapacity() {
        return capacity;
    }

    // 스택에 쌓여있는 데이터 수 반환
    public int size() {
        return ptr;
    }

    // 스택이 비어 있는가?
    public boolean isEmpty() {
        return ptr <= 0;
    }

    // 스택이 가득 찼는가?
    public boolean isFull() {
        return ptr >= capacity;
    }

    // 스택 안의 모든 데이터를 바닥부터 꼭대기까지 순서대로 출력
    public void dump() {
        if (ptr <= 0) {
            System.out.println("스택이 비어 있습니다.");
        } else {
            for (int i = 0; i < ptr; i++) {
                System.out.print(stk[i] + " ");
            }
            System.out.println();
        }
    }
}

 

제네릭 스택 사용(Gstack 클래스의 모든 메서드 사용)

package ch04_1;

import java.util.Scanner;

// 제네릭 스택 사용(Gstack 클래스의 모든 메서드 사용)
public class Ex03_stackTesterEx {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        Stack<String> s = new Stack<>(64); // 최대 64개 푸시할 수 있는 스택

        while(true) {
            System.out.printf("현재 데이터 개수: %d / %d\\n", s.size(), s.getCapacity());
            System.out.print("(1) 푸시 (2) 팝 (3) 피크 (4) 덤프 (5) 검색 (6) 비움 (7) 출력 (0) 종료 : ");

            int menu = scanner.nextInt();
            if(menu == 0) break;

            String x;

            switch (menu) {
                case 1: // 푸시
                    System.out.print("데이터: ");
                    x = scanner.next();
                    try {
                        s.push(x);
                    } catch (Stack.OverflowGstackException e) {
                        System.out.println("스택이 가득 찼습니다.");
                    }
                    break;

                case 2: // 팝
                    try {
                        x = s.pop();
                        System.out.println("팝한 데이터는 " + x + "입니다.");
                    } catch (Stack.EmptyGstackException e) {
                        System.out.println("스택이 비어 있습니다.");
                    }
                    break;

                case 3: // 피크
                    try {
                        x = s.peak();
                        System.out.println("피크한 데이터는 " + x + "입니다.");
                    } catch (Stack.EmptyGstackException e) {
                        System.out.println("스택이 비어 있습니다.");
                    }
                    break;

                case 4: // 덤프
                    s.dump();
                    break;

                case 5: // 검색
                    System.out.print("검색할 데이터: ");
                    x = scanner.next();
                    int n = s.indexOf(x);
                    if(n >= 0) {
                        System.out.println("꼭대기에서 " + (s.size() - n) + "번째에 있습니다.");
                    } else {
                        System.out.println("해당 데이터가 없습ㄴ디ㅏ.");
                    }
                    break;

                case 6: // 비웁니다
                    s.clear();
                    break;

                case 7: // 데이터 출력
                    System.out.println("용량: " + s.getCapacity());
                    System.out.println("데이터수: " + s.size());
                    System.out.println("비어 " + (s.isEmpty() ? "있습니다." : "있지 않습니다."));
                    System.out.println("가득차 " + (s.isFull() ? "있습니다." : "있지 않습니다."));
                    break;
            }
        }
    }
}
/*
현재 데이터 개수: 0 / 64
(1) 푸시 (2) 팝 (3) 피크 (4) 덤프 (5) 검색 (6) 비움 (7) 출력 (0) 종료 : 1
데이터: 1
현재 데이터 개수: 1 / 64
(1) 푸시 (2) 팝 (3) 피크 (4) 덤프 (5) 검색 (6) 비움 (7) 출력 (0) 종료 : 1
데이터: 3
현재 데이터 개수: 2 / 64
(1) 푸시 (2) 팝 (3) 피크 (4) 덤프 (5) 검색 (6) 비움 (7) 출력 (0) 종료 : 1
데이터: 5

현재 데이터 개수: 3 / 64
(1) 푸시 (2) 팝 (3) 피크 (4) 덤프 (5) 검색 (6) 비움 (7) 출력 (0) 종료 : 2
팝한 데이터는 5입니다.
현재 데이터 개수: 2 / 64
(1) 푸시 (2) 팝 (3) 피크 (4) 덤프 (5) 검색 (6) 비움 (7) 출력 (0) 종료 : 3
피크한 데이터는 3입니다.
현재 데이터 개수: 2 / 64
(1) 푸시 (2) 팝 (3) 피크 (4) 덤프 (5) 검색 (6) 비움 (7) 출력 (0) 종료 : 4
1 3 

현재 데이터 개수: 2 / 64
(1) 푸시 (2) 팝 (3) 피크 (4) 덤프 (5) 검색 (6) 비움 (7) 출력 (0) 종료 : 5
검색할 데이터: 1
꼭대기에서 2번째에 있습니다.
현재 데이터 개수: 2 / 64
(1) 푸시 (2) 팝 (3) 피크 (4) 덤프 (5) 검색 (6) 비움 (7) 출력 (0) 종료 : 6
현재 데이터 개수: 0 / 64
(1) 푸시 (2) 팝 (3) 피크 (4) 덤프 (5) 검색 (6) 비움 (7) 출력 (0) 종료 : 7
용량: 64
데이터수: 0
비어 있습니다.
가득차 있지 않습니다.
현재 데이터 개수: 0 / 64
 */

 

머리가 둘인 int형 고정 길이 스택

package ch04_1;

// 머리가 둘인 int형 고정 길이 스택
public class DoubleHeadIntStack {
    private int[] stk; // 스택 본체
    private int capacity; // 스택 용량(A, B의 합계)
    private int ptrA; // 스택포인터 A
    private int ptrB; // 스택포인터 B

    public enum AorB {StackA, StackB};

    // 실행 시 예외 - 스택이 비어 있음
    public class EmptyDoubleHeadIntStackException extends RuntimeException {
        public EmptyDoubleHeadIntStackException() {
        }
    }

    // 실행 시 예외 - 스택이 가득 참
    public class OverflowDoubleHeadIntStackException extends RuntimeException {
        public OverflowDoubleHeadIntStackException() {
        }
    }

    // 생성자
    public DoubleHeadIntStack(int maxlen) {
        ptrA = 0;
        ptrB = maxlen - 1;
        capacity = maxlen;
        try {
            stk = new int[capacity]; // 스택 본체용 배열 생성
        } catch (OutOfMemoryError e) {
            // 생성할 수 없음
            capacity = 0;
        }
    }

    // 스택에 x를 푸시
    public int push(AorB sw, int x) throws OverflowDoubleHeadIntStackException {
        if (ptrA >= ptrB + 1) {
            throw new OverflowDoubleHeadIntStackException();
        }
        switch (sw) {
            case StackA -> stk[ptrA++] = x;
            case StackB -> stk[ptrB--] = x;
        }
        return x;
    }

    // 스택에서 데이터를 팝(꼭대기 데이터 꺼냄)
    public int pop(AorB sw) throws EmptyDoubleHeadIntStackException {
        int x = 0;
        switch (sw) {
            case StackA -> {
                if (ptrA <= 0) throw new EmptyDoubleHeadIntStackException(); // 스택 A가 비어있음
                x = stk[--ptrA];
            }
            case StackB -> {
                if (ptrB >= capacity - 1) throw new EmptyDoubleHeadIntStackException(); // 스택 B가 비어있음
                x = stk[++ptrB];
            }
        }
        return x;
    }

    // 스택에서 데이터를 피크(꼭대기 데이터 들여다봄)
    public int peek(AorB sw) throws EmptyDoubleHeadIntStackException {
        int x = 0;
        switch (sw) {
            case StackA -> {
                if (ptrA <= 0) throw new EmptyDoubleHeadIntStackException(); // 스택 A가 비어있음
                x = stk[ptrA - 1];
            }
            case StackB -> {
                if (ptrB >= capacity - 1) throw new EmptyDoubleHeadIntStackException(); // 스택 B가 비어있음
                x = stk[ptrB + 1];
            }
        }
        return x;
    }

    // 스택에서 x 검색하여 인덱스(없으면 -1) 반환
    public int indexOf(AorB sw, int x) {
        switch (sw) {
            case StackA -> {
                // 꼭대기부터 선형검색
                for (int i = ptrA - 1; i >= 0; i--) {
                    if (stk[i] == x) return i; // 검색 성공
                }
            }
            case StackB -> {
                // 꼭대기부터 선형검색
                for (int i = ptrB + 1; i < capacity; i++) {
                    if (stk[i] == x) return i; // 검색 성공
                }
            }
        }
        return -1; // 검색 실패
    }

    // 스택 비우기
    public void clear(AorB sw) {
        switch (sw) {
            case StackA -> ptrA = 0;
            case StackB -> ptrB = capacity - 1;
        }
    }

    // 스택 용량 반환(A와 B의 합계)
    public int getCapacity() {
        return capacity;
    }

    // 스택의 데이터 수 반환
    public int size(AorB sw) {
        switch (sw) {
            case StackA -> {
                return ptrA;
            }
            case StackB -> {
                return capacity - ptrB - 1;
            }
        }
        return 0;
    }

    // 스택이 비어 있는가
    public boolean isEmpty(AorB sw) {
        switch (sw) {
            case StackA -> {
                return ptrA <= 0;
            }
            case StackB -> {
                return ptrB >= capacity - 1;
            }
        }
        return true;
    }

    // 스택이 가득 찼는가
    public boolean isFull() {
        return ptrA >= ptrB + 1;
    }

    // 스택 안 모든 데이터를 바닥에서 꼭대기 순서로 출력
    public void dump(AorB sw) {
        switch (sw) {
            case StackA -> {
                if (ptrA <= 0)
                    System.out.println("스택이 비어 있습니다.");
                else
                    for (int i = 0; i < ptrA; i++) {
                        System.out.print(stk[i] + " ");
                    }
                System.out.println();
            }
            case StackB -> {
                if (ptrB >= capacity - 1)
                    System.out.println("스택이 비어 있습니다.");
                else
                    for (int i = capacity - 1; i > ptrB; i--) {
                        System.out.print(stk[i] + " ");
                    }
                System.out.println();
            }
        }
    }
}

 

머리가 둘인 int형 고정 길이 스택 사용(DoubleHeadIntStackTester 클래스의 모든 메서드 사용)

package ch04_1;

import java.util.Scanner;

// 머리가 둘인 int형 고정 길이 스택 사용(DoubleHeadIntStackTester 클래스의 모든 메서드 사용)
public class Ex04_doubleHeadIntStackTester {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        DoubleHeadIntStack s = new DoubleHeadIntStack(64); // 최대 64개 푸시할 수 있는 머리 둘 스택

        while (true) {
            System.out.println("현재 데이터 개수: A -" + s.size(DoubleHeadIntStack.AorB.StackA) + " / B -" + s.size(DoubleHeadIntStack.AorB.StackB));
            System.out.print("( 1) A 푸시 ( 2) A 팝 ( 3) A 피크 ( 4) A 덤프 ( 5) A 검색 ( 6) A 비움\\n" +
                    "( 7) B 푸시 ( 8) B 팝 ( 9) B 피크 (10) B 덤프 (11) B 검색 (12) B 비움\\n" +
                    "(13)   출력 ( 0) 종료 : ");

            int menu = scanner.nextInt();
            if(menu == 0) break;

            int n, x = 0;
            switch (menu) {
                case 1 -> { // A에 푸시
                    System.out.print("데이터: ");
                    x = scanner.nextInt();
                    try {
                        s.push(DoubleHeadIntStack.AorB.StackA, x);
                    } catch (DoubleHeadIntStack.EmptyDoubleHeadIntStackException e) {
                        System.out.println("스택이 가득 찼습니다.");
                    }
                }

                case 2 -> { // A에서 팝
                    try {
                        x = s.pop(DoubleHeadIntStack.AorB.StackA);
                        System.out.println("팝한 데이터는 " + x + "입니다.");
                    } catch (DoubleHeadIntStack.EmptyDoubleHeadIntStackException e) {
                        System.out.println("스택이 비어 있습니다.");
                    }
                }

                case 3 -> { // A에서 피크
                    try {
                        x = s.peek(DoubleHeadIntStack.AorB.StackA);
                        System.out.println("피크한 데이터는 " + x + "입니다.");
                    } catch (DoubleHeadIntStack.EmptyDoubleHeadIntStackException e) {
                        System.out.println("스택이 비어 있습니다.");
                    }
                }

                case 4 -> { // A를 덤프
                    s.dump(DoubleHeadIntStack.AorB.StackA);
                }

                case 5 -> { // A에서 검색
                    System.out.print("검색할 데이터: ");
                    x = scanner.nextInt();
                    n = s.indexOf(DoubleHeadIntStack.AorB.StackA, x);
                    if(n >= 0)
                        System.out.println("꼭대기에서 " + (s.size(DoubleHeadIntStack.AorB.StackA) - n) + "번째에 있습니다.");
                    else
                        System.out.println("그 데이터가 없습니다.");
                }

                case 6 -> { // A 비우기
                    s.clear(DoubleHeadIntStack.AorB.StackA);
                }

                case 7 -> { // B에 푸시
                    System.out.print("데이터: ");
                    x = scanner.nextInt();
                    try {
                        s.push(DoubleHeadIntStack.AorB.StackB, x);
                    } catch (DoubleHeadIntStack.OverflowDoubleHeadIntStackException e) {
                        System.out.println("스택이 가득 찼습니다.");
                    }
                }

                case 8 -> { // B에서 팝
                    try {
                        x = s.pop(DoubleHeadIntStack.AorB.StackB);
                        System.out.println("팝한 데이터는 " + x + "입니다.");
                    } catch (DoubleHeadIntStack.EmptyDoubleHeadIntStackException e) {
                        System.out.println("스택이 비어 있습니다.");
                    }
                }

                case 9 -> { // B에서 피크
                    try {
                        x = s.peek(DoubleHeadIntStack.AorB.StackB);
                        System.out.println("피크한 데이터는 " + x + "입니다.");
                    } catch (DoubleHeadIntStack.EmptyDoubleHeadIntStackException e) {
                        System.out.println("스택이 비어 있습니다.");
                    }
                }

                case 10 -> { // B를 덤프
                    s.dump(DoubleHeadIntStack.AorB.StackB);
                }

                case 11 -> { // B에서 검색
                    System.out.print("검색할 데이터: ");
                    x = scanner.nextInt();
                    n = s.indexOf(DoubleHeadIntStack.AorB.StackB, x);
                    if(n >= 0)
                        System.out.println("꼭대기에서 " + (s.size(DoubleHeadIntStack.AorB.StackB) - (s.getCapacity() - n) + 1) + "번째에 있습니다.");
                    else
                        System.out.println("그 데이터가 없습니다.");
                }

                case 12 -> { // B 비우기
                    s.clear(DoubleHeadIntStack.AorB.StackB);
                }

                case 13 -> { // 데이터 출력
                    System.out.println("용량: " + s.getCapacity());
                    System.out.println("A의 데이터수: " + s.size(DoubleHeadIntStack.AorB.StackA));
                    System.out.println("B의 데이터수: " + s.size(DoubleHeadIntStack.AorB.StackB));
                    System.out.println("A는 비어 " + (s.isEmpty(DoubleHeadIntStack.AorB.StackA) ? "있습니다." : "있지 않습니다."));
                    System.out.println("B는 비어 " + (s.isEmpty(DoubleHeadIntStack.AorB.StackB) ? "있습니다." : "있지 않습니다."));
                    System.out.println("가득 차 " + (s.isFull() ? "있습니다" : "있지 않습니다."));
                }
            }
        }
    }
}
/*
현재 데이터 개수: A -0 / B -0
( 1) A 푸시 ( 2) A 팝 ( 3) A 피크 ( 4) A 덤프 ( 5) A 검색 ( 6) A 비움
( 7) B 푸시 ( 8) B 팝 ( 9) B 피크 (10) B 덤프 (11) B 검색 (12) B 비움
(13)   출력 ( 0) 종료 : 1
데이터: 1
현재 데이터 개수: A -1 / B -0
데이터: 3
현재 데이터 개수: A -2 / B -0
데이터: 5

현재 데이터 개수: A -3 / B -0
( 1) A 푸시 ( 2) A 팝 ( 3) A 피크 ( 4) A 덤프 ( 5) A 검색 ( 6) A 비움
( 7) B 푸시 ( 8) B 팝 ( 9) B 피크 (10) B 덤프 (11) B 검색 (12) B 비움
(13)   출력 ( 0) 종료 : 7
데이터: 0
현재 데이터 개수: A -3 / B -1
데이터: 8
현재 데이터 개수: A -3 / B -2
데이터: 6

현재 데이터 개수: A -3 / B -3
( 1) A 푸시 ( 2) A 팝 ( 3) A 피크 ( 4) A 덤프 ( 5) A 검색 ( 6) A 비움
( 7) B 푸시 ( 8) B 팝 ( 9) B 피크 (10) B 덤프 (11) B 검색 (12) B 비움
(13)   출력 ( 0) 종료 : 2
팝한 데이터는 5입니다.
현재 데이터 개수: A -2 / B -3
( 1) A 푸시 ( 2) A 팝 ( 3) A 피크 ( 4) A 덤프 ( 5) A 검색 ( 6) A 비움
( 7) B 푸시 ( 8) B 팝 ( 9) B 피크 (10) B 덤프 (11) B 검색 (12) B 비움
(13)   출력 ( 0) 종료 : 8
팝한 데이터는 6입니다.

현재 데이터 개수: A -2 / B -2
( 1) A 푸시 ( 2) A 팝 ( 3) A 피크 ( 4) A 덤프 ( 5) A 검색 ( 6) A 비움
( 7) B 푸시 ( 8) B 팝 ( 9) B 피크 (10) B 덤프 (11) B 검색 (12) B 비움
(13)   출력 ( 0) 종료 : 3
피크한 데이터는 3입니다.
현재 데이터 개수: A -2 / B -2
( 1) A 푸시 ( 2) A 팝 ( 3) A 피크 ( 4) A 덤프 ( 5) A 검색 ( 6) A 비움
( 7) B 푸시 ( 8) B 팝 ( 9) B 피크 (10) B 덤프 (11) B 검색 (12) B 비움
(13)   출력 ( 0) 종료 : 9
피크한 데이터는 8입니다.

현재 데이터 개수: A -2 / B -2
( 1) A 푸시 ( 2) A 팝 ( 3) A 피크 ( 4) A 덤프 ( 5) A 검색 ( 6) A 비움
( 7) B 푸시 ( 8) B 팝 ( 9) B 피크 (10) B 덤프 (11) B 검색 (12) B 비움
(13)   출력 ( 0) 종료 : 4
1 3
현재 데이터 개수: A -2 / B -2
( 1) A 푸시 ( 2) A 팝 ( 3) A 피크 ( 4) A 덤프 ( 5) A 검색 ( 6) A 비움
( 7) B 푸시 ( 8) B 팝 ( 9) B 피크 (10) B 덤프 (11) B 검색 (12) B 비움
(13)   출력 ( 0) 종료 : 10
0 8

현재 데이터 개수: A -2 / B -2
( 1) A 푸시 ( 2) A 팝 ( 3) A 피크 ( 4) A 덤프 ( 5) A 검색 ( 6) A 비움
( 7) B 푸시 ( 8) B 팝 ( 9) B 피크 (10) B 덤프 (11) B 검색 (12) B 비움
(13)   출력 ( 0) 종료 : 5
검색할 데이터: 3
꼭대기에서 1번째에 있습니다.
현재 데이터 개수: A -2 / B -2
( 1) A 푸시 ( 2) A 팝 ( 3) A 피크 ( 4) A 덤프 ( 5) A 검색 ( 6) A 비움
( 7) B 푸시 ( 8) B 팝 ( 9) B 피크 (10) B 덤프 (11) B 검색 (12) B 비움
(13)   출력 ( 0) 종료 : 11
검색할 데이터: 0
꼭대기에서 2번째에 있습니다.

현재 데이터 개수: A -2 / B -2
( 1) A 푸시 ( 2) A 팝 ( 3) A 피크 ( 4) A 덤프 ( 5) A 검색 ( 6) A 비움
( 7) B 푸시 ( 8) B 팝 ( 9) B 피크 (10) B 덤프 (11) B 검색 (12) B 비움
(13)   출력 ( 0) 종료 : 6
현재 데이터 개수: A -0 / B -2
( 1) A 푸시 ( 2) A 팝 ( 3) A 피크 ( 4) A 덤프 ( 5) A 검색 ( 6) A 비움
( 7) B 푸시 ( 8) B 팝 ( 9) B 피크 (10) B 덤프 (11) B 검색 (12) B 비움
(13)   출력 ( 0) 종료 : 13
용량: 64
A의 데이터수: 0
B의 데이터수: 2
A는 비어 있습니다.
B는 비어 있지 않습니다.
가득 차 있지 않습니다.
현재 데이터 개수: A -0 / B -2
( 1) A 푸시 ( 2) A 팝 ( 3) A 피크 ( 4) A 덤프 ( 5) A 검색 ( 6) A 비움
( 7) B 푸시 ( 8) B 팝 ( 9) B 피크 (10) B 덤프 (11) B 검색 (12) B 비움
(13)   출력 ( 0) 종료 : 12
현재 데이터 개수: A -0 / B -0
 */

댓글