stack은 데이터를 저장하는 자료구조 중 하나로 후입선출(Last In First Out) 의 구조를 따른다. 즉, 나중에 추가된 데이터가 먼저 제거되는 구조이다.
활용 예시: 함수 호출이나 재귀 알고리즘, 데이터를 저장하고 추출하는 데에 있어서 효율적이다.
call stack, 후위 표기법 연산, 괄호 유효성 검사, 웹 브라우저 방문기록, 깊이 우선 탐색(DFS)
시간 순서상 먼저 입력된게 가장 먼저 출력되는 선입선출 구조를 따르는 큐와 달리 스택은 시간 순서상 가장 최근에 추가한 데이터가 가장 먼저 나오는 후입선출 형식으로 데이터를 저장한다.
stack에서 데이터를 추가 하는 것, push의 경우 스택의 맨 뒤에 데이터를 추가하면 완료되기 때문에 시간복잡도는 O(1)이다.
stack에서 맨 위의 데이터를 추출 하는 것, pop의 경우 스택의 맨 뒤에 데이터를 삭제하면 완료되기 때문에 시간복잡도는 O(1)이다.
push와 pop모두 스택의 top(가장 나중의 데이터)에 원소를 추가하거나 삭제하는 형식으로 구현
#include <stack>
stack<int> stack;//정수형 스택
stack.push(element)
stack.pop()
stack.top()
stack.size()
stack.empty()
swap(stack1 , stack2)
Q. 스택 두 개를 이용해 큐를 구현하기
⭐️핵심: stack 두 개를 사용해서 enqueue ,dequeue를 구현하는 것에 초점을 맞춘다.
큐의 enqueue() 를 구현할 때 첫 번째 스택을 사용하고 dequeue()를 구현할 때 두번째 스택을 사용하면 큐를 구현할 수 있다.
#include <iostream>
#include <stack>
using namespace std;
class MyQueue {
private:
stack<int> instack;
stack<int> outstack;
public:
// 큐에 요소를 추가하는 함수
void enqueue(int x) {
instack.push(x);
}
// 큐에서 요소를 제거하고 반환하는 함수
int dequeue() {
if (outstack.empty()) {
// outstack이 비어있는 경우, instack의 모든 요소를 outstack으로 이동
while (!instack.empty()) {
outstack.push(instack.top());
instack.pop();
}
}
// outstack에서 요소를 꺼내 반환
int front = outstack.top();
outstack.pop();
return front;
}
};
int main() {
MyQueue q;
// enqueue 연산 수행
q.enqueue(1);
q.enqueue(2);
q.enqueue(3);
// dequeue 연산 수행
cout << q.dequeue() << endl; // 출력: 1
cout << q.dequeue() << endl; // 출력: 2
// enqueue 연산 수행
q.enqueue(4);
// dequeue 연산 수행
cout << q.dequeue() << endl; // 출력: 3
cout << q.dequeue() << endl; // 출력: 4
return 0;
}
=>이를 종합해봤을 때 amortized O(1)의 시간복잡도를 갖는다.
Q. ⭐️큐 두 개를 이용해 스택 구현하기
핵심: queue 두 개를 사용해 스택의 push, pop을 구현하는 것에 초점을 맞춰서 문제 해결
push에 사용할 큐는 q1, pop에 사용할 큐는 q2로 가정
#include <iostream>
#include <queue>
using namespace std;
class MyStack {
private:
queue<int> q1;
queue<int> q2;
public:
// 스택에 요소를 추가하는 함수
void push(int x) {
// q1에 요소 추가
q1.push(x);
}
// 스택에서 요소를 제거하고 반환하는 함수
int pop() {
// q1에 저장된 데이터의 갯수가 1 이하로 남을 때까지 q1의 모든 요소를 q2로 이동
while (q1.size() > 1) {
q2.push(q1.front());
q1.pop();
}
// q1에 남아있는 하나의 데이터를 제거하여 반환
int topElement = q1.front();
q1.pop();
// q1과 q2의 이름을 swap하여 다음 pop을 위해 준비
swap(q1, q2);
return topElement;
}
};
int main() {
MyStack s;
// push 연산 수행
s.push(1);
s.push(2);
s.push(3);
// pop 연산 수행
cout << s.pop() << endl; // 출력: 3
cout << s.pop() << endl; // 출력: 2
// push 연산 수행
s.push(4);
// pop 연산 수행
cout << s.pop() << endl; // 출력: 4
cout << s.pop() << endl; // 출력: 1
return 0;
}