contiguous-memorypointerrandom-access

Array와 Linked List의 차이를 설명해 주세요

면접 출제
예상 시간
5분
30초 답변

꼬리질문

조금 더 깊게 물어본다면

답변 뒤에 이어질 수 있는 질문들을 하나씩 열어볼 수 있어요.

배열에서 임의 위치 삽입과 삭제가 O(n)인 이유는?

시간 복잡도

연산ArrayLinked List
인덱스 접근O(1)O(1)O(n)O(n)
값 검색O(n)O(n)O(n)O(n)
삽입 (끝)O(1)O(1) amortized2O(1)O(1)
삽입 (중간)O(n)O(n)O(1)O(1) — 노드 참조 있을 때1
삭제 (끝)O(1)O(1)O(1)O(1)
삭제 (중간)O(n)O(n)O(1)O(1) — 노드 참조 있을 때1

부가 설명

둘의 차이는 저장 방식에서 시작됩니다. Array는 값들이 연속된 공간에 놓이기 때문에 arr[10]처럼 바로 위치를 계산할 수 있습니다. 반면 Linked List는 각 노드가 다음 노드의 위치를 들고 있어서, 열 번째 값을 보려면 앞에서부터 링크를 따라가야 합니다.

시간복잡도만 보면 Linked List가 중간 삽입에 항상 유리해 보일 수 있습니다. 하지만 삽입할 위치의 노드를 이미 알고 있을 때만 빠르고, 그 위치를 찾는 데 O(n)O(n)이 걸릴 수 있습니다. 실제 CPU 캐시 관점에서는 연속 메모리를 쓰는 Array가 순회에서 더 빠른 경우도 많습니다.

한 줄 정리

Array는 바로 찾기 좋고, Linked List는 연결을 바꾸기 좋지만 위치를 찾는 비용을 숨기면 안 됩니다.

Footnotes

  1. 코드 어딘가에 해당 노드를 가리키는 변수가 이미 있는 경우를 말한다. 노드끼리의 연결(next 포인터)과는 다른 이야기로, 위치를 모르면 head부터 순회해서 찾아야 하므로 탐색 비용 O(n)O(n)이 먼저 든다. ↩ ↩ ↩

  2. 분할상환 분석(amortized analysis). 일부 연산이 비싸더라도 전체 연산의 평균 비용이 낮을 때 쓰는 표현이다. 동적 배열은 확장 시 O(n)O(n)이 걸리지만, 2배씩 늘리면 n번 append의 총 비용이 O(n)O(n)이라 평균은 O(1)O(1)이 된다. ↩