C++ 개념 공부/자료구조
[C++] 연결리스트
taene_
2023. 9. 2. 16:23
1. node의 위치를 기억한다면 list의 중간 삽입 및 삭제가 빠르게 작동하지만, node의 위치를 기억하지 못하고 찾으려고 하면 느리다.
2. 임의접근(중간에 인덱스번호를 말하고 거기에 접근하려는것)이 굉장히 느리다.
//템플릿과 클래스를 이용한 싱글 링크드 리스트 구현
#include<iostream>
using namespace std;
//typedef int T;
//using T = int;
template <typename T>
struct Node //노드 구조체
{
public:
T value;
struct Node<T> *next = nullptr;
};
//////////////////////////////////////////////////////////////////////
template <typename T>
class SingleLinked_List //싱글 링크드 리스트
{
private:
Node<T> *head; //처음(front)
Node<T> *tail; //끝(back)
int size = 0; //링크의 길이
public:
SingleLinked_List() : head(nullptr), tail(nullptr) {} //생성자 리스트
~SingleLinked_List() {} //소멸자
void AddNode(T _value) //노드 추가하기(back)
{
Node<T> *node = new Node<T>; //노드 동적 할당
size++;
node->value = _value;
node->next = nullptr;
if (head == nullptr) //만약 머리가 없을경우
{
head = node;
tail = node;
}
else //만약 머리가 있을경우 뒤에 연결
{
tail->next = node;
tail = tail->next;
}
}
void RemoveNode(T _value) //찾는 값 노드 지우기
{
Node<T> *ptr = head;
Node<T> *tmp = ptr;
while (ptr != nullptr) //ptr 반복
{
if (ptr->value == _value) //만약 값을 찾앗다면
{
break;
}
else
{
tmp = ptr; //목표의 전 노드
ptr = ptr->next;
}
}
if (ptr == nullptr)
{
cout << "찾을 수 없는 노드 입니다" << endl;
}
else
{
size--;
cout << "삭제된 노드의 값: " << ptr->value << endl;
tmp->next = ptr->next; //삭제할 노드를 제외하고 연결
delete ptr; //동적 할당 해제
}
}
void Show() //리스트 안에 값 보여주기
{
Node<T> *node = head;
while (node != nullptr) //노드값이 null
{
cout << node->value << "->";
node = node->next;
}
cout << endl;
}
void DeleteList() //리스트 삭제하기 (동적할당 풀기)
{
Node<T> *ptr = head;
while (ptr != nullptr)
{
head = ptr->next;
delete ptr;
ptr = head;
}
delete head; //null 포인터 삭제
size = 0;
cout << "리스트가 삭제되었습니다" << endl;
}
void RemoveTail() //꼬리(back) 삭제하기
{
Node<T> *ptr = head;
Node<T> *tmp = new Node<T>;
while (ptr->next != nullptr)
{
tmp = ptr;
ptr = ptr->next;
}
size--;
tail = tmp;
tail->next = nullptr;
delete ptr; //꼬리 동적할당 해제
}
void RemoveHead() //헤드(front) 삭제하기
{
Node<T> *ptr = head;
head = ptr->next;
size--;
delete ptr;
}
void AddHead(T _value) //헤드(front)에 값넣기
{
Node<T> *ptr = new Node<T>();
size++;
ptr->next = head;
ptr->value = _value;
head = ptr;
}
void AddPosition(int _index, T _value)
{
if (size < _index || 0>_index) //인덱스가 잘못될 경우
{
cout << "해당하는 인덱스 값은 없습니다." << endl;
return;
}
Node<T> *ptr = head;
Node<T> *tmp = ptr;
Node<T> *node = new Node<T>; //새로 추가된 노드
node->value = _value;
node->next = nullptr;
for (int i = 0; i < _index-1; i++)
{
tmp = ptr; //들어갈 노드의 전 위치
ptr = ptr->next; //들어갈 노드의 위치
}
tmp->next = node;
node->next = ptr; //새노드는 기존에 있는 노드위치를 가리킨다.
size++;
}
void SearchValue(T _value) //원하는 값이 몇 번쨰에 있는지 확인하기
{
Node<T> *ptr = head;
int index = 0;
bool isFind = false; //찾앗는지 확인하는 bool 값
while (ptr != nullptr)
{
index++;
if (ptr->value == _value) //ptr 값이랑 같을떄 인덱스값 반환
{
cout << _value << " 값은 인덱스 " << index << " 번쨰에 있습니다" << endl;
isFind = true;
break;
}
ptr = ptr->next;
}
//못찾았을 경우
if (isFind == false)
{
cout << _value << " 값은 리스트 안에 없습니다. " << endl;
}
}
int Size() //리스트 크기를 반환
{
return size;
}
};
int main()
{
//리스트 동적할당의 경우
//SingleLinked_List<int> *List = new SingleLinked_List<int>();
//List->add_node(10);
//List->add_node(11);
//List->show();
//delete List;
SingleLinked_List<int> List; //리스트 정적할당
//리스트에 노드 추가하기
List.AddNode(10);
List.AddNode(11);
List.AddHead(14);
List.AddHead(18);
List.AddHead(1);
List.AddPosition(2, 7); //인덱스 2번쨰에 값 7넣기
List.Show();
List.SearchValue(10);
cout << "리스트의 크기 " << List.Size() << endl; //리스트 크기 반환
List.AddHead(4); //리스트 헤드에 값넣기
List.AddNode(9);
List.Show();
cout << "리스트의 크기 " << List.Size() << endl; //리스트 크기 반환
List.RemoveHead(); //리스트 헤드 삭제
List.RemoveTail(); //리스트 꼬리 삭제
List.RemoveNode(14); //리스트에서 값이 14인 노드 삭제
List.SearchValue(14); //삭제된 14값 찾기
List.Show();
cout << "리스트의 크기 " << List.Size() << endl; //리스트 크기 반환
List.DeleteList(); //리스트 삭제하기 (모든 노드 동적할당 해제)
List.AddNode(10);
List.Show();
cout << "리스트의 크기 " << List.Size() << endl; //리스트 크기 반환
return 0;
}