ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Data Structure] 링크드리스트
    Data Structure 2024. 5. 18. 01:27

    링크드리스트(linked_list) 자료구조에 대해 정리하였습니다.


     


    < 종류별 링크드 리스트 >

    [ 단일 링크드 리스트 (Singly Linked List) ]

    단일 링크드 리스트

     

    • 각 노드는 데이터와 다음 노드를 가리키는 하나의 포인터를 포함합니다.
    • 마지막 노드의 포인터는 null을 가리키며 리스트의 끝을 나타냅니다.
    Node1 -> Node2 -> Node3 -> null

     

     

    [ 이중 링크드 리스트 (Doubly Linked List) ]

    이중 링크드 리스트

     

    • 각 노드는 데이터를 포함하며, 다음 노드를 가리키는 포인터와 이전 노드를 가리키는 포인터를 가지고 있습니다.
    • 양방향 탐색이 가능하다는 장점이 있습니다.
    null <- Node1 <-> Node2 <-> Node3 -> null

     

     

    [ 원형 링크드 리스트 (Circular Linked List) ]

    원형 링크드 리스트

     

    • 마지막 노드가 첫 번째 노드를 가리키도록 연결되어 있습니다.
    • 단일 및 이중 링크드 리스트 형태로 구현될 수 있습니다.
    Node1 -> Node2 -> Node3 -> Node1 (단일 원형 링크드 리스트)
    null <- Node1 <-> Node2 <-> Node3 <-> Node1 (이중 원형 링크드 리스트)

     

     


    < 장/단점 >

    [ 장점 ]

    • 동적 크기를 가지며, 크기를 사전에 정의할 필요가 없습니다.
    • 삽입과 삭제가 배열에 비해 효율적입니다. (특히 리스트의 시작 부분에서)

     

    [ 단점 ]

    • 임의 접근이 불가능하여 특정 위치의 노드를 찾기 위해서는 처음부터 순차적으로 탐색해야 합니다.
    • 각 노드가 추가적인 포인터를 저장하기 때문에 배열보다 메모리 오버헤드가 발생합니다.

     

     


    < 주요 연산 >

    1. 삽입 (Insertion)
      • 리스트의 시작 부분, 중간, 끝 부분에 노드를 삽입합니다.
      • 시작 부분 삽입의 경우: 새 노드의 다음 포인터를 현재 첫 번째 노드를 가리키도록 설정하고, 헤드를 새 노드로 변경합니다.
      • 중간 삽입의 경우: 삽입 위치의 이전 노드와 다음 노드를 각각 새 노드와 연결합니다.
    2. 삭제 (Deletion)
      • 특정 위치에 있는 노드를 삭제합니다.
      • 시작 부분 삭제의 경우: 헤드를 현재 첫 번째 노드의 다음 노드로 변경합니다.
      • 중간 삭제의 경우: 삭제할 노드의 이전 노드의 포인터를 삭제할 노드의 다음 노드를 가리키도록 변경합니다.
    3. 탐색 (Search)
      • 특정 값을 가지는 노드를 찾기 위해 리스트를 순차적으로 탐색합니다.
    4. 출력 (Display)
      • 리스트에 있는 모든 노드를 순차적으로 출력합니다.
    5. 반전 (Reverse)
      • 리스트를 반전시킵니다. prev, current, next 포인터를 사용하여 리스트의 노드들을 뒤집습니다.

     

     


    < 구현 : 단일 링크드 리스트 >

    class Node {
        constructor(data) {
            this.data = data;
            this.next = null;
        }
    }
    
    class SinglyLinkedList {
        constructor() {
            this.head = null;
        }
    
        // 시작 부분 삽입
        insertAtBeginning(data) {
            const newNode = new Node(data);
            newNode.next = this.head;
            this.head = newNode;
        }
    
        // 중간 삽입
        insertAtPosition(data, position) {
            if (position === 0) {
                this.insertAtBeginning(data);
                return;
            }
            const newNode = new Node(data);
            let current = this.head;
            let previous = null;
            let index = 0;
    
            while (index < position && current !== null) {
                previous = current;
                current = current.next;
                index++;
            }
    
            if (current === null) {
                console.log("Position out of bounds");
                return;
            }
    
            newNode.next = current;
            previous.next = newNode;
        }
    
        // 끝 부분 삽입
        append(data) {
            const newNode = new Node(data);
            if (!this.head) {
                this.head = newNode;
                return;
            }
            let current = this.head;
            while (current.next) {
                current = current.next;
            }
            current.next = newNode;
        }
    
        // 시작 부분 삭제
        deleteAtBeginning() {
            if (this.head) {
                this.head = this.head.next;
            }
        }
    
        // 중간 삭제
        deleteAtPosition(position) {
            if (position === 0) {
                this.deleteAtBeginning();
                return;
            }
            let current = this.head;
            let previous = null;
            let index = 0;
    
            while (index < position && current !== null) {
                previous = current;
                current = current.next;
                index++;
            }
    
            if (current === null) {
                console.log("Position out of bounds");
                return;
            }
    
            previous.next = current.next;
        }
    
        // 끝 부분 삭제
        deleteAtEnd() {
            if (!this.head) {
                return;
            }
            if (!this.head.next) {
                this.head = null;
                return;
            }
            let current = this.head;
            while (current.next && current.next.next) {
                current = current.next;
            }
            current.next = null;
        }
    
        // 탐색
        search(data) {
            let current = this.head;
            while (current) {
                if (current.data === data) {
                    return true;
                }
                current = current.next;
            }
            return false;
        }
    
        // 출력
        display() {
            let current = this.head;
            let listString = '';
            while (current) {
                listString += current.data + ' -> ';
                current = current.next;
            }
            listString += 'null';
            console.log(listString);
        }
    
        // 반전
        reverse() {
            let prev = null;
            let current = this.head;
            let next = null;
            while (current) {
                next = current.next;
                current.next = prev;
                prev = current;
                current = next;
            }
            this.head = prev;
        }
    }
    
    // 사용 예제
    const sll = new SinglyLinkedList();
    sll.append(1);
    sll.append(2);

     

     

     

     

    'Data Structure' 카테고리의 다른 글

    [Data Structure] BST (Binary Search Tree)  (0) 2024.05.24
    [Data Structure] 힙(Heap)  (0) 2024.05.19
    [Data Structure] 큐(Queue) & 스택(Stack)  (0) 2024.05.16

    댓글

Designed by Tistory.