1 스택 및 대기열
스택 : 선입 선출 데이터 구조
대기열 :
그림에 표시된 선입 선출 데이터 구조 :
그렇다면 C ++를 예로 들어 보겠습니다. 사용하는 프로그래밍 언어의 스택과 큐는 무엇입니까? 다음 측면에 대해 생각할 수 있습니다.
- C ++ 의 스택 은 컨테이너입니까?
- 우리가 사용하는 스택 은 어떤 STL 버전에 속합니까 ?
- 그것을 달성하기 위해 STL에서 스택 을 어떻게 사용 합니까?
- 스택 은 스택 공간 을 순회하는 반복기를 제공 합니까?
C ++ 표준 라이브러리에는 여러 버전이 있습니다. 해당 스택 및 큐의 구현 원리를 알기 위해서는 사용중인 STL 버전을 알아야합니다. HP의 Silicon Graphics Computer Systems에서 참조하는 SGI STL을 사용합니다. STL 구현, Linux C ++ 컴파일러 GCC에 의해 채택 된 SGI STL은 오픈 소스 소프트웨어이며 소스 코드의 가독성이 높습니다.
스택에 대해 이야기합시다
- 스택은 푸시 및 팝과 같은 인터페이스를 제공합니다. 모든 요소는 선입 선출 규칙을 준수해야하므로 스택은 순회 기능을 제공하지 않으며 반복기를 제공하지도 않습니다. 세트 또는 맵과 달리 모든 요소를 순회하는 반복기를 제공합니다.
- 스택은 모든 작업을 완료하기 위해 하단 컨테이너를 기반으로하여 외부에 통합 인터페이스를 제공하고 하단 컨테이너는 플러그 가능합니다. 스택의 기능을 구현하는 데 사용되는 컨테이너를 제어 할 수 있습니다. 따라서 STL의 스택은 컨테이너가 아니라 컨테이너 어댑터로 분류됩니다.
그렇다면 STL에서 스택을 구현하는 데 어떤 컨테이너가 사용됩니까?
아래 그림에서 볼 수 있듯이 스택의 내부 구조, 스택의 기본 구현은 벡터, deque, 목록이 모두 가능하며 주로 배열 및 연결 목록의 기본 구현이 가능합니다.
우리는 일반적으로 SGI STL을 사용합니다. 기본 구현이 지정되지 않았습니다. 기본값은 기본적으로 스택의 하위 수준 구조로 deque입니다. deque는 양방향 대기열로, 한 섹션이 봉인되어있는 한 다른 쪽 끝을 열어서 만 스택의 논리를 실현할 수 있습니다.
스택이 설명 된 후 대기열이 이해하기 더 쉽습니까?
큐의 선입 선출 데이터 구조도 순회 동작을 허용하지 않으며 반복자를 제공하지 않습니다. SGI STL의 큐는 deque를 기본 하단 구조로 사용합니다.
따라서 STL의 큐는 컨테이너가 아니라 컨테이너 어댑터로 분류됩니다.
3 스택을 사용하여 대기열 구현
https://leetcode-cn.com/problems/implement-queue-using-stacks/
3.1 사고 분석
스택을 사용하여 대기열의 동작을 모델링하면 스택을 하나만 사용하는 경우 확실히 작동하지 않으므로 두 개의 스택, 하나의 입력 스택 및 하나의 출력 스택이 필요합니다. 여기서는 입력 스택과 스택 간의 관계에주의해야합니다. 출력 스택.
다음은 거물 https://mp.weixin.qq.com/s/P6tupDwRFi6Ay-L7DT4NVg의 애니메이션을 인용합니다.
3.2 코드 구현
class MyQueue {
//用两个栈实现队列
public:
stack<int> stackIn;
stack<int> stackOut;
/** Initialize your data structure here. */
MyQueue() {
}
/** Push element x to the back of queue. */
void push(int x) {
stackIn.push(x);
}
/** Removes the element from in front of queue and returns that element. */
int pop() {
//当stackOut中是空的时候把stackIn中的数据导入到stackOut中
if (stackOut.empty()) {
//把stackIn中的数据导入,直到其为空为止
while (!stackIn.empty()) {
stackOut.push(stackIn.top());
stackIn.pop();
}
}
int result = stackOut.top();
stackOut.pop();
return result;
}
/** Get the front element. */
int peek() {
int ret = this->pop();
stackOut.push(ret);
return ret;
}
/** Returns whether the queue is empty. */
bool empty() {
return stackIn.empty() && stackOut.empty();
}
};
/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue* obj = new MyQueue();
* obj->push(x);
* int param_2 = obj->pop();
* int param_3 = obj->peek();
* bool param_4 = obj->empty();
*/
4 대기열을 사용하여 스택 구현
https://leetcode-cn.com/problems/implement-stack-using-queues/
4.1 사고 분석
위는 스택을 사용하여 대기열, 입력 스택 및 출력 스택을 구현하는 것입니다. 대기열을 사용하여 스택을 구현할 수 있습니까? 실제로 작동하지 않습니다. 대기열은 선입 선출을 따릅니다. 한 큐의 데이터를 다른 큐로 가져 오면 데이터의 순서가 변경되지 않고 선입 선출 (first-in-last-out) 순서가됩니다.
따라서 대기열을 사용하여 스택을 구현하는 아이디어는 두 개의 대기열과 하나의 대기열이 백업으로 사용되는 것입니다. 두 개의 대기열 que1 및 que2는 대기열의 기능을 구현하는 데 사용됩니다. que2는 실제로 백업 기능입니다. que1의 마지막 요소를 제외한 모든 요소는 que2로 백업 된 다음 마지막 요소가 팝되고 다른 요소는 que2에서 다시 가져옵니다. que1.
거인의 애니메이션 사진 인용 : https://mp.weixin.qq.com/s/yzn6ktUlL-vRG3-m5a8_Yw
4.2 코드 구현
class MyStack {
public:
//用两个队列实现栈的功能----后进先出
queue<int> que1;
queue<int> que2;//用于临时备份数据
/** Initialize your data structure here. */
MyStack() {
}
/** Push element x onto stack. */
void push(int x) {
que1.push(x);
}
/** Removes the element on top of the stack and returns that element. */
int pop() {
//将que1中的数据放入到que2中,直到que1中只剩1个数据
while (que1.size() > 1) {
que2.push(que1.front());
que1.pop();
}
//此时que1中有一个数据
int ret = que1.front();
que1.pop();
//把que2中的数据放回que1中
while(!que2.empty()) {
que1.push(que2.front());
que2.pop();
}
return ret;
}
/** Get the top element. */
int top() {
return que1.back();//back:队列尾 front:队列头
}
/** Returns whether the stack is empty. */
bool empty() {
return que1.empty();
}
};
/**
* Your MyStack object will be instantiated and called as such:
* MyStack* obj = new MyStack();
* obj->push(x);
* int param_2 = obj->pop();
* int param_3 = obj->top();
* bool param_4 = obj->empty();
*/