https://cplusplus.com/reference/stack/stack/
https://cplusplus.com/reference/stack/stack/
container_typeThe second template parameter (Container)Type of the underlying container
cplusplus.com
기능>
1. 생성자 : 기본 생성자만 추가
2. empty() : 현재 스택이 비어있는지 체크하여 Bool 타입 반환
3. size() : 현재 스택에 저장된 데이터의 갯수 Integer 타입 반환
4. top() : 가장 최근에 넣은 데이터 반환 (수정 가능)
5. push() : 스택에 데이터 추가
6. pop() : 스택에서 가장 최근 추가한 데이터 삭제
7. swap() : 서로 다른 스택끼리 저장된 데이터 관리 자료구조 교환 (길이가 달라도 상관 없음)
스택 컨테이너의 멤버 함수를 직접 구현해보자.
01) 데이터를 배열로 관리
[StackByArray.h 소스코드]
#pragma once
template <class T>
class StackByArray
{
public:
StackByArray()
{
length = 0;
capacity = 2;
pArr = new T[capacity];
}
~StackByArray()
{
delete[] pArr;
pArr = nullptr;
}
public:
bool empty()
{
return length == 0;
}
T& top()
{
if (length == 0)
{
printErrMsg("Stack empty!");
pArr[length] = -1;
}
return pArr[length];
}
int size()
{
return length;
}
void push(const T value)
{
if (length == capacity-1)
{
T* pNewArr = new T[capacity * 2];
for (int i = 1; i < capacity; ++i)
{
pNewArr[i] = pArr[i];
}
delete pArr;
pArr = pNewArr;
capacity *= 2;
}
pArr[++length] = value;
return;
}
void pop()
{
if (length == 0)
{
printErrMsg("Stack empty!");
}
else
{
--length;
}
return;
}
void emplace(const T value)
{
if (length == capacity - 1)
{
T* pNewArr = new T[capacity * 2];
for (int i = 1; i < capacity; ++i)
{
pNewArr[i] = pArr[i];
}
delete[] pArr;
pArr = pNewArr;
capacity *= 2;
}
pArr[++length] = value;
return;
}
void swap(StackByArray<T>& target)
{
T* tmp = pArr;
int tmpLength = length;
int tmpCapacity = capacity;
pArr = target.pArr;
length = target.length;
capacity = target.capacity;
target.pArr = tmp;
target.length = tmpLength;
target.capacity = tmpCapacity;
return;
}
void printErrMsg(const char* msg)
{
std::cout << "ERROR: " << msg << '\n';
return;
}
private:
T* pArr;
int length;
int capacity;
};
02) 데이터를 더블 링크드 리스트로 관리
[StackByDoubleLinkedList.h 소스코드]
#pragma once
#include <iostream>
template <typename T>
struct Node
{
T value;
Node<T>* pPrev;
Node<T>* pNext;
};
template <class T>
class StackByDoubleLinkedList
{
public:
StackByDoubleLinkedList()
{
pHeader = new Node<T>();
pTail = new Node<T>();
pHeader->pNext = pTail;
pHeader->pPrev = nullptr;
pTail->pNext = nullptr;
pTail->pPrev = pHeader;
length = 0;
}
~StackByDoubleLinkedList()
{
Node<T>* pNode = pHeader;
while (pNode != nullptr)
{
Node<T>* delNode = pNode;
pNode = pNode->pNext;
delete delNode;
}
}
public:
bool empty()
{
return length == 0;
}
T& top()
{
Node<T>* top = pTail->pPrev;
if (top == nullptr)
{
printErrMsg("Stack empty!");
return pTail->value;
}
else
{
return top->value;
}
}
int size()
{
return length;
}
void push(const T value)
{
Node<T>* top = pTail->pPrev;
Node<T>* newTop = new Node<T>();
newTop->value = value;
top->pNext = newTop;
newTop->pPrev = top;
newTop->pNext = pTail;
pTail->pPrev = newTop;
++length;
return;
}
void pop()
{
if (length == 0)
{
printErrMsg("Stack empty!");
}
else
{
Node<T>* oldTop = pTail->pPrev;
Node<T>* newTop = oldTop->pPrev;
newTop->pNext = pTail;
pTail->pPrev = newTop;
delete oldTop;
--length;
}
return;
}
void emplace(const T value)
{
Node<T>* top = pTail->pPrev;
Node<T>* newTop = new Node<T>();
newTop->value = value;
top->pNext = newTop;
newTop->pPrev = top;
newTop->pNext = pTail;
pTail->pPrev = newTop;
++length;
return;
}
void swap(const StackByDoubleLinkedList<T>& target)
{
Node<T>* tmp;
Node<T>* h1 = this->pHeader;
Node<T>* h2 = target.pHeader;
tmp = h1->pNext;
h1->pNext = h2->pNext;
h2->pNext = tmp;
h1->pNext->pPrev = h2;
h2->pNext->pPrev = h1;
Node<T>* t1 = this->pTail;
Node<T>* t2 = target.pTail;
tmp = t1->pPrev;
t1->pPrev = t2->pPrev;
t2->pPrev = tmp;
t1->pPrev->pNext = t2;
t2->pPrev->pNext = t1;
return;
}
void printErrMsg(const char* msg)
{
std::cout << "Error: " << msg << '\n';
return;
}
private:
Node<T>* pHeader;
Node<T>* pTail;
int length;
};
[Main.cpp 소스코드]
#include "StackByDoubleLinkedList.h"
#include "StackByArray.h"
int main(int argc, char* argv[])
{
StackByArray<int> mystack1, mystack2;
mystack1.push(10);
mystack1.push(20);
mystack1.push(30);
mystack1.push(40);
mystack1.push(50);
std::cout << "stack size: " << mystack1.size() << '\n';
std::cout << "stack top: " << mystack1.top() << '\n';
mystack1.top() = 99999;
std::cout << "mystack1 top: " << mystack1.top() << '\n';
mystack2.emplace(100);
mystack2.emplace(200);
mystack2.emplace(300);
mystack2.emplace(400);
mystack2.emplace(500);
std::cout << "stack size: " << mystack2.size() << '\n';
std::cout << "mystack2 top: " << mystack2.top() << '\n';
// swap
mystack1.swap(mystack2);
std::cout << "swap>mystack1 top: " << mystack1.top() << '\n';
std::cout << "swap>mystack2 top: " << mystack2.top() << '\n';
return 0;
}
[실행화면]
[개선점]
1) emplace()와 push() 함수의 기능이 동일하나 문서를 참조해보면 다르다.
2) stack 컨테이너의 문서와 소스코드를 보면 기본 컨테이너라는 개념이 있고,
컨테이너의 기본적인 기능을 제공하며, 확장에 용이하게 설계되어 있다.
위 사항에 따라 기본 컨테이너를 추가하고
템플릿 프로그래밍을 더 잘 활용하면, 좀더 유연한 스택 자료구조를 구현해 볼 수 있다.
'자료구조' 카테고리의 다른 글
Queue 막 구현하기 (0) | 2023.08.10 |
---|