void push_front(const T& _Data);
template<typename T>
void List<T>::push_front(const T& _Data)
{
Node<T>* pNewNode = new Node<T>(_Data, m_pHead, nullptr);
if (nullptr != m_pHead)
{
m_pHead->pPrev = pNewNode;
}
else
{
m_pTail = pNewNode;
}
m_pHead = pNewNode;
++m_CurCount;
}
push_front
메소드는 템플릿 타입 T
의 상수 참조를 인자로 받습니다. 이는 리스트에 추가될 데이터를 나타냅니다.
새 노드 (pNewNode
)는 동적 메모리 할당을 사용하여 생성됩니다. 새 노드는 데이터 (_Data
)로 초기화되며, 다음 포인터 (pNext
)는 현재 리스트의 헤드 (m_pHead
)를 가리키도록 설정됩니다. 이전 포인터 (pPrev
)는 nullptr
로 초기화되는데, 이것은 새로운 첫 번째 노드가 될 것이기 때문입니다.
리스트가 비어있지 않은 경우 (m_pHead
가 nullptr
이 아닌 경우)를 확인합니다. 리스트가 비어있지 않다면:
m_pHead->pPrev
)를 새 노드 (pNewNode
)를 가리키도록 업데이트합니다.리스트가 비어있다면 (m_pHead
가 nullptr
인 경우), 새 노드는 리스트의 꼬리 (m_pTail
)가 됩니다 (m_pTail = pNewNode
).
리스트의 헤드를 새 노드로 업데이트합니다 (m_pHead = pNewNode
).
리스트의 크기 (m_CurCount
)를 증가시켜 새 노드의 추가를 반영합니다.
stdcharlist.push_back(CharInfo(L"Warrior", 100, 30, 50));
stdcharlist.push_back(CharInfo(L"Archer", 80, 50, 40));
stdcharlist.push_back(CharInfo(L"Wizzard", 50, 100, 20));
list<CharInfo>::iterator listiter = stdcharlist.begin();
void List<T>::push_back(const T& _Data)
list<CharInfo>::iterator listiter = stdcharlist.begin();
(*listiter) // 1
list<CharInfo>::iterator listiter = stdcharlist.begin();
++listiter;
++listiter;
list<CharInfo>::iterator listiter;
for (listiter = stdcharlist.begin(); listiter != stdcharlist.end(); ++listiter)
{
std::wcout << (*listiter).szName << std::endl;
}
std::vector<CharInfo> vecInfo;
for (size_t i = 0; i < vecInfo.size(); ++i)
{
std::wcout << (*listiter).szName << std::endl;
}
listiter = stdcharlist.begin();
++listiter; // 1
stdcharlist.insert(listiter, CharInfo(L"Berserker", 80, 10, 80));
const CharInfo& info = (*listiter);
listiter = stdcharlist.insert(listiter, CharInfo(L"Berserker", 80, 10, 80));
const CharInfo& info = (*listiter);
listiter = stdcharlist.begin();
++listiter;
++listiter;
stdcharlist.erase(listiter);
const CharInfo& charinfo = *listiter;
listiter = stdcharlist.erase(listiter);
const CharInfo& charinfo = *listiter;
vector<int> vecInt;
for (int i = 0; i < 100; ++i)
{
vecInt.push_back(i + 1);
}
vector<int>::iterator veciter = vecInt.begin();
for (; veciter != vecInt.end(); ++veciter)
{
if ((*veciter) <= 50) // 1
{
// vecInt.erase(veciter); // 2
// 돌렸을떄 사진
veciter = vecInt.erase(veciter); // 3
}
for (; veciter != vecInt.end(); /*++veciter*/)
{
// 3.5
if ((*veciter) <= 50)
{
veciter = vecInt.erase(veciter);
}
else
{
++veciter;
}
public:
class iterator
{
private:
List<T>* m_Owner; // 1
Node<T>* m_TargetNode; // 2
};
class iterator; // 1
iterator begin()
{
//iterator iter(this, m_pHead); // 2
//return iter // 3
return iterator(this, m_pHead); // 4
}
iterator end()
{
return iterator(this, nullptr); // 5
}
public:
T& operator *() // 1
{
// assert(m_Owner); // 2
// assert(m_TargetNode); // 3
assert(!(!m_Owner || !m_TargetNode)); // 4
// assert( m_Owner && m_TargetNode ); // 5
return m_TargetNode->Data;
}
void operator ++()
{
assert(m_Owner && m_TargetNode); // 1
m_TargetNode = m_TargetNode->pNext; // 2
}
void operator --()
{
assert(m_Owner && m_TargetNode); // 1
m_Owner->m_pHead == m_TargetNode // 2
{
assert(nullptr);
}
m_TargetNode = m_TargetNode->pPrev; // 3
}
assert(m_Owner->m_pHead != m_TargetNode);
bool operator == (const iterator& _otheriter)
{
if (m_Owner == _otheriter.m_Owner && m_TargetNode == _otheriter.m_TargetNode)
return true;
else
return false;
}
bool operator != (const iterator& _otheriter)
{
return !((*this) == _otheriter); // 1
}
#include <iostream>
#include <vector>
using std::vector;
#include <list>
using std::list;
#include "List.h"
struct CharInfo
{
wchar_t szName[20];
int HP;
int MP;
int SP;
int MaxHP;
int MaxMP;
int MaxSP;
public:
void SetInfo(const wchar_t* _strName, int _HP, int _MP, int _SP)
{
wcscpy_s(szName, _strName);
HP = MaxHP = _HP;
MP = MaxMP = _MP;
SP = MaxSP = _SP;
}
CharInfo()
: HP(0), MP(0), SP(0)
, MaxHP(0), MaxMP(0), MaxSP(0)
{}
CharInfo(const wchar_t* _strName, int _HP, int _MP, int _SP)
: HP(0), MP(0), SP(0)
, MaxHP(0), MaxMP(0), MaxSP(0)
{
SetInfo(_strName, _HP, _MP, _SP);
}
~CharInfo()
{}
};
List<CharInfo> charlist;
list<CharInfo> stdcharlist;
int main()
{
//CharInfo(L"Warrior", 100, 30, 50) - 임시객체, 이름없는 지역변수
charlist.push_back(CharInfo(L"Warrior", 100, 30, 50));
charlist.push_back(CharInfo(L"Archer", 80, 50, 40));
charlist.push_back(CharInfo(L"Wizzard", 50, 100, 20));
stdcharlist.push_back(CharInfo(L"Warrior", 100, 30, 50));
stdcharlist.push_back(CharInfo(L"Archer", 80, 50, 40));
stdcharlist.push_back(CharInfo(L"Wizzard", 50, 100, 20));
list<CharInfo>::iterator listiter;
listiter = stdcharlist.begin();
--listiter;
for (listiter = stdcharlist.begin(); listiter != stdcharlist.end(); ++listiter)
{
std::wcout << (*listiter).szName << std::endl;
}
listiter = stdcharlist.begin();
++listiter;
// list 의 insert 함수 테스트
stdcharlist.insert(listiter, CharInfo(L"Berserker", 80, 10, 80));
const CharInfo& info = (*listiter);
// list 의 erase 함수 테스트
// Warrior - Berserker - (Archer) - Wizzard
listiter = stdcharlist.begin();
++listiter;
++listiter;
listiter = stdcharlist.erase(listiter);
const CharInfo& charinfo = *listiter;
// erase 문제
vector<int> vecInt;
for (int i = 0; i < 100; ++i)
{
// 1 ~ 100 까지 입력
vecInt.push_back(i + 1);
}
// erase 사용하는 경우 iterator 가 문제가 되지 않게, 삭제된 다음 iterator 를 돌려받는 구조
// 따라서 반복문에서 iterator 를 매번 ++ 하는 경우 erase 함수와 중복되어서
// 가리키는 요소를 두번 증가하게 될 수 있다.
vector<int>::iterator veciter = vecInt.begin();
for (; veciter != vecInt.end();)
{
if ((*veciter) <= 50)
{
veciter = vecInt.erase(veciter);
}
else
{
++veciter;
}
}
return 0;
}
#pragma once
#include <assert.h>
template<typename T>
struct Node
{
T Data;
Node<T>* pNext;
Node<T>* pPrev;
Node()
: Data()
, pNext(nullptr)
, pPrev(nullptr)
{}
Node(const T& _Data, Node<T>* _Next, Node<T>* _Prev)
: Data(_Data)
, pNext(_Next)
, pPrev(_Prev)
{}
};
template<typename T>
class List
{
private:
Node<T>* m_pHead;
Node<T>* m_pTail;
int m_CurCount;
public:
void push_back(const T& _Data);
void push_front(const T& _Data);
class iterator;
iterator begin() { return iterator(this, m_pHead); }
iterator end() { return iterator(this, nullptr); }
// _targetIter 가 가리키는곳에 _Data 를 저장시키고, 새로 저장한 데이터를 가리키는 iterator 를 반환해준다.
// iterator insert(iterator _targetIter, const T& _Data);
// _targetIter 가 가리키는 데이터를 삭제하고, 삭제한 다음을 가리키는 iterator 를 반환
// iterator erase(iterator _targetIter);
public:
List()
: m_pHead(nullptr)
, m_pTail(nullptr)
, m_CurCount(0)
{}
~List()
{
Node<T>* pNode = m_pHead;
while (pNode)
{
Node<T>* pNext = pNode->pNext;
delete pNode;
pNode = pNext;
}
}
public:
class iterator
{
private:
List<T>* m_Owner;
Node<T>* m_TargetNode;
public:
T& operator *()
{
// Owner(List) 가 설정되어있지 않으면, 정상적인 iterator 가 아니다.
// Owner 가 설정되어 있어도, m_TargetNode 가 nullptr 이면 End Iterator 이기 때문에
// 마지막의 다음을 가리키는 상태의 iterator 에게 * 로 접근기능을 쓰면 에러
assert(m_Owner && m_TargetNode);
return m_TargetNode->Data;
}
// 1. ++, -- 반환타입 문제
// 2. ++, -- 후위연산자 문제
void operator ++()
{
// enditerator 에서 ++ 하는 경우
assert(m_Owner && m_TargetNode);
m_TargetNode = m_TargetNode->pNext;
}
void operator --()
{
assert(m_Owner && m_TargetNode);
assert(m_Owner->m_pHead != m_TargetNode); // iterator 가 begin 이다.
m_TargetNode = m_TargetNode->pPrev;
}
bool operator == (const iterator& _otheriter)
{
if (m_Owner == _otheriter.m_Owner && m_TargetNode == _otheriter.m_TargetNode)
return true;
else
return false;
}
bool operator != (const iterator& _otheriter)
{
return !((*this) == _otheriter);
}
public:
iterator()
: m_Owner(nullptr)
, m_TargetNode(nullptr)
{}
iterator(List<T>* _Owner, Node<T>* _TargetNode)
: m_Owner(_Owner)
, m_TargetNode(_TargetNode)
{}
~iterator()
{}
};
};
template<typename T>
void List<T>::push_back(const T& _Data)
{
Node<T>* pNewNode = new Node<T>(_Data, nullptr, nullptr);
if (0 == m_CurCount) //nullptr == m_pHead)
{
m_pHead = pNewNode;
m_pTail = pNewNode;
}
else
{
m_pTail->pNext = pNewNode;
pNewNode->pPrev = m_pTail;
m_pTail = pNewNode;
}
++m_CurCount;
}
template<typename T>
inline void List<T>::push_front(const T& _Data)
{
Node<T>* pNewNode = new Node<T>(_Data, m_pHead, nullptr);
if (nullptr != m_pHead)
{
m_pHead->pPrev = pNewNode;
}
else
{
m_pTail = pNewNode;
}
m_pHead = pNewNode;
++m_CurCount;
}
1차 23.12.29
2차 24.01.02
3차 24.01.03
4차 24.01.04
5차 24.01.05