빈 연결리스트에 노드 추가: 아무것도 존재하지 않으므로 head/tail 모두 추가하려는 노드를 가리키면 된다.
연결리스트의 첫번째에 노드를 추가: 새로운 노드가 head의 주소를 가리킴. head의 주소는 새로운 노드로 변경
연결리스트의 마지막에 노드를 추가: 새로운 노드가 tail의 주소를 가리킴. tail의 주소는 새로운 노드로 변경
연결리스트의 중간에 노드를 삽입: 4개의 링크를 변경하면 된다. 글보단 아래 그림을 보는 것이 이해가 편하다.
-노드 삭제
void remove(Node *p) {
if (head == p && tail == p) { // p is only node of list
head = NULL;
tail = NULL;
}
else if (head == p) { // p is head
p->next->prev = NULL;
head = p->next;
}
else if (tail == p) { // p is tail
p->prev->next = NULL;
tail = p->prev;
}
else { // p is middle node
p->prev->next = p->next;
p->next->prev = p->prev;
}
free(p);
size--;
}
이중 연결리스트의 장점인 삭제 부분이다. 기존 연결리스트는 어떤 노드를 삭제하기 위해서 타겟노드의 이전 노드를 기억하고 있어야 했다. 하지만 노드들 마다 이전 노드의 주소를 알고 있기 때문에 코드에서 이전노드의 주소를 기억할 필요가 없어지게 된다.
노드 삽입/추가와 마찬가지로 4가지 경우로 나누어 코드를 구현하면 된다.
-정렬된 연결리스트에 노드 삽입
add_ordered_list(char *item) { // start searching at tail
Node *p = tail;
while (p != NULL && strcmp(item, p->data) < 0) {
p = p->prev;
}
add_after(p, item);
}
이미 노드 삽입 부분을 구현했다. 따라서 기존 삽입함수를 활용하면 4가지 경우를 고려하지 않고 코드를 구현할 수 있다. 일단 정렬된 연결리스트이기 때문에 삽입하려는 노드의 값보다 작은 값을 찾아야 한다. (여기선 abc 오름차순 정렬) strcmp함수로 삽입하려는 노드보다 작은 값을 찾거나 p 노드가 가리키는 노드가 NULL이면 반복을 종료한다. 이 노드를 add_after 함수에 전달만 하면 끝이다. 4가지 경우는 add_after 함수에서 처리할 것이다.
-결과 확인
int main() {
add_ordered_list("c");
add_ordered_list("a");
add_ordered_list("d");
add_ordered_list("b");
return 0;
}
결과값
제대로 결과값이 나오는 모습을 확인
사실 연결리스트 개념 자체는 이해하기 어렵지 않았다. 다만 c언어를 잘못해서 포인터 변수에 대한 이해가 조금 어려웠던 것 같다.