연결리스트
다음 연결에 대한 참조만을 갖는 기본적인 연결리스트. 첫 항목부터 순차적으로 접근하기 때문에 O(n)의 시간 복잡도를 갖는다. 기본적인 자료구조로 사용되는 배열의 경우 물리적으로 인접하여 접근 시간 단축 및 캐싱에 유리하지만, 연결리스트는 그렇지 않다. 하지만 배열에 비해 삽입이 간단하며 배열에 비해 사이즈 변경에 신경 쓸 일이 없다는 점에서 유리하다. 결론적으로 삽입은 연결리스트, 조회는 배열이 유리하다.
class Node{
friend class linkedList;
private:
int value;
Node* link;
public:
Node(int v, Node* l):value(v),link(l) {}
};
class linkedList{
private:
Node* head;
public:
linkedList() {head=NULL;}
/*삽입, 삭제, 조회, 갱신 함수 구현*/
}
위는 C++을 이용한 기본적인 연결리스트 구현이다. 그리고 연결리스트(linkedList) 클래스에 기본 연산 함수인 삽입, 삭제, 조회, 갱신은 아래와 같다.
//헤드 위치에 노드를 삽입하는 방식
void insert(int value){
//새로 만든 노드에 지정한 값을 넣고 다음 링크는 현재 헤드이며 이렇게 설정한 노드 자체를 헤드로 초기화
head = new Node(value, head);
}
위의 삽입 방식 외에도 연결리스트에 head와 더불어 tail까지 관리하여 맨 끝에 삽입, 특정 위치의 삽입 등이 가능하다.
//조회함수
boolean search(int value){
for(Node* temp=head;temp;temp=temp->link){
if(temp->value==value)
return true; //조회하는 값이 존재.
}
return false; //리스트에 조회하는 값이 존재하지 않음.
}
//갱신함수
boolean update(int fromValue, int toValue){
for(Node* temp=head; temp; temp=temp->link){
if(temp->value==fromValue){
temp->value=toValue;
return true;
}
}
return false;
}
//삭제함수
boolean delete(int value){
Node *deleteNode;
Node *prevNode; //삭제할 노드의 이전 노드: 연결을 끊기 위함.
if(head->value==value){
deleteNode=head;
head=head->link;
free(deleteNode);
return true;
}else{
prevNode=head;
if(head->link) //리스트에 헤드노드 하나만 존재하는 경우를 대비하기 위한 조건문
deleteNode=head->link;
else
return false;
//실제 탐색 후 삭제 로직
for(;deleteNode;deleteNode=deleteNode->link){
if(deleteNode->value==value){
prevNode->link=deleteNode->link;
free(deleteNode);
return true;
}else{
prevNode=prevNode->link;
}
}
}
return false;
}
원형 연결리스트
마지막 노드가 첫번째 노드를 가리키는 연결리스트.
class CircularLinkedList{
private:
Node* tail;
public:
CircularlinkedList() {tail=NULL;}
/*삽입, 삭제, 조회, 갱신 함수 구현*/
};
기존의 연결리스트에서는 head를 사용했다. 하지만, 원형 연결리스트의 경우 마지막 노드가 head 노드를 가리키기 위한 로직을 위해 tail이라는 노드를 사용한다. 그러면 head는 어떻게 하냐? tail의 다음 노드는 head라는 것을 이용한다.
//마지막 노드 위치에 노드를 삽입하는 방식
void insert(int value){
if(tail){
Node *new=new Node(value, tail->link);
tail=tail->link=new;//tail의 다음 노드는 new로 갱신하고, new는 tail이 된다.
}else{//리스트가 비어있을 경우
Node *new=new Node(value);
new->link=new;
tail=new;
}
size++;
}
//삭제함수
boolean delete(int value){
Node *deleteNode;
Node *prevNode; //삭제할 노드의 이전 노드: 연결을 끊기 위함.
if(tail->value==value){
deleteNode=tail;
for(prevNode=tail; prevNode->link==tail; prevNode=prevNode->link);
prevNode->link=tail->link;
tail=prevNode;
free(deleteNode);
return true;
}else{
prevNode=tail;
if(tail->link)
deleteNode=tail->link;
else
return false;
for(;deleteNode->value==value; deleteNode=deleteNode->link){
prev=prev->link;
if(prev==tail)
return false; //한 바퀴를 돌았지만 삭제할 값이 존재하지 않는 경우.
}
prev->link=deleteNode->link;
free(deleteNode);
return true;
}
return false;
}
조회와 갱신은 연결리스트와 매우 유사하여 생략
이중 연결리스트
각 노드가 선행 노드와 후행 노드 모두를 가리키는 연결리스트.
'Domain > 자료구조' 카테고리의 다른 글
2. 큐, 스택 (0) | 2020.03.12 |
---|---|
3. 이진 트리 (0) | 2020.03.12 |
4. 히프 트리(Heap Tree) (0) | 2020.03.12 |
5. 이진 탐색 트리(BST, Binary Searching Tree) (0) | 2020.03.12 |
6. 그래프 (0) | 2020.03.12 |