# ์คํ & ํ
# ์คํ(Stack)
์ ๋ ฅ๊ณผ ์ถ๋ ฅ์ด ํ ๊ณณ(๋ฐฉํฅ)์ผ๋ก ์ ํ
# LIFO (Last In First Out, ํ์ ์ ์ถ) : ๊ฐ์ฅ ๋์ค์ ๋ค์ด์จ ๊ฒ์ด ๊ฐ์ฅ ๋จผ์ ๋์ด
์ธ์ ์ฌ์ฉ?
ํจ์์ ์ฝ์คํ, ๋ฌธ์์ด ์ญ์ ์ถ๋ ฅ, ์ฐ์ฐ์ ํ์ํ๊ธฐ๋ฒ
๋ฐ์ดํฐ ๋ฃ์ : push()
๋ฐ์ดํฐ ์ต์์ ๊ฐ ๋บ : pop()
๋น์ด์๋ ์ง ํ์ธ : isEmpty()
๊ฝ์ฐจ์๋ ์ง ํ์ธ : isFull()
+SP
push์ popํ ๋๋ ํด๋น ์์น๋ฅผ ์๊ณ ์์ด์ผ ํ๋ฏ๋ก ๊ธฐ์ตํ๊ณ ์๋ '์คํ ํฌ์ธํฐ(SP)'๊ฐ ํ์ํจ
์คํ ํฌ์ธํฐ๋ ๋ค์ ๊ฐ์ด ๋ค์ด๊ฐ ์์น๋ฅผ ๊ฐ๋ฆฌํค๊ณ ์์ (์ฒ์ ๊ธฐ๋ณธ๊ฐ์ -1)
private int sp = -1;
# push
public void push(Object o) {
if(isFull(o)) {
return;
}
stack[++sp] = o;
}
์คํ ํฌ์ธํฐ๊ฐ ์ต๋ ํฌ๊ธฐ์ ๊ฐ์ผ๋ฉด return
์๋๋ฉด ์คํ์ ์ต์์ ์์น์ ๊ฐ์ ๋ฃ์
# pop
public Object pop() {
if(isEmpty(sp)) {
return null;
}
Object o = stack[sp--];
return o;
}
์คํ ํฌ์ธํฐ๊ฐ 0์ด ๋๋ฉด null๋ก return;
์๋๋ฉด ์คํ์ ์ต์์ ์์น ๊ฐ์ ๊บผ๋ด์ด
# isEmpty
private boolean isEmpty(int cnt) {
return sp == -1 ? true : false;
}
์ ๋ ฅ ๊ฐ์ด ์ต์ด ๊ฐ๊ณผ ๊ฐ๋ค๋ฉด true, ์๋๋ฉด false
# isFull
private boolean isFull(int cnt) {
return sp + 1 == MAX_SIZE ? true : false;
}
์คํ ํฌ์ธํฐ ๊ฐ+1์ด MAX_SIZE์ ๊ฐ์ผ๋ฉด true, ์๋๋ฉด false
# ๋์ ๋ฐฐ์ด ์คํ
์์ฒ๋ผ ๊ตฌํํ๋ฉด ์คํ์๋ MAX_SIZE๋ผ๋ ์ต๋ ํฌ๊ธฐ๊ฐ ์กด์ฌํด์ผ ํ๋ค
(์คํ ํฌ์ธํฐ์ MAX_SIZE๋ฅผ ๋น๊ตํด์ isFull ๋ฉ์๋๋ก ๋น๊ตํด์ผ๋๊ธฐ ๋๋ฌธ!)
์ต๋ ํฌ๊ธฐ๊ฐ ์๋ ์คํ์ ๋ง๋๋ ค๋ฉด?
arraycopy๋ฅผ ํ์ฉํ ๋์ ๋ฐฐ์ด ์ฌ์ฉ
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;
}
๊ธฐ์กด ์คํ์ 2๋ฐฐ ํฌ๊ธฐ๋งํผ ์์ ๋ฐฐ์ด(arr)์ ๋ง๋ค๊ณ
arraycopy๋ฅผ ํตํด stack์ ์ธ๋ฑ์ค 0๋ถํฐ MAX_SIZE๋งํผ์ arr ๋ฐฐ์ด์ 0๋ฒ์งธ๋ถํฐ ๋ณต์ฌํ๋ค
๋ณต์ฌ ํ์ arr์ ์ฐธ์กฐ๊ฐ์ stack์ ๋ฎ์ด์์ด๋ค
๋ง์ง๋ง์ผ๋ก MAX_SIZE์ ๊ฐ์ 2๋ฐฐ๋ก ์ฆ๊ฐ์์ผ์ฃผ๋ฉด ๋๋ค.
์ด๋ฌ๋ฉด, ์คํ์ด ๊ฐ๋์ฐผ์ ๋ ์๋์ผ๋ก ํ์ฅ๋๋ ์คํ์ ๊ตฌํํ ์ ์์
# ์คํ์ ์ฐ๊ฒฐ๋ฆฌ์คํธ๋ก ๊ตฌํํด๋ ํด๊ฒฐ ๊ฐ๋ฅ
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์ ๋ฐ์ดํฐ๊ฐ ์๋ค๋ ์๋ฏธ๋ก ์ง์ ํด๋ .
}
}
# ํ(Queue)
์ ๋ ฅ๊ณผ ์ถ๋ ฅ์ ํ ์ชฝ ๋(front, rear)์ผ๋ก ์ ํ
# FIFO (First In First Out, ์ ์ ์ ์ถ) : ๊ฐ์ฅ ๋จผ์ ๋ค์ด์จ ๊ฒ์ด ๊ฐ์ฅ ๋จผ์ ๋์ด
์ธ์ ์ฌ์ฉ?
๋ฒํผ, ๋ง๊ตฌ ์ ๋ ฅ๋ ๊ฒ์ ์ฒ๋ฆฌํ์ง ๋ชปํ๊ณ ์๋ ์ํฉ, BFS
ํ์ ๊ฐ์ฅ ์ฒซ ์์๋ฅผ front, ๋ ์์๋ฅผ rear๋ผ๊ณ ๋ถ๋ฆ
ํ๋ ๋ค์ด์ฌ ๋ rear๋ก ๋ค์ด์ค์ง๋ง, ๋์ฌ ๋๋ front๋ถํฐ ๋น ์ง๋ ํน์ฑ์ ๊ฐ์ง
์ ๊ทผ๋ฐฉ๋ฒ์ ๊ฐ์ฅ ์ฒซ ์์์ ๋ ์์๋ก๋ง ๊ฐ๋ฅ
๋ฐ์ดํฐ ๋ฃ์ : enQueue()
๋ฐ์ดํฐ ๋บ : deQueue()
๋น์ด์๋ ์ง ํ์ธ : isEmpty()
๊ฝ์ฐจ์๋ ์ง ํ์ธ : isFull()
๋ฐ์ดํฐ๋ฅผ ๋ฃ๊ณ ๋บ ๋ ํด๋น ๊ฐ์ ์์น๋ฅผ ๊ธฐ์ตํด์ผ ํจ. (์คํ์์ ์คํ ํฌ์ธํฐ์ ๊ฐ์ ์ญํ )
์ด ์์น๋ฅผ ๊ธฐ์ตํ๊ณ ์๋ ๊ฒ front์ rear
front : deQueue ํ ์์น ๊ธฐ์ต
rear : enQueue ํ ์์น ๊ธฐ์ต
# ๊ธฐ๋ณธ๊ฐ
private int size = 0;
private int rear = -1;
private int front = -1;
Queue(int size) {
this.size = size;
this.queue = new Object[size];
}
# enQueue
public void enQueue(Object o) {
if(isFull()) {
return;
}
queue[++rear] = o;
}
enQueue ์, ๊ฐ๋ ์ฐผ๋ค๋ฉด ๊ฝ ์ฐจ ์๋ ์ํ์์ enQueue๋ฅผ ํ๊ธฐ ๋๋ฌธ์ overflow
์๋๋ฉด rear์ ๊ฐ ๋ฃ๊ณ 1 ์ฆ๊ฐ
# deQueue
public Object deQueue(Object o) {
if(isEmpty()) {
return null;
}
Object o = queue[front];
queue[front++] = null;
return o;
}
deQueue๋ฅผ ํ ๋ ๊ณต๋ฐฑ์ด๋ฉด underflow
front์ ์์นํ ๊ฐ์ object์ ๊บผ๋ธ ํ, ๊บผ๋ธ ์์น๋ null๋ก ์ฑ์์ค
# isEmpty
public boolean isEmpty() {
return front == rear;
}
front์ rear๊ฐ ๊ฐ์์ง๋ฉด ๋น์ด์ง ๊ฒ
# isFull
public boolean isFull() {
return (rear == queueSize-1);
}
rear๊ฐ ์ฌ์ด์ฆ-1๊ณผ ๊ฐ์์ง๋ฉด ๊ฐ๋์ฐฌ ๊ฒ
์ผ๋ฐ ํ์ ๋จ์ : ํ์ ๋น ๋ฉ๋ชจ๋ฆฌ๊ฐ ๋จ์ ์์ด๋, ๊ฝ ์ฐจ์๋๊ฒ์ผ๋ก ํ๋จํ ์๋ ์์
(rear๊ฐ ๋์ ๋๋ฌํ์ ๋)
์ด๋ฅผ ๊ฐ์ ํ ๊ฒ์ด '์ํ ํ'
๋ ผ๋ฆฌ์ ์ผ๋ก ๋ฐฐ์ด์ ์ฒ์๊ณผ ๋์ด ์ฐ๊ฒฐ๋์ด ์๋ ๊ฒ์ผ๋ก ๊ฐ์ฃผํจ!
์ํ ํ๋ ์ด๊ธฐ ๊ณต๋ฐฑ ์ํ์ผ ๋ front์ rear๊ฐ 0
๊ณต๋ฐฑ, ํฌํ ์ํ๋ฅผ ์ฝ๊ฒ ๊ตฌ๋ถํ๊ธฐ ์ํด ์๋ฆฌ ํ๋๋ฅผ ํญ์ ๋น์๋
(index + 1) % size๋ก ์ํ์ํจ๋ค
# ๊ธฐ๋ณธ๊ฐ
private int size = 0;
private int rear = 0;
private int front = 0;
Queue(int size) {
this.size = size;
this.queue = new Object[size];
}
# enQueue
public void enQueue(Object o) {
if(isFull()) {
return;
}
rear = (++rear) % size;
queue[rear] = o;
}
enQueue ์, ๊ฐ๋ ์ฐผ๋ค๋ฉด ๊ฝ ์ฐจ ์๋ ์ํ์์ enQueue๋ฅผ ํ๊ธฐ ๋๋ฌธ์ overflow
# deQueue
public Object deQueue(Object o) {
if(isEmpty()) {
return null;
}
preIndex = front;
front = (++front) % size;
Object o = queue[preIndex];
return o;
}
deQueue๋ฅผ ํ ๋ ๊ณต๋ฐฑ์ด๋ฉด underflow
# isEmpty
public boolean isEmpty() {
return front == rear;
}
front์ rear๊ฐ ๊ฐ์์ง๋ฉด ๋น์ด์ง ๊ฒ
# isFull
public boolean isFull() {
return ((rear+1) % size == front);
}
rear+1%size๊ฐ front์ ๊ฐ์ผ๋ฉด ๊ฐ๋์ฐฌ ๊ฒ
์ํ ํ์ ๋จ์ : ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ์ ํ์ฉํ์ง๋ง, ๋ฐฐ์ด๋ก ๊ตฌํ๋์ด ์๊ธฐ ๋๋ฌธ์ ํ์ ํฌ๊ธฐ๊ฐ ์ ํ
์ด๋ฅผ ๊ฐ์ ํ ๊ฒ์ด '์ฐ๊ฒฐ๋ฆฌ์คํธ ํ'
# ์ฐ๊ฒฐ๋ฆฌ์คํธ ํ๋ ํฌ๊ธฐ๊ฐ ์ ํ์ด ์๊ณ ์ฝ์ , ์ญ์ ๊ฐ ํธ๋ฆฌ
# enqueue ๊ตฌํ
public void enqueue(E item) {
Node oldlast = tail; // ๊ธฐ์กด์ tail ์์ ์ ์ฅ
tail = new Node; // ์๋ก์ด tail ์์ฑ
tail.item = item;
tail.next = null;
if(isEmpty()) head = tail; // ํ๊ฐ ๋น์ด์์ผ๋ฉด head์ tail ๋ชจ๋ ๊ฐ์ ๋
ธ๋ ๊ฐ๋ฆฌํด
else oldlast.next = tail; // ๋น์ด์์ง ์์ผ๋ฉด ๊ธฐ์กด tail์ next = ์๋ก์ด tail๋ก ์ค์
}
๋ฐ์ดํฐ ์ถ๊ฐ๋ ๋ ๋ถ๋ถ์ธ tail์ ํ๋ค.
๊ธฐ์กด์ tail๋ ๋ณด๊ดํ๊ณ , ์๋ก์ด tail ์์ฑ
ํ๊ฐ ๋น์์ผ๋ฉด head = tail๋ฅผ ํตํด ๋์ด ๊ฐ์ ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋๋ก ํ๋ค.
ํ๊ฐ ๋น์ด์์ง ์์ผ๋ฉด, ๊ธฐ์กด tail์ next์ ์๋ก๋ง๋ tail๋ฅผ ์ค์ ํด์ค๋ค.
# dequeue ๊ตฌํ
public T dequeue() {
// ๋น์ด์์ผ๋ฉด
if(isEmpty()) {
tail = head;
return null;
}
// ๋น์ด์์ง ์์ผ๋ฉด
else {
T item = head.item; // ๋นผ๋ผ ํ์ฌ front ๊ฐ ์ ์ฅ
head = head.next; // front๋ฅผ ๋ค์ ๋
ธ๋๋ก ์ค์
return item;
}
}
- ๋ฐ์ดํฐ๋ head๋ก๋ถํฐ ๊บผ๋ธ๋ค. (๊ฐ์ฅ ๋จผ์ ๋ค์ด์จ ๊ฒ๋ถํฐ ๋นผ์ผํ๋ฏ๋ก)
- head์ ๋ฐ์ดํฐ๋ฅผ ๋ฏธ๋ฆฌ ์ ์ฅํด๋๋ค.
- ๊ธฐ์กด์ head๋ฅผ ๊ทธ ๋ค์ ๋ ธ๋์ head๋ก ์ค์ ํ๋ค.
- ์ ์ฅํด๋ ๋ฐ์ดํฐ๋ฅผ return ํด์ ๊ฐ์ ๋นผ์จ๋ค.
์ด์ฒ๋ผ ์ฝ์ ์ tail, ์ ๊ฑฐ๋ head๋ก ํ๋ฉด์ ์ฝ์ /์ญ์ ๋ฅผ ์คํ์ฒ๋ผ O(1)์ ๊ฐ๋ฅํ๋๋ก ๊ตฌํ์ด ๊ฐ๋ฅํ๋ค.