12. linked list

Posted by aliontory on April 19, 2024 · 2 mins read

2024-04-19-12. Linked List

Linked List의 정의



  • Node들과 head 하나로 구성된다.
  • Node는 저장 공간의 한 단위로, 데이터 저장 공간과 포인터로 구성된다.
  • Node의 포인터에는 다음 노드의 주소가 저장되어 있다.
  • head는 첫 번째 노드의 주소를 저장하는 포인터이다.
  • 위 그림은 값 12, 99, 37을 순서대로 저장하는 Linked List를 그림으로 나타낸 것이다. 데이터로 12가 저장된 노드의 포인터는 99가 저장된 다음 노드의 주소를 저장하고 있다.
  • 위 그림에서, head에는 12가 저장된 노드의 주소가 저장되어 있을 것이다.


Linked List 코드

다음은 ‘정렬된’ Linked List와 그것의 생성, 검색, 삽입, 삭제, 소멸 함수들이다.
class Node {
int data;
Node *n;
};

class List {
List();
~List();
int Search();
int Insert();
int Delete();

Node *head;
/* 다음 p, l은 search에 사용할 포인터이다.
검색에 성공할 경우, l에는 검색한 값을 가지는 노드의 주소가 저장되고, p에는 그 이전 노드의 주소기 저장된다.
검색에 실패할 경우, p와 l이 가리키는 노드 사이에 검색값이 삽입되야 정렬된 상태를 유지하도록, p와 l값이 정해진다. */
Node *p, *l;
};

List::List() {
head = nullptr;
}

List::~List() {
Node *current, *next;
current = head;
while(current != nullptr) {
next = current->n;
delete current;
current = next;
}
}

/* Search는 Linear Search 알고리즘을 이용한다.
linked list는 중간 노드에 바로 접근할 수 없으므로, binary search를 빠르게 할 수 없다. */
int List::Search(int x) {
p = nullptr;
l = head;
while(l != nullptr) {
if(l->data == x) return 1;
else if(l->data > x) return 0;
else {
p = l; l = l->n;
}
}
return 0;
}

int List::Insert(int x) {
if(!Search(x)) { // 중복값을 막기 위해 검색에 실패했을 때만 Insert
Node* new_node = new Node;
new_node->data = x;
if(p == nullptr)
head = new_node;
else
p->n = new_node;
new_node->n = l;
return 1;
}
return 0;
}

List::Delete(int x) {
if(Search(x)) {
if(p==nullptr)
head = l->n;
else
p->n = l->n;
delete l;
return 1;
}
return 0;
}

Search 결과에 nullptr이 들어간 경우를 다루기 위해 if문을 사용해야 했다. -∞와 ∞가 저장된 Node를 리스트 앞, 뒤에 저장하면, 이런 경우를 따로 처리하지 않아도 된다.


Linked List 성능

  • 정렬된 리스트의 경우
    • 정렬되어 있어도 인덱스의 중간값에 바로 접근할 수 없으므로 binary search 불가.
    • Search : O(n)
    • Inseart : S + O(1)  (S는 search 에 걸리는 시간)
    • Delete : S + O(1)
  • 정렬되지 않은 리스트의 경우
    • Search : O(n)
    • Insert : O(1) (정렬을 유지할 필요가 없으므로, Search 없이 그냥 head에 노드를 추가하면 됨)
    • Delete : S + O(1)

Linked List는 binary search를 사용할 수 없어, Array보다 search 가 느리다. 

stack, queue를 구현할 때 Array 대신 Linked List를 사용할 수도 있다.


Skip List에 대한 아이디어


skip list는 linked list에서 binary search를 할 수 있도록, 중간 원소로 바로 갈 수 있는 포인터들을 추가한 것이다.