C++기초
220412_자료구조_리스트형 스택(Stack) 구현 및 실행
hyrule
2022. 4. 18. 14:45
//Stack.h
#pragma once
#include <assert.h>
/*
* FILO(선입 후출): 먼저 들어온 데이터가 나중에 나간다.
-> 물건을 통에 차곡차곡 담는다고 생각하면 될듯.
꺼낼때는 당연히 맨 위의 물건부터 꺼내야 한다.
메모리의 스택도 비슷한 느낌이다.
메모리 전체가 통으로 있으면, 메모리의 뒤쪽 부분에 스택 영역을 할당한다.
* 활용처
- 데이터 뒤집기: 그냥 스택에 데이터를 넣었다 빼면 데이터가 뒤집어지므로
- 길찾기 알고리즘
* 구현 방법
- 동적 배열
- 리스트: 싱글 링크드 리스트면 충분하다.
반대로 갈 이유가 전혀없음 -> 맨 마지막 데이터에서부터 순서대로 접근할것이므로
* 이런 것들을 구현할 줄 알아야 하는 이유
- 나중에 멀티스레드를 활용하는 단계에서는,
C++의 경우 STL을 사용하면 안정성을 보장할 수 없다...
- 그러므로 나중에는 직접 안정성을 보장할 수 있게 코드를 수정해서 사용해야 한다.
*/
/*
CF)함수에 인자를 T&(레퍼런스)형으로 주는 이유
- 함수에 포인터 타입으로 인자를 주면 스택에 새 공간을 임시로 할당하여
인자 주소의 값을 복사해온다 -> 이 과정에서 시간이 추가로 소요된다.
- 하지만 레퍼런스 타입으로 받아오면 이런 과정 없이 참조만 해서
데이터를 활용하므로 시간이 단축된다.
- 앞에 const를 붙여놓는 이유는 const를 붙이면 인자로 들어온 값을
변경할 수 없게 되기 때문이다.
*/
template <typename T>
class CStackNode
{
template <typename T>
friend class CStack;
private:
CStackNode():
m_Next(nullptr)
{
}
~CStackNode()
{
}
private:
T m_Data;
CStackNode<T>* m_Next;
};
template <typename T>
class CStack
{
public:
CStack()
{
m_Last = nullptr;
m_Size = 0;
}
~CStack()
{
//스택을 싹 지워버리는 반복문.
NODE* Node = m_Last;
while (Node)
{
NODE* Next = m_Last->m_Next;
delete Node;
Node = Next;
}
}
private:
typedef CStackNode<T> NODE;
//가장 마지막 주소부터 뺄 것이므로 마지막 노드의 주소를 가지고 있을 변수가 필요.
NODE* m_Last;
int m_Size;
//스택을 다 비웠는지 체크 = null 노드를 통해 확인.
public:
void push(const T& Data)
{
//1. 새 노드 생성해주고
NODE* Node = new NODE;
//2. 데이터 넣어주고
Node->m_Data = Data;
//3. 이전의 마지막 노드와 연결해 주고
Node->m_Next = m_Last;
//4. m_Last의 주소를 갱신
m_Last = Node;
//5.마지막으로 스택의 사이즈를 저장
++m_Size;
}
T& Top()
{
//예외처리
if (empty())
assert(false);
return m_Last->m_Data;
}
void pop()
{
//예외처리
if (empty())
{
assert(false);
}
//지울 노드를 임시로 저장해놓고 주소 변경 작업
NODE* Temp = m_Last;
//마지막 노드 주소 변경
m_Last = Temp->m_Next;
//노드 제거
delete Temp;
//사이즈 감소
--m_Size;
}
int size() const
{
return m_Size;
}
bool empty() const
{
return 0 == m_Size;
}
};
//main.cpp
#include <iostream>
#include "Stack.h"
int main()
{
std::cout << "====== 리스트형 스택 확인 =====" << std::endl;
CStack<int> stack;
for (int i = 0; i < 10; ++i)
{
stack.push(i);
}
while (!stack.empty())
{
std::cout << stack.Top() << std::endl;
stack.pop();
}
std::cout << "남은 Size: " << stack.size() << std::endl;
return 0;
}