각 노드가 데이터와 포인터를 가지고 한 줄로 연결되어 있는 방식으로 데이터를 저장하는 자료구조
연결 리스트의 구성 요소로는
연결 리스트는 다음과 같은 아파트의 호실 형태라고 보시면 됩니다.
분명 방은 다 흩어져 있는데 연결이 되어있죠? 이것이 가능한 이유는 연결리스트의 구성요소인 노드가 데이터 공간과 함께 포인터 공간, 즉 다음 노드의 주소를 참조하고 있기 때문입니다.
더 쉽게 말하자면 노드1은 자신이 가지고 있는 노드2의 주소만을 따라가서 노드2와 연결되는 겁니다.
여기서 우리는 왜 연결리스트인지에 대해 알 수 있습니다.
연결리스트는 다른 것들과 다르게 그 위치가 흩어져 있어 서로 주소로 연결되어있어야 한다는 의미로 연결이라는 키워드가 사용된 것이죠.
각 노드의 자료공간과 포인터 공간이 각각 한 개씩만 존재하는 리스트
여기서는 마지막 포인터를 제외한 나머지 노드가 다음 노드에 대한 참조만을 가집니다.
단일 연결 리스트 | |
---|---|
접근 | O(n) |
검색 | O(n) |
삽입 | O(1) |
삭제 | O(1) |
접근, 검색 : 가장 마지막 원소를 찾으려면 배열처럼 처음부터 끝까지 찾아봐야 하기 때문에 시간복잡도는 O(n) 을 갖습니다.
삽입, 삭제 : 연결리스트는 포인터가 주소를 참조하여 연결되는 방식이므로 원하는 값을 삽입 또는 삭제할 때 해당 주소로 가서 바로 삽입 또는 삭제가 가능합니다. 따라서 제일 빠른 시간복잡도인 O(1) 를 갖습니다.
일렬로 연결되는 구조의 특성상 중간에 어떤 한 참조주소만 잘못되어도 잘라진 것처럼 데이터가 유실될 수 있는 위험이 있습니다.
포인터 공간이 두 개이기 때문에 앞과 뒤의 노드 모두 가리킬 수 있는 리스트
이중 연결 리스트 | |
---|---|
접근 | O(n) |
검색 | O(n) |
삽입 | O(1) |
삭제 | O(1) |
접근, 검색 : 가장 마지막 원소를 찾으려면 배열처럼 처음부터 끝까지 찾아봐야 하기 때문에 시간복잡도는 O(n) 을 갖습니다.
하지만 이는 최악의 상황을 가정한 것이고, 만약 노드가 100
개인데 99
번째 노드에 접근하려고 한다면 tail
에서부터 접근하여 단 한 번의 이동만을 할 수 있습니다.
삽입, 삭제 : 연결리스트는 포인터가 주소를 참조하여 연결되는 방식이므로 원하는 값을 삽입 또는 삭제할 때 해당 주소로 가서 바로 삽입 또는 삭제가 가능합니다. 따라서 제일 빠른 시간복잡도인 O(1) 를 갖습니다.
양방향으로 접근하기 때문에 별도로 tail
이라는 변수가 필요하며 양방향의 연결을 구현해야하기때문에 추가, 삭제 연산이 복잡합니다.
단순 연결리스트에서 마지막 포인터가 참조하는 주소를 null -> 처음 노드 주소를 가리키는 것으로 변경한 연결리스트
구분 | 배열 | 연결리스트 |
---|---|---|
검색 | 데이터 검색 속도 빠름 | 데이터 검색 속도 느림 |
데이터 변경 | 데이터 추가/삭제 시 이동 | 데이터 추가/삭제 용이 |
기억 공간 | 정적 할당, 연속 공간 | 동적 할당, 불연속 공간 |
추가 기억 공간 | 추가 공간 없음 | 링크 필드 추가 |
// listNode : [1,2,3,4,5]
void display(ListNode *h)
{
while (h != NULL) {
printf("%d ", h->data);
h = h->link;
}
printf("\n");
}
Linked list - Data Structure (자료구조)
나무위키 - 연결리스트
[자료구조 Java] 이중 연결리스트(Doubly Linked List) 핵심 정리