2025. 2. 24. 12:16ㆍ원티드_언리얼RPG 2기/자료구조& 알고리즘
https://chisel-chocolate-566.notion.site/1-Stack-queue-deque-1a26a793da6280659ce8ffee14b37368
1주차 스택,큐,덱 발표 <담당자: 정재훈>
덱은 double ended que
양 끝에서 삽입 삭제가 가능한 구조 이다.
원소의 추가, 제거, 맨 앞/뒤 원소확인시 O(1)의 시간복잡도를 가진다.
맨앞/뒤 외의 자료구조는 확인이 불가하다.
배열로 구현한 덱, 연결리스트로 구현한 덱, 원형 리스트로 구현한 덱 등이 있다.
연결리스트를 이용한 구현은 다음 주차때 연결리스트를 배우고 하려고 한다.
따라서 이번에는 가장 난이도가 쉬운 배열로 덱의 삽입,삭제 기능을 구현해봤다.
작성코드
#include <iostream>
using namespace std;
//덱은 시작지점을 배열의 중간에 둬야한다.
const int MX = 5;
int deq[2 * MX + 1];
int head = MX, tail = MX;
bool isEmpty();
// push_front, push_back : 앞 or 뒤에 데이터 추가하기.
void push_front(int x){
if (head > 0) {
deq[--head] = x;
}
else {
cout << "front에서 오버플로우\n";
}
}
void push_back(int x){
if (tail < 2 * MX + 1) {
deq[tail++] = x;
}
else {
cout << "back에서 오버플로우\n";
}
}
// pop_front, pop_back: 앞 or 뒤에 데이터 삭제하기.
void pop_front(){
if (head < tail) {
head++;
}
else {
cout << "덱이 비어있습니다.\n";
}
}
void pop_back(){
if (head < tail) {
tail--;
}
else {
cout << "덱이 비어있습니다.\n";
}
}
// front(), back() : 앞 or 뒤의 데이터를 반환한다.
int front(){
if (!isEmpty()) {
return deq[head];
}
else {
cout << "덱이 비어있습니다.\n";
return -1;
//만약에 덱에 -1을 넣었다면 데이터가 있어도 -1을 반환할수있다.
//stl deque에서는 자동으로 예외처리를 해줌
}
}
int back(){
if (!isEmpty()) {
return deq[tail - 1];
}
else {
cout << "덱이 비어있습니다.\n";
return -1;
}
}
// empty() 덱이 비었는지 확인 , 비면 true
bool isEmpty(){
return head == tail;
}
// 덱의 전체 요소의 개수 반환
int size(){
return tail - head;
}
//head와 tail을 중앙으로 재설정하여 초기화, head ~ tail 사이의 구간만 유효한 요소로 간주
//이전값들은 메모리 상에 그대로 존재하지만 덱의 동작에서는 무시됨 "사라진것처럼 동작"
void clear(){
head = tail = MX;
}
void test() {
push_front(3); // 덱: 3
push_front(2); // 덱: 2 3
push_front(1); // 덱: 1 2 3
push_back(4); // 덱: 1 2 3 4
pop_back(); // 덱: 1 2 3
pop_front(); // 덱: 2 3
cout << "Front: " << front() << "\n"; // 출력: 2
cout << "Back: " << back() << "\n"; // 출력: 3
clear(); // 덱 초기화
if (isEmpty())
cout << "clear이후 덱은 비어있습니다.\n";
}
int main() {
test();
return 0;
}
문제 1.
push 할때 오버플로우, pop할때 언더플로우 예외처리가 필요
해결: head >0 tail < 배열의 크기 일때 push
head < tail 일때 pop,
문제 2.
clear 할때 0으로 초기화 했음
해결: head와 tail을 중앙으로 재설정 하여 초기화
head ~ tail 사이의 구간만 유효한 요소로 간주
이전값들은 메모리 상에 그대로 존재하지만 덱의 동작에서는 무시됨 "사라진것처럼 동작"
문제 3.
덱이 비었음을 알릴때 return -1을 하면 문제가 생김
덱에 들어있는 -1 을 back하면 덱이 비지않아도 -1을 return 함
해결:
방법1 ) stl::deque 사용시 내부적으로 처리해줌
방법2) int 대신 bool 반환
수정 코드
#include <iostream>
using namespace std;
const int MX = 10;
int deque[2 * MX + 1];
int head = MX, tail = MX;
bool isEmpty();
void push_front(int x){
if (head > 0) {
deque[--head] = x;
}
else {
cout << "front에서 오버플로우\n";
}
}
void push_back(int x){
if (tail < 2 * MX + 1) {
deque[tail++] = x;
}
else {
cout << "back에서 오버플로우\n";
}
}
void pop_front(){
if (head < tail) {
head++;
}
else {
cout << "덱이 비어있습니다.\n";
}
}
void pop_back(){
if (head < tail) {
tail--;
}
else {
cout << "덱이 비어있습니다.\n";
}
}
int front(){
return deque[head];
}
int back(){
return deque[tail - 1];
}
bool isEmpty(){
return head == tail;
}
int size(){
return tail - head;
}
void clear(){
head = tail = MX;
}
void test(){
push_front(1); // 덱: [1]
push_back(4); // 덱: [1, 4]
push_front(2); // 덱: [2, 1, 4]
push_back(3); // 덱: [2, 1, 4, 3]
cout << "Size: " << size() << endl; // 기대 출력: 4
cout << front() << endl; // 기대 출력: 2
cout << back() << endl; // 기대 출력: 3
pop_front(); // 덱: [1, 4, 3]
pop_back(); // 덱: [1, 4]
cout << "Size after pop: " << size() << endl; // 기대 출력: 2
cout << front() << endl; // 기대 출력: 1
cout << back() << endl; // 기대 출력: 4
clear();
if (!(isEmpty()))
clear();
else
cout << "덱이 비었습니다\n";
}
int main() {
test();
return 0;
}
stl::queue 를 사용한 예제
#include <iostream>
#include <deque>
using namespace std;
int main() {
deque<int> dq;
dq.push_front(3);
dq.push_front(2);
dq.push_front(4);
dq.push_front(13);
cout << "Front: " << dq.front() << "\n";
cout << "Back: " << dq.back() << "\n";
dq.pop_front();
dq.pop_back();
cout << "Front: " << dq.front() << "\n";
cout << "Back: " << dq.back() << "\n";
}
stl 덱의 장점: 가장 빠르고 쉽게 구현이 가능하다. 동적으로 크기조절이 가능하다. 언더플로우, 오버플로우를 내부적으로 처리해준다. 앞 뒤에서 O(1)의 시간복잡도로 삽입,삭제가 가능하다.
'원티드_언리얼RPG 2기 > 자료구조& 알고리즘' 카테고리의 다른 글
<연결리스트> 백준 1406 에디터 (0) | 2025.03.06 |
---|---|
<배열,연결리스트> 백준 1158번 요세푸스 문제 (0) | 2025.03.04 |
2주차 배열, 벡터, 연결리스트 (0) | 2025.03.03 |
<덱deque> 백준 1021번 회전하는 큐 (0) | 2025.03.01 |
<스택> 백준 3986번 좋은 단어 (0) | 2025.03.01 |