연결리스트 - 배열이 더 빠른데 왜 굳이 연결 리스트를 배울까?

2025. 10. 31. 05:21·자료구조

1. 들어가며 

 연결 리스트(Linked List)는 데이터를 노드(Node) 단위로 저장하고 각 노드가 다음 노드의 참조(reference) 를 통해 서로 연결된 선형 자료구조입니다.

 

배열처럼 메모리에 연속적으로 저장되지 않으며 메모리의 임의 위치에 존재하는 노드들이 포인터(pointer) 를 통해 논리적으로 연결됩니다.

이 구조는 메모리의 불연속성을 극복하면서 유연하게 데이터를 관리할 수 있게 해줍니다.


2. 연결리스트 내부 구조 이해

각 노드는 일반적으로 다음 두 가지 정보를 가집니다.

  • data: 저장할 실제 데이터
  • next: 다음 노드의 주소(참조)
class Node {
    int data;
    Node next; // 다음 노드를 가리킴

    Node(int data) {
        this.data = data;
        this.next = null;
    }
}

리스트의 시작점은 head 노드가 가리킵니다.

head → [10 | *] → [20 | *] → [30 | null]

 

head 만 알고 있어도 순차 탐색 가능하지만 역방향 탐색은 불가능 합니다.(이 부분은 뒤의 ‘이중 연결 리스트’에서 해결됩니다.)

3. 종류별 비교

단일 연결 리스트 (Singly) 한 방향(next) 구현 단순, 메모리 효율 좋음 기본 리스트
이중 연결 리스트 (Doubly) 양방향(prev, next) 앞뒤 탐색 가능, 삽입/삭제 유연 LRU Cache, Deque
원형 연결 리스트 (Circular) 마지막 노드가 첫 노드 연결 순환 구조, 반복 탐색 가능 라운드 로빈 스케줄링

 4. 시간 복잡도 분석


접근(access) O(n) 임의 인덱스 접근 불가, 순차 탐색 필요
탐색(search) O(n) 모든 노드 순회
맨 앞 삽입(addFirst) O(1) 포인터만 변경
맨 뒤 삽입(addLast) O(n) (tail 없을 때) / O(1) (tail 유지 시)  
삭제(remove) O(n) 삭제 대상 이전 노드 탐색 필요
메모리 사용량 O(n) 포인터(참조) 추가로 인한 오버헤드
접근은 느리지만 구조 변경은 빠르다.
연결 리스트의 핵심은 ‘유연한 변경’입니다.

 5. 배열과 다른점 

항목배열(Array)연결 리스트(Linked List)
메모리 구조 연속된 공간 불연속, 포인터로 연결
접근 속도 O(1) O(n)
삽입/삭제 O(n) (이동 필요) O(1) (참조 변경)
크기 변경 불가능(정적) / 복사 필요(동적) 자유롭게 추가/삭제
캐시 효율 높음 (연속적) 낮음 (비연속적)
메모리 효율 우수 포인터로 인한 추가 사용
  • 배열은 CPU 캐시 친화적 → 빠른 순회
  • 연결 리스트는 구조 유연성 ↑, 메모리 효율 ↓

 6. 메모리 동작 원리

연결 리스트는 힙(Heap) 메모리에 노드를 동적으로 할당합니다. 새로운 데이터를 추가하면 다음과 같은 과정이 일어납니다.

  1. JVM(혹은 런타임)이 new 명령으로 메모리를 힙에 확보
  2. 새 노드를 생성하고 데이터 저장
  3. 이전 노드의 next 포인터가 새 노드를 가리킴

이 과정은 연속된 메모리를 요구하지 않아 단편화(fragmentation) 가 심한 환경에서도 유연하게 동작합니다.


7. 삽입 / 삭제 

 삽입 (insert after)

Node newNode = new Node(25);
newNode.next = prev.next;
prev.next = newNode;

 

기존 노드를 밀어내지 않고 포인터만 교체합니다.

 

 

 삭제 (delete)

prev.next = prev.next.next;​

삭제 대상의 참조를 끊으면 GC(가비지 컬렉터)가 자동 해제합니다.(단, C언어 등에서는 free()로 직접 메모리 해제해야 함.)

 


8. 자바(Java) 예제 구현

 
public class LinkedList {
    private Node head;

    private static class Node {
        int data;
        Node next;
        Node(int data) { this.data = data; }
    }

    public void addFirst(int data) {
        Node node = new Node(data);
        node.next = head;
        head = node;
    }

    public void addLast(int data) {
        Node node = new Node(data);
        if (head == null) {
            head = node;
            return;
        }
        Node cur = head;
        while (cur.next != null) {
            cur = cur.next;
        }
        cur.next = node;
    }

    public void remove(int data) {
        if (head == null) return;
        if (head.data == data) {
            head = head.next;
            return;
        }
        Node cur = head;
        while (cur.next != null && cur.next.data != data) {
            cur = cur.next;
        }
        if (cur.next != null) cur.next = cur.next.next;
    }

