-
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)
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 모범 답안
'CS > Data Structure' 카테고리의 다른 글
Hash 자료구조 알아보기 (0) 2021.04.20 이진탐색트리(Binary Search Tree) 자료구조 (0) 2021.04.20 PriorityQueue와 Heap 자료구조 (0) 2021.04.20 트리 자료구조의 개념과 이진 트리 순회 (0) 2021.04.17 Array, LinkedList, ArrayList 비교 (0) 2021.04.17 댓글