본문 바로가기
백준

[10866] 덱

by kmyobin 2022. 11. 4.


https://www.acmicpc.net/problem/10866

 

10866번: 덱

첫째 줄에 주어지는 명령의 수 N (1 ≤ N ≤ 10,000)이 주어진다. 둘째 줄부터 N개의 줄에는 명령이 하나씩 주어진다. 주어지는 정수는 1보다 크거나 같고, 100,000보다 작거나 같다. 문제에 나와있지

www.acmicpc.net

 

deque를 실제로 구현해보는 문제이다.

 

 

Deque는 앞/뒤에서 모두 push, pop이 가능하다는 것이다.(Queue는 앞에서는 pop, 뒤에서는 push 가능)

 

 

deque의 앞과 뒤를 나타내는 front, rear를 어떻게 나타냈냐면

size 오타. size=(rear-front+MAX)%MAX로 정정

front는 실제 있는 곳보다 앞에, rear는 실제 값이 있는 곳을 가리키도록 설정하였다. 

size를 출력하고자 한다면 (rear-front+MAX)%MAX 로 구할 수 있다.

 

 

완성된 MyDeque는 아래와 같다.

template<class T> class MyDeque
{
public:
	int front; int rear; int size;
	T* values;

	MyDeque() {
		size = MAX;
		values = new T[size];
		front = 0; rear = 0;
	}

	~MyDeque() { delete[] values; }
	
	void push_front(T value) { // front에서 값 넣기
		values[front] = value; // 값 넣고
		front = (front - 1 + MAX) % MAX; // front--와 비슷(배열 최소 인덱스는 0이므로 배열 끝으로 가서 front를 가리킬수도) 
	}

	void push_back(T value) { // rear에서 값 넣기
		rear = (rear + 1) % MAX; // 미리 index를 증가시키고
		values[rear] = value; // 값 넣음
	}

	void pop_front() { // front 값 빼기
		if (!empty()) {
			front = (front + 1) % MAX; // 비어있는 곳을 가리키므로 증가시킨다음
			cout << values[front] << "\n"; // 출력 후
			values[front] = NULL; // NULL값으로 비워줌
			
		}
		else { // queue에 들어있는 정수가 없는 경우
			cout << -1 << "\n";
		}
	}
	void pop_back() { // rear 값 빼기
		if (!empty()) {
			cout << values[rear] << "\n";
			rear = (rear - 1 + MAX) % MAX;
		}
		else { // queue에 들어있는 정수가 없는 경우
			cout << -1 << "\n";
		}
	}

	void size_() { // 재정의 오류 발생
		cout << (rear - front + MAX) % MAX << "\n";
	}

	bool empty() {
		return front == rear;
	}

	void front_() { // 재정의 오류 발생
		if (!empty()) cout << values[(front + 1) % MAX] << "\n"; // front는 비어있는 곳을 가리키므로 +1
		else cout << -1 << "\n";
	}

	void back() { // 가장 뒤에 있는 정수 출력
		if (!empty()) cout << values[rear] << "\n"; // rear는 실제 값이 있는 곳을 가리키므로
		else cout << -1 << "\n";
	}
};

중간중간 헤더파일과 충돌하는 재정의 오류들은 _를 붙여서 해결하였다.

 

왜 값을 가리킬 때 index에서 자꾸 MAX를 더해주고 MAX로 나눈 나머지값을 취해주냐면 

C++에서의 배열은 0부터 시작하여 한정적이다.

하지만 front에 값이 채워질 수록 front는 앞당겨져야하는데, 우리는 배열 index를 0까지만 쓸 수 있으므로 다시 뒤로 돌아가서 쓰는 것이다!

 

이해 완료!

 

전체 코드는 아래와 같다.

#include <iostream>
#include <string>
#define MAX 100000
using namespace std;

template<class T> class MyDeque
{
public:
	int front; int rear; int size;
	T* values;

	MyDeque() {
		size = MAX;
		values = new T[size];
		front = 0; rear = 0;
	}

	~MyDeque() { delete[] values; }
	
	void push_front(T value) { // front에서 값 넣기
		values[front] = value; // 값 넣고
		front = (front - 1 + MAX) % MAX; // front--와 비슷(배열 최소 인덱스는 0이므로 배열 끝으로 가서 front를 가리킬수도) 
	}

	void push_back(T value) { // rear에서 값 넣기
		rear = (rear + 1) % MAX; // 미리 index를 증가시키고
		values[rear] = value; // 값 넣음
	}

	void pop_front() { // front 값 빼기
		if (!empty()) {
			front = (front + 1) % MAX; // 비어있는 곳을 가리키므로 증가시킨다음
			cout << values[front] << "\n"; // 출력 후
			values[front] = NULL; // NULL값으로 비워줌
			
		}
		else { // queue에 들어있는 정수가 없는 경우
			cout << -1 << "\n";
		}
	}
	void pop_back() { // rear 값 빼기
		if (!empty()) {
			cout << values[rear] << "\n";
			rear = (rear - 1 + MAX) % MAX;
		}
		else { // queue에 들어있는 정수가 없는 경우
			cout << -1 << "\n";
		}
	}

	void size_() { // 재정의 오류 발생
		cout << (rear - front + MAX) % MAX << "\n";
	}

	bool empty() {
		return front == rear;
	}

	void front_() { // 재정의 오류 발생
		if (!empty()) cout << values[(front + 1) % MAX] << "\n"; // front는 비어있는 곳을 가리키므로 +1
		else cout << -1 << "\n";
	}

	void back() { // 가장 뒤에 있는 정수 출력
		if (!empty()) cout << values[rear] << "\n"; // rear는 실제 값이 있는 곳을 가리키므로
		else cout << -1 << "\n";
	}
};

MyDeque<int> mydeque;

int N;
string command[8] = { "push_front", "push_back", "pop_front", "pop_back",
"size", "empty", "front", "back" };
string input;

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);

	cin >> N;

	for (int i = 0; i < N + 1; i++)
	{
		getline(cin, input);
		for (int j = 0; j < 8; j++) {
			if (input.find(command[j]) != string::npos) { // 찾았다면				
				if (j == 0) { // push_front
					string temp = "";
					for (int k = 11; k < input.length(); k++) {
						temp += input[k]; // 정수 string으로 받은다음
					}
					int in = stoi(temp); // stoi로 정수 만듦
					mydeque.push_front(in);
				}
				else if (j == 1) { // push_back
					string temp = "";
					for (int k = 10; k < input.length(); k++) {
						temp += input[k]; // 정수 string으로 받은다음
					}
					int in = stoi(temp); // stoi로 정수 만듦
					mydeque.push_back(in);
				}
				else if (j == 2) { // pop_front
					mydeque.pop_front();
				}
				else if (j == 3) { // pop_back
					mydeque.pop_back();
				}
				else if (j == 4) { // size
					mydeque.size_();
				}
				else if (j == 5) { // empty
					cout << mydeque.empty() << "\n";
				}
				else if (j == 6) { // front
					mydeque.front_();
				}
				else { // back
					mydeque.back();
				}
				break;
			}
		}
	}

}

'백준' 카테고리의 다른 글

[1406] 에디터  (0) 2022.11.07
[1158] 요세푸스 문제  (0) 2022.11.06
[10845] 큐  (0) 2022.11.03
[17413] 단어 뒤집기 2  (0) 2022.11.02
[2156] 포도주 시식  (0) 2022.10.31

댓글