반응형
이중 연결 리스트
# 이중 연결 리스트에서는 이전 노드가 다음 노드의 포인터를, 다음 노드는 이전 노드의 포인터를 가지고 있다.
# 그러므로 시작에서만이 아니라 앞에서뿐만 아니라 뒤에서부터도 순회가 가능하다.
# 삽입, 삭제 위치에 따른 분류는 이후에 다룰 '스택', '큐', '덱'으로 이루어지므로 이에 자세한 고민은 안했다.
# STL에서는 list가 이 구조이다. (즉, 실제로 사용하게 되는건 STL의 <list>)
단일 연결 리스트의 ADT
1. 원하는 위치에 노드를 추가할 수 있다.
2. 원하는 위치의 노드를 삭제할 수 있다.
3. 원하는 위치의 노드의 값을 수정할 수 있다.
4. 리스트 전체를 양방향으로 순회할 수 있다.
5. 리스트의 전체 노드수를 확인할 수 있다.
6. 리스트가 비어있는 경우는 사용자가 알아서 예외처리를 한다고 가정한다.
C++로 구현한 이중 연결 리스트
#pragma once
template <typename T>
class DoublyLinkedList
{
template <typename T>
struct node {
T data;
node<T>* prev;
node<T>* next;
};
node<T>* pHead;
node<T>* pCursor;
node<T>* pTail;
int iSize;
public:
int getSize();
int AddFront(T data); //리스트 앞에 데이터 추가
int AddBack(T data); //리스트 끝에 데이터 추가
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:
DoublyLinkedList();
~DoublyLinkedList();
};
template <typename T>
DoublyLinkedList<T>::DoublyLinkedList()
{
pHead = nullptr;
pTail = nullptr;
iSize = 0;
}
//getMethod
template <typename T>
int DoublyLinkedList<T>::getSize()
{
return iSize;
}
//리스트 앞에 데이터 추가
template <typename T>
int DoublyLinkedList<T>::AddFront(T data)
{
node<T>* newnode = new node<T>;
newnode->data = data;
newnode->prev = nullptr;
newnode->next = pHead;
if (pTail == nullptr) {
pTail = newnode;
pCursor = pTail;
}
else {
pHead->prev = newnode;
}
pHead= newnode;
return ++iSize;
}
//리스트 끝에 데이터 추가
template <typename T>
int DoublyLinkedList<T>::AddBack(T data)
{
node<T>* newnode = new node<T>;
newnode->data = data;
newnode->prev = pTail;
newnode->next = nullptr;
if (pHead == nullptr) {
pHead = newnode;
pCursor = pHead;
}
else {
pTail->next = newnode;
}
pTail = newnode;
return ++iSize;
}
//원하는 위치에 데이터 추가
template <typename T>
int DoublyLinkedList<T>::AddData(int index, T data)
{
node<T>* newnode = new node<T>;
newnode->data = data;
newnode->prev = nullptr;
newnode->next = nullptr;
if (pHead == nullptr) {
pHead = newnode;
pTail = newnode;
}
else {
if (index <= 0) {
newnode->next = pHead;
pHead->prev = newnode;
pHead = newnode;
}
else if (index >= iSize - 1) {
newnode->prev = pTail;
pTail->next = newnode;
pTail = newnode;
}
else {
node<T>* pFind = pHead;
for (int i = 0; i < index - 1; i++) {
pFind = pFind->next;
}
newnode->next = pFind->next;
newnode->prev = pFind;
pFind->next = newnode;
}
}
pCursor = pHead;
return ++iSize;
}
//지정한 위치에 있는 데이터를 확인.
template <typename T>
T& DoublyLinkedList<T>::CheckData(int index)
{
int iIndex = index;
if (index <= 0) {
iIndex = 0;
}
node<T>* pFind = pHead;
for (int i = 0; i < iIndex; i++) {
pFind = pFind->next;
}
return pFind->data;
}
//지정한 위치에 있는 데이터를 수정.
template <typename T>
void DoublyLinkedList<T>::ChangeData(int index, T data)
{
int iIndex = index;
if (index <= 0) {
iIndex = 0;
}
node<T>* pFind = pHead;
for (int i = 0; i < iIndex; i++) {
pFind = pFind->next;
}
pFind->data = data;
}
//지정한 위치에 있는 데이터를 삭제
template <typename T>
int DoublyLinkedList<T>::DeleteData(int index)
{
node<T>* pDel = nullptr;
int iIndex = index;
if (index <= 0) {
pDel = pHead;
pHead = pHead->next;
pHead->prev = nullptr;
delete pDel;
pCursor = pHead;
}
else if (index >= iSize - 1) {
iIndex = iSize - 1;
}
node<T>* pFind = pHead;
for (int i = 0; i < iIndex - 1; i++) {
pFind = pFind->next;
}
if (pFind->next == pTail) {
pTail = pFind;
pDel = pFind->next;
pFind->next = nullptr;
delete pDel;
}
else {
pDel = pFind->next;
pFind->next = pDel->next;
pDel->next->prev = pFind;
delete pDel;
}
return --iSize;
}
//특정한 값을 가진 노드(들) 삭제
template <typename T>
int DoublyLinkedList<T>::DeleteValue(T data)
{
node<T>* pDel = nullptr;
while (pHead != nullptr && pHead->data == data) {
pDel = pHead;
pHead = pHead->next;
pHead->prev = nullptr;
delete pDel;
pCursor = pHead;
iSize--;
}
if (pHead == nullptr) {
return 0;
}
node<T>* pFind = pHead;
while (pFind->next != nullptr) {
if (pFind->next->data == data) {
if (pFind->next == pTail) {
pTail = pFind;
pDel = pFind->next;
pFind->next = nullptr;
delete pDel;
iSize--;
}
else {
pDel = pFind->next;
pFind->next = pDel->next;
pDel->next->prev = pFind;
delete pDel;
iSize--;
}
}
else {
pFind = pFind->next;
}
}
return iSize;
}
//커서 포인터를 지정한 위치로 이동.
template <typename T>
void DoublyLinkedList<T>::SetCursor(int index)
{
pCursor = pHead;
int iIndex = index;
if (index >= iSize - 1) {
iIndex = iSize - 1;
}
for (int i = 0; i < iIndex; i++) {
pCursor = pCursor->next;
}
}
//리스트 순회용
template <typename T>
T& DoublyLinkedList<T>::Next()
{
T& ret = pCursor->data;
if (pCursor != nullptr && pCursor->next != nullptr) {
pCursor = pCursor->next;
}
return ret;
}
template <typename T>
T& DoublyLinkedList<T>::Prev()
{
T& ret = pCursor->data;
if (pCursor != nullptr && pCursor->prev != nullptr) {
pCursor = pCursor->prev;
}
return ret;
}
template <typename T>
DoublyLinkedList<T>::~DoublyLinkedList()
{
node<T>* pDel = nullptr;
node<T>* pFind = pHead;
while (pFind != nullptr) {
pDel = pFind;
pFind = pFind->next;
delete pDel;
}
pHead = nullptr;
pTail = nullptr;
pCursor = nullptr;
iSize = 0;
}반응형