profile image

L o a d i n g . . .

반응형

개념

링크드 리스트의 탐색 기능을 개선한 자료구조이다. 양방향으로 탐색이 가능하다.

 

코드 자체는 링크드 리스트와 크게 다른 게 없다. 삽입, 삭제 시 양방향인 것만 신경 쓰면 된다.

template<typename T>
struct Node
{
	T data;			// 데이터
	Node<T>* prevNode;	// 이전 노드를 가리키는 포인터
	Node<T>* nextNode;	// 다음 노드를 가리키는 포인터

	Node<T>(T value) : data(value), prevNode(NULL), nextNode(NULL) {}
};

template<typename T>
class DoublyLinkedList
{
	Node<T>* head;
	Node<T>* tail;
	int size = 0;

public:
	DoublyLinkedList() : head(NULL), tail(NULL) {}
	~DoublyLinkedList()
	{
		Node<T>* deleteNode;
		while (head->nextNode != NULL)
		{
			deleteNode = head;
			head = head->nextNode;
			delete deleteNode;
		}
	}
	// ...
}

 

 

노드 추가

void addNode(T data)
{
	Node<T>* newNode = new Node<T>(data);
	++size;

	// head가 NULL이라면 현재 Linked List는 비어 있는 상태
	if (head == NULL)
	{
		head = tail = newNode;
		return;
	}
    
	tail->nextNode = newNode;
	newNode->prevNode = tail;
	tail = newNode;
}

 

 

노드 탐색

void showList() const
{
	Node<T>* findNode = head;

	cout << "size of DLL: " << size << endl;

	while (findNode != NULL)
	{
		cout << findNode->data << " ";
		findNode = findNode->nextNode;
	}
	cout << endl;
}
Node<T>* findNode(int location) const
{
	Node<T>* searchNode = head;
	int index = location;

	while (searchNode != NULL && --index >= 0)
	{
		searchNode = searchNode->nextNode;
	}

	return searchNode;
}

T findNodeData(int location) const
{
	Node<T>* searchNode = head;
	int index = location;

	while (searchNode != NULL && --index >= 0)
	{
		searchNode = searchNode->nextNode;
	}

	return searchNode->data;
}

귀찮아서 스킵했지만(...) findNode처럼 index로 접근하는 경우, 리스트 사이즈의 절반보다 큰지, 작은지를 체크해서 분기를 나눠서 처리하면 DLL의 개선점을 활용하는 코드가 될 것 같다.

 

 

노드 삭제

void removeNode(T data)
{
	// 삭제될 Node를 가리키는 포인터
	Node<T>* deleteNode = head;

	while (deleteNode != NULL)
	{
		if (deleteNode->data == data)
			break;
		deleteNode = deleteNode->nextNode;
	}

	// nullptr이면 해당 데이터를 찾지 못함
	if (deleteNode != NULL)
	{
		if (deleteNode->prevNode != NULL)
			deleteNode->prevNode->nextNode = deleteNode->nextNode;
		if (deleteNode->nextNode != NULL)
			deleteNode->nextNode->prevNode = deleteNode->prevNode;
		--size;

		delete deleteNode;
	}
}

 

 

노드 삽입

void insertNode(T data, int index)
{
	// index가 DLL 사이즈보다 크거나 음수인 경우 예외 처리
	if (index > size || index < 0)
	{
		cout << "invalid index : " << index << endl;
		return;
	}

	Node<T>* newNode = new Node<T>(data);

	// head에 추가
	if (index == 0)
	{
		// 만약 비어 있다면
		if (head == NULL)
			tail = newNode;

		head->prevNode = newNode;
		newNode->nextNode = head;
		head = newNode;
	}
	// tail에 추가
	else if (index == size)
	{
		// 만약 비어 있다면
		if (head == NULL)
			head = tail = newNode;
		else
		{
			newNode->prevNode = tail;
			tail->nextNode = newNode;
			tail = newNode;
		}
	}
	else
	{
		Node<T>* findNode = head;

		for (int i = 1; i < index; ++i)
		{
			findNode = findNode->nextNode;
		}

		newNode->nextNode = findNode->nextNode;
		newNode->prevNode = findNode;
		findNode->nextNode = newNode;
	}

	++size;
}
반응형
복사했습니다!