반응형
이중 원형 연결 리스트
# 이중 원형 연결 리스트는 마지막 노드가 첫번째 노드를 가리키고, 첫번째 노드도 마지막 노드를 가리키게 함으로 원형 구조를 이루게 한 이중 연결 리스트다.
# 그러므로 순회시 따로 끝을 지정하지 않는한 무한 루프를 돌게 된다.
# 앞에 두개는 처음이나 끝에 도달했는데도 계속 prev나 next를 호출하면 각각 첫 노드나 끝 노드를 계속 반환하도록 했었다.
# 앞에 두개에서는 Head포인터와 Tail포인터 두개를 사용했으나 Head포인터 하나로 두 위치를 모두 표시할 수 있다. (Head의 prev가 Tail임으로)
# 연결 리스트의 특성상 특정 위치의 노드를 찾기 위해서는 각각의 노드를 거쳐가야 하므로 최악의 경우 size만큼의 노드를 확인해야한다.
# 하지만 이중 원형 연결 리스트는 거쳐갈 노드의 수가 최악의 경우에도 size/2로 줄일 수 있다.
# 원형 리스트는 STL에 포함되어 있지 않다.
이중 원형 연결 리스트의 ADT
1. 원하는 위치에 노드를 추가할 수 있다.
2. 원하는 위치의 노드를 삭제할 수 있다.
3. 원하는 위치의 노드의 값을 수정할 수 있다.
4. 리스트 전체를 양방향으로 순회할 수 있다.
5. 리스트의 전체 노드수를 확인할 수 있다.
6. 리스트가 비어있는 경우는 사용자가 알아서 예외처리를 한다고 가정한다.
C++로 구현한 이중 원형 연결 리스트
#pragma once template <typename T> class SircularLinkedList { template <typename T> struct node { T data; node<T>* prev; node<T>* next; }; node<T>* pHead; node<T>* pCursor; int iSize; public: int getSize(); int AddData(int index, T data); //지정한 위치에 데이터 추가. T& CheckData(int index); //지정한 위치에 있는 데이터를 확인. void ChangeData(int index, T data); //지정한 위치에 있는 데이터를 수정. int DeleteData(int index); //지정한 위치에 있는 데이터 삭제. int DeleteValue(T data); //지정한 값을 가진 노드(들) 삭제. void SetCursor(int index); //커서 포인터를 지정한 위치로 이동. //리스트 순회용 T& Next(); T& Prev(); public: SircularLinkedList(); ~SircularLinkedList(); }; template <typename T> SircularLinkedList<T>::SircularLinkedList() { pHead = nullptr; iSize = 0; } //getMethod template <typename T> int SircularLinkedList<T>::getSize() { return iSize; } //원하는 위치에 데이터 추가 (맨 앞에 추가하고 싶다면 -1을, 맨 끝에 추가하고 싶다면 getSize()사용) template <typename T> int SircularLinkedList<T>::AddData(int index, T data) { node<T>* newnode = new node<T>; newnode->data = data; if (pHead == nullptr) { newnode->prev = newnode; newnode->next = newnode; pCursor = pHead = newnode; } else { if (index <= 0 || index >= iSize - 1) { newnode->prev = pHead->prev; newnode->next = pHead; pHead->prev->next = newnode; pHead->prev = newnode; if (index <= 0) { pCursor = pHead = newnode; } } else { node<T>* pFind = pHead; if (index <= iSize / 2) { for (int i = 0; i < index - 1; i++) { pFind = pFind->next; } } else { for (int i = 0; i < iSize - index + 1; i++) { pFind = pFind->prev; } } newnode->prev = pFind; newnode->next = pFind->next; pFind->next->prev = newnode; pFind->next = newnode; } } return ++iSize; } //지정한 위치에 있는 데이터를 확인. template <typename T> T& SircularLinkedList<T>::CheckData(int index) { int iIndex = index; if (index >= iSize) { iIndex = iSize - 1; } node<T>* pFind = pHead; if (iIndex <= iSize / 2) { for (int i = 0; i < iIndex; i++) { pFind = pFind->next; } } else { for (int i = 0; i < iSize - iIndex; i++) { pFind = pFind->prev; } } return pFind->data; } //지정한 위치에 있는 데이터를 수정. template <typename T> void SircularLinkedList<T>::ChangeData(int index, T data) { int iIndex = index; if (index >= iSize) { iIndex = iSize - 1; } node<T>* pFind = pHead; if (iIndex <= iSize / 2) { for (int i = 0; i < iIndex; i++) { pFind = pFind->next; } } else { for (int i = 0; i < iSize - iIndex; i++) { pFind = pFind->prev; } } pFind->data = data; } //지정한 위치에 있는 데이터를 삭제 template <typename T> int SircularLinkedList<T>::DeleteData(int index) { if (pHead == nullptr) { return 0; } node<T>* pDel = nullptr; int iIndex = index; if (index <= 0) { pDel = pHead; pHead = pHead->next; pDel->prev->next = pHead; pHead->prev = pDel->prev; delete pDel; pCursor = pHead; return --iSize; } if (index >= iSize - 1) { pDel = pHead->prev; pDel->prev->next = pHead; pHead->prev = pDel->prev; delete pDel; return --iSize; } if (index > iSize - 1) { iIndex = iSize - 1; } node<T>* pFind = pHead; if (iIndex <= iSize / 2) { for (int i = 0; i < iIndex - 1; i++) { pFind = pFind->next; } } else { for (int i = 0; i < iSize - iIndex + 1; i++) { pFind = pFind->prev; } } pDel = pFind->next; pFind->next = pDel->next; pDel->next->prev = pFind; delete pDel; return --iSize; } //특정한 값을 가진 노드(들) 삭제 template <typename T> int SircularLinkedList<T>::DeleteValue(T data) { if (pHead == nullptr) { return 0; } node<T>* pDel = nullptr; while (pHead->data == data) { pDel = pHead; pHead = pHead->next; pDel->prev->next = pHead; pHead->prev = pDel->prev; delete pDel; pCursor = pHead; iSize--; if (iSize == 0) { pHead = nullptr; return 0; } } node<T>* pFind = pHead; while (pFind->next != pHead) { if (pFind->next->data == data) { pDel = pFind->next; pFind->next = pDel->next; pDel->next->prev = pFind; delete pDel; iSize--; } else { pFind = pFind->next; } } return iSize; } //커서 포인터를 지정한 위치로 이동. template <typename T> void SircularLinkedList<T>::SetCursor(int index) { pCursor = pHead; int iIndex = index; if (index > iSize - 1) { iIndex = iSize - 1; } if (iIndex <= iSize / 2) { for (int i = 0; i < iIndex; i++) { pCursor = pCursor->next; } } else { for (int i = 0; i < iSize - iIndex; i++) { pCursor = pCursor->prev; } } } //리스트 순회용 template <typename T> T& SircularLinkedList<T>::Next() { T& ret = pCursor->data; if (pCursor->next != nullptr) { pCursor = pCursor->next; } return ret; } template <typename T> T& SircularLinkedList<T>::Prev() { T& ret = pCursor->data; if (pCursor->prev != nullptr) { pCursor = pThis->prev; } return ret; } template <typename T> SircularLinkedList<T>::~SircularLinkedList() { node<T>* pDel = nullptr; node<T>* pFind = pHead; while (pFind != nullptr) { pDel = pFind; pFind = pFind->next; delete pDel; } pHead = nullptr; pCursor = nullptr; iSize = 0; }
반응형