    public void printList() {
        Node cur = head;
        while (cur != null) {
            System.out.print(cur.data + " -> ");
            cur = cur.next;
        }
        System.out.println("null");
    }
}

9. 언어별 구현 비교

언어기본 구조체메모리 해제특징
C 포인터 사용 (struct Node*) 직접 free() 필요 저수준 제어 가능
Java 참조(reference) 기반 GC가 자동 해제 안전하지만 약간 느림
Python 객체 참조 + 동적 타입 자동 관리 리스트(list)는 배열 기반
C++ STL std::list 자동 관리 Doubly Linked List 기본 제공

10. 시간복잡도 총정리

연산연결 리스트배열
접근(access) O(n) O(1)
맨 앞 삽입(addFirst) O(1) O(n)
맨 뒤 삽입(addLast) O(1)* (tail 있을 경우) O(1) amortized
삭제(remove) O(n) O(n)
탐색(search) O(n) O(n)
공간복잡도 O(n) O(n)
캐시효율 낮음 높음

11. 연결 리스트의 실질적 한계

많은 개발자들이 “삽입/삭제가 빠르다”는 이유만으로 연결 리스트를 선호하지만 현대 CPU 환경에서는 배열 기반 구조가 더 빠른 경우가 많습니다.

그 이유는 다음과 같습니다.

  • 배열은 연속 메모리 덕분에 캐시 히트율이 압도적
  • 연결 리스트는 각 노드 접근 시 추가 포인터 참조 연산 발생
  • 작은 규모에서는 연결 리스트의 “O(1)” 삽입이 실질적으로 더 느릴 수 있음

즉, 연결 리스트의 강점은 “빅오 표기상의 이론적 효율”보다 “구조적 유연성”에 있습니다.


12.  연결리스트를 알아야 하는 이유

연결리스트를 이해하면 데이터가 서로 ‘어떻게 연결되어 흘러가는지’ 보이기 시작합니다.

 “배열은 정적인 세상에서 강하고, 연결 리스트는 변화하는 세상에서 강하다.”

 

13. 요약 및 결론


정의 데이터와 포인터로 이루어진 노드들의 연결 구조
 장점 삽입/삭제 O(1), 유연한 크기 관리
 단점 접근 O(n), 캐시 비효율, 메모리 오버헤드
 사용 시점 삽입/삭제가 잦고 데이터 크기가 가변적일 때
 피해야 할 시점 탐색/조회 위주 로직, 실시간 고성능 시스템

 

  정리

연결 리스트는 “메모리의 불연속성을 극복하는 유연한 구조” 배열은 “빠른 접근성과 캐시 효율을 극대화한 구조”

현대 환경에서는 배열 기반 구조(ArrayList) 가 더 자주 쓰이지만 스택, 큐, 그래프, 캐시 같은 “구조적 연결”이 중요한 곳에서는 여전히 필수입니다

 

저작자표시 비영리 (새창열림)

'자료구조' 카테고리의 다른 글

스택(Stack): 마지막에 쌓은 것을 가장 먼저 꺼내는 구조  (0) 2025.10.31
배열  (0) 2025.10.29
'자료구조' 카테고리의 다른 글
  • 스택(Stack): 마지막에 쌓은 것을 가장 먼저 꺼내는 구조
  • 배열
깊은바다속꼬북이
깊은바다속꼬북이
  • 깊은바다속꼬북이
    CodeBlossom
    깊은바다속꼬북이
  • 전체
    오늘
    어제
    • 분류 전체보기 (53) N
      • 라이징 캠프 (4)
      • 객채지향 개발론 (3)
      • 스프링 (10) N
      • 네트워크 (2)
      • 자바 (16)
      • 자료구조 (3)
      • 운영체제 (0)
      • 데이터베이스 (4)
      • 디자인패턴 (7)
      • JSP (1)
      • 개발 알쓸신잡 (2)
      • 일반 교양 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    자료구조
    스프링
    JVM
    java data area
    JUnnit5
    mockito라이브러리
    jvm 클래스 로더
    jit-compiler
    java
    템플릿 메서드 패턴(Template Method Pattern)
    junnit5프레임워크
    개발자 철학
    객체지향
    MySQL 파서
    백엔드
    디자인 패턴
    한국어 검색
    트랜잭션 전파레벨
    개발 교훈
    개발 철학
    디자인패턴
    싱글턴 패턴(Singleton Pattern)
    MySQL 옵티마이저
    어댑터 패턴(Adapter Pattern)
    전략 패턴(Strategy Pattern)
    GC
    java 버전별 특징
    spring
    자바 Socket 클래스
    프로그램밍 언어
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
깊은바다속꼬북이
연결리스트 - 배열이 더 빠른데 왜 굳이 연결 리스트를 배울까?
상단으로

티스토리툴바