iterator& operator ++()
{
if (m_pOwner && -1 == m_Idx)
{
assert(nullptr); // 1
}
++m_Idx;
if (m_pOwner->m_CurCount <= m_Idx) // 2
{
m_Idx = -1;
}
return (*this);
}
iterator operator ++(int)
{
iterator copyiter = (*this);
++(*this);
return copyiter;
}
iterator& operator --()
{
assert(m_pOwner && m_Idx); // 1
if (-1 == m_Idx) // 2
{
assert(m_pOwner->m_CurCount); // 3
// 가장 마지막 데이터를 가리킨다.
m_Idx = m_pOwner->m_CurCount - 1; // 4
}
else
{
--m_Idx; // 5
}
return (*this);
}
iterator operator --(int)
{
iterator copyiter = *this;
--(*this);
return copyiter;
}
bool operator ==(const iterator& _otheriter)
{
if (m_Owner == _otheriter.m_Owner && m_TargetNode == _otheriter.m_TargetNode)
{
return true;
}
return false;
}
bool operator !=(const iterator& _otheriter)
{
return !((*this) == _otheriter);
}
iterator end()
{
return iterator(this, nullptr);
}
for (; myiter != bst.end(); ++myiter)
{
cout << (*myiter).first << endl;
// 클래스 iterator에 구현되있다.
const BSTPair<T1, T2>& operator* ()
{
assert(m_Owner && m_TargetNode);
return m_TargetNode->pair;
}
근데 우리 이진탐색트리는 기존의 동적 배열이랑 리스트랑 다르게 템플릿형식으로 짝지어서 2개 받았다(pair)
iterator 입장에서도 *(별)을 붙이면 다른 iterator랑 다르게 pair형태로 반환을 해줘야한다.
반환타입을 그래서 BSTPair<T1, T2>로 주고 원본자체를 받을거니까 &(레퍼런스)로 했다.
const로 수정을 못하게한 이유
// 100(xx) 30
// 50 150
// 25 75 125 170
복사된 비용을 레퍼런스로 최적화 시키고 const로 막아서 원본 수정못하게 한다.
assert는 end iterator이거나 m_Owner가 nullptr일떄 *(별)을 호출하면 말 안되니까 둘중하나라도 0이면 assert를 걸었다.
구현을 했기 때문에 위의 오류가 해결된다.
iterator& operator ++()
{
if (m_TargetNode->HasRightChild())
{
BSTNode<T1, T2>* pNextNode = m_TargetNode->pRightChild;
while (pNextNode->pLeftChild) { pNextNode = pNextNode->pLeftChild; }
m_TargetNode = pNextNode;
}
// 오른쪽 자식이 없으면
else
{
BSTNode<T1, T2>* pNextNode = m_TargetNode;
// 1.1
// 부모의 왼쪽 자식일때 까지 올라가서 그때 부모가 나의 중위 후속자
while (true)
{
// 루트 노드라면 if문 나가기.
// 본인이 이미 루트 노드라면 나는 end iterator였다.
if (pNextNode->IsRoot())
{
// 현재 노드가 가장 마지막 노드이다(중위 후속자를 찾기전에 루트노드에 도달)
// end iterator
m_TargetNode = nullptr;
return (*this);
}
// 올라갈수잇는 상황이고 본인이 왼쪽 자식인지 확인하고 내가 왼쪽이네 그러면 중위후속자다.
else if(pNextNode->IsLeftChild())
{
m_TargetNode = pNextNode->pParent;
break;
}
// 그것도 아니라면 왼쪽까지 계속 올라가서 올라간다.
else
{
pNextNode = pNextNode->pParent;
}
}
m_TargetNode = pNextNode->pParent;
}
return (*this);
}
// BST 클래스 안에 있다.
iterator find(const T1& _key);
template<typename T1, typename T2>
typename BST<T1, T2>::iterator BST<T1, T2>::find(const T1& _key)
{
BSTNode<T1, T2>* pNode = m_Root;
while (pNode)
{
if (_key < pNode->pair.first)
{
pNode = pNode->pLeftChild;
}
else if (pNode->pair.first < _key)
{
pNode = pNode->pRightChild;
}
else
{
break;
}
}
return iterator(this, pNode);
}
m_Root->pair.first;
_key;
BSTNode<T1, T2>* pNode = m_Root;
if (nullptr == pNode)
{
return end();
}
if (_key < pNode->pair.first)
{
pNode = pNode->pLeftChild;
}
else if (pNode->pair.first < _key)
{
pNode = pNode->pRightChild;
}
while(true)
{
if (nullptr == pNode)
{
return end();
}
else if (_key < pNode->pair.first)
{
pNode = pNode->pLeftChild;
}
else if (pNode->pair.first < _key)
{
pNode = pNode->pRightChild;
}
}
return iterator();
else
{
return iterator(this, pNode)
}
while(true)
{
if (nullptr == pNode)
{
return end();
}
else if (_key < pNode->pair.first)
{
pNode = pNode->pLeftChild;
}
else if (pNode->pair.first < _key)
{
pNode = pNode->pRightChild;
}
else
{
return iterator(this, pNode)
}
}
return iterator();
while (pNode)
{
if (_key < pNode->pair.first)
{
pNode = pNode->pLeftChild;
}
else if (pNode->pair.first < _key)
{
pNode = pNode->pRightChild;
}
else
{
break;
}
}
return iterator(this, pNode);
myiter = bst.find(75);
myiter = bst.find(74);
// iterator 안에 있다.
private:
BST* m_Owner;
BSTNode<T1, T2>* m_TargetNode;
wchar_t m_szDesc[6]; // 1
public:
iterator()
: m_Owner(nullptr)
, m_TargetNode(nullptr)
, m_szDesc{}
{
wcscpy_s(m_szDesc, L"None");
}
iterator(BST* _Owner, BSTNode<T1, T2>* _Node)
: m_Owner(_Owner)
, m_TargetNode(_Node)
, m_szDesc{}
{
if (nullptr != m_Owner && nullptr == m_TargetNode)
{
wcscpy_s(m_szDesc, L"End");
}
}
// BST 클래스 public내부에 선언
iterator erase(const iterator& _target);
friend class BST<T1, T2>;
// struct BSTNode 안에 있다.
// 1
bool IsLeaf() { return !(pLeftChild || pRightChild); }
// 2
bool IsFull() { return pLeftChild&& pRightChild; }
template<typename T1, typename T2>
typename BST<T1, T2>::iterator BST<T1, T2>::erase(const iterator& _target)
{
// 삭제할 노드가 리푸노드인 경우 (자식이 0개)
if (_target.m_TargetNode->IsLeaf())
{
}
// 자식이 2개 있는 경우
else if (_target.m_TargetNode->IsFull())
{
}
// 자식이 1개 있는 경우
else
{
}
return iterator();
}
#include <iostream>
using std::cout;
using std::endl;
#include "BST.h"
#include <set>
#include <map>
using std::set;
using std::map;
using std::make_pair;
int main()
{
set<int> intset;
intset.insert(100);
intset.insert(150);
intset.insert(170);
intset.insert(125);
intset.insert(80);
intset.insert(90);
intset.insert(50);
set<int>::iterator iter = intset.find(125);
iter = intset.find(124);
if (iter != intset.end())
{
}
else
{
}
// map 사용
map<int, int> intmap;
intmap.insert(make_pair(100, 1));
intmap.insert(make_pair(150, 2));
intmap.insert(make_pair(170, 3));
intmap.insert(make_pair(125, 4));
intmap.insert(make_pair(80, 5));
intmap.insert(make_pair(90, 6));
intmap.insert(make_pair(50, 7));
map<int, int>::iterator mapiter = intmap.find(50);
if (mapiter != intmap.end())
{
(*mapiter).first;
(*mapiter).second;
}
BST<int, float> bst;
bst.insert(make_bstpair(100, 1.1f));
bst.insert(make_bstpair(150, 2.2f));
bst.insert(make_bstpair(50, 2.2f));
bst.insert(make_bstpair(170, 1.1f));
bst.insert(make_bstpair(125, 2.2f));
bst.insert(make_bstpair(25, 2.2f));
bst.insert(make_bstpair(75, 2.2f));
bst.Circit();
BST<int, float>::iterator myiter = bst.begin();
for (; myiter != bst.end(); ++myiter)
{
cout << (*myiter).first << endl;
}
myiter = bst.find(74);
BST<int, float>::iterator TestIter;
return 0;
}
#pragma once
#include <iostream>
#include <assert.h>
#include "List.h"
// Binary Search Tree(BST)
template<typename T1, typename T2>
struct BSTPair
{
T1 first;
T2 second;
BSTPair()
{}
BSTPair(const T1& _first, const T2& _second)
: first(_first)
, second(_second)
{
}
};
template<typename T1, typename T2>
struct BSTNode
{
BSTPair<T1, T2> pair;
BSTNode* pParent;
BSTNode* pLeftChild;
BSTNode* pRightChild;
bool HasRightChild() { return pRightChild; }
bool HasLeftChild() { return pLeftChild; }
bool IsLeftChild() { return pParent->pLeftChild == this; }
bool IsRightChild() { return pParent->pRightChild == this; }
bool IsRoot() { return !pParent; }
bool IsLeaf() { return !(pLeftChild || pRightChild); }
bool IsFull() { return pLeftChild && pRightChild; }
BSTNode()
: pParent(nullptr)
, pLeftChild(nullptr)
, pRightChild(nullptr)
{}
BSTNode(const BSTPair<T1, T2>& _pair, BSTNode* _Parent = nullptr, BSTNode* _LeftChild = nullptr, BSTNode* _RightChild = nullptr)
: pair(_pair)
, pParent(_Parent)
, pLeftChild(_LeftChild)
, pRightChild(_RightChild)
{}
};
template<typename T1, typename T2>
class BST
{
private:
BSTNode<T1, T2>* m_Root; // 루트 노드 주소
int m_CurCount; // 현재 데이터 개수
public:
void Circit()
{
Circit(m_Root);
}
private:
void Circit(BSTNode<T1, T2>* _Node);
public:
class iterator;
void insert(const BSTPair<T1, T2>& _pair);
iterator find(const T1& _key);
iterator erase(const iterator& _target);
iterator begin()
{
assert(m_Root);
BSTNode<T1, T2>* pNode = m_Root;
while (pNode->pLeftChild) { pNode = pNode->pLeftChild; }
return iterator(this, pNode);
}
iterator end()
{
return iterator(this, nullptr);
}
public:
BST()
: m_Root(nullptr)
, m_CurCount(0)
{}
~BST()
{
// 모든 노드들을 삭제
// 재귀함수
// 레벨순회
List<BSTNode<T1, T2>*> queue;
queue.push_back(m_Root);
while (!queue.empty())
{
BSTNode<T1, T2>* pNode = queue.pop_front();
if (nullptr != pNode->pLeftChild)
queue.push_back(pNode->pLeftChild);
if (nullptr != pNode->pRightChild)
queue.push_back(pNode->pRightChild);
delete pNode;
}
}
class iterator
{
private:
BST* m_Owner;
BSTNode<T1, T2>* m_TargetNode;
wchar_t m_szDesc[6]; // 설명 정보
// end iterator 조건
// m_Owner 가 nullptr 이 아니고 m_TargetNode 가 nullptr 이면...
public:
const BSTPair<T1, T2>& operator* ()
{
assert(m_Owner && m_TargetNode);
return m_TargetNode->pair;
}
bool operator == (const iterator& _otheriter)
{
if (m_Owner == _otheriter.m_Owner && m_TargetNode == _otheriter.m_TargetNode)
{
return true;
}
return false;
}
bool operator != (const iterator& _otheriter)
{
return !((*this) == _otheriter);
}
iterator& operator ++()
{
// 중위 후속자(InOrder Successor)
// 오른쪽 자식이 있으면
if (m_TargetNode->HasRightChild())
{
// 오른쪽 자식으로 간다.
BSTNode<T1, T2>* pNextNode = m_TargetNode->pRightChild;
// 왼쪽자식이 없을 때 까지 내려간다.
while (pNextNode->pLeftChild) { pNextNode = pNextNode->pLeftChild; }
m_TargetNode = pNextNode;
}
// 오른쪽 자식이 없으면
else
{
BSTNode<T1, T2>* pNextNode = m_TargetNode;
// 부모의 왼쪽 자식일때 까지 올라가서 그때 부모가 나의 중위 후속자
while (true)
{
if (pNextNode->IsRoot())
{
// 현재 노드가 가장 마지막 노드이다(중위 후속자를 찾기전에 루트노드에 도달)
// end iterator
m_TargetNode = nullptr;
wcscpy_s(m_szDesc, L"End");
return (*this);
}
else if (pNextNode->IsLeftChild())
{
m_TargetNode = pNextNode->pParent;
break;
}
else
{
pNextNode = pNextNode->pParent;
}
};
}
return (*this);
}
iterator& operator--()
{
// 중위 선행자(InOrder Predecessor)
return (*this);
}
public:
iterator()
: m_Owner(nullptr)
, m_TargetNode(nullptr)
, m_szDesc{}
{
wcscpy_s(m_szDesc, L"None");
}
iterator(BST* _Owner, BSTNode<T1, T2>* _Node)
: m_Owner(_Owner)
, m_TargetNode(_Node)
, m_szDesc{}
{
if (nullptr != m_Owner && nullptr == m_TargetNode)
{
wcscpy_s(m_szDesc, L"End");
}
}
friend class BST<T1, T2>;
};
};
// 입력된 T1, T2 타입의 데이터를 묶어서 BSTPair<T1, T2> 타입 구조체로 반환
template<typename T1, typename T2>
BSTPair<T1, T2> make_bstpair(const T1& _first, const T2& _second)
{
return BSTPair<T1, T2>(_first, _second);
}
template<typename T1, typename T2>
void BST<T1, T2>::insert(const BSTPair<T1, T2>& _pair)
{
BSTNode<T1, T2>* pNewNode = new BSTNode<T1, T2>(_pair);
// 최초로 데이터가 입력된 상황
if (nullptr == m_Root)
{
m_Root = pNewNode;
}
// 데이터가 2개 이상인 경우
else
{
BSTNode<T1, T2>* pNode = m_Root;
while (true)
{
// 입력된 first 값이 현재 노드의 first 값보다 작은 경우
if (pNewNode->pair.first < pNode->pair.first)
{
// 왼쪽이 비어있으면
if (nullptr == pNode->pLeftChild)
{
// 현재 노드의 왼쪽으로 연결
pNode->pLeftChild = pNewNode;
pNewNode->pParent = pNode;
break;
}
// 왼쪽으로 내려간다.
pNode = pNode->pLeftChild;
}
// 입력된 first 값이 현재 노드의 first 값보다 큰 경우
else if (pNode->pair.first < pNewNode->pair.first)
{
// 현재 노드의 오른쪽이 비어있으며
if (nullptr == pNode->pRightChild)
{
// 입력된 노드를 현재 노드의 오른쪽으로 연결
pNode->pRightChild = pNewNode;
pNewNode->pParent = pNode;
break;
}
// 오른쪽으로 내려간다.
pNode = pNode->pRightChild;
}
}
}
++m_CurCount;
}
template<typename T1, typename T2>
inline void BST<T1, T2>::Circit(BSTNode<T1, T2>* _Node)
{
if (nullptr == _Node)
{
return;
}
Circit(_Node->pLeftChild);
//std::cout << _Node->pair.first << std::endl;
Circit(_Node->pRightChild);
}
template<typename T1, typename T2>
typename BST<T1, T2>::iterator BST<T1, T2>::find(const T1& _key)
{
BSTNode<T1, T2>* pNode = m_Root;
while (pNode)
{
if (_key < pNode->pair.first)
{
pNode = pNode->pLeftChild;
}
else if (pNode->pair.first < _key)
{
pNode = pNode->pRightChild;
}
else
{
break;
}
}
return iterator(this, pNode);
}
template<typename T1, typename T2>
typename BST<T1, T2>::iterator BST<T1, T2>::erase(const iterator& _target)
{
// 삭제할 노드가 리프노드인 경우 (자식이 0개)
if (_target.m_TargetNode->IsLeaf())
{
}
// 자식이 2개 있는 경우
else if (_target.m_TargetNode->IsFull())
{
}
// 자식이 1개 있는 경우
else
{
}
return iterator();
}
1차 24.01.08
2차 24.01.09
3차 24.01.10
4차 24.01.11
5차 24.01.12