(JS 자료구조)이중 연결 리스트

정태호·2023년 3월 24일
0

이중 연결 리스트(Doubly Linked List)

  • 이중 연결 리스트는 단일 연결 리스트에서 이전의 노드를 가리키는 포인터를 하나 더하는 것 뿐이다. 각각의 노드에 포인터 가 두 개씩 있게 된다.
  • 이중 연결 리스트는 이처럼 반대 방향 포인터도 갖게 되어 성능상 유연함을 갖게 됐지만, 더 많은 메모리가 필요하게 됐다.(next,previous)

기본 구조

class Node {
  constructor(val) {
    this.val = val;
    this.next = null;
    this.prev = null;
  }
}

class DoublyLinkedList {
  constructor() {
    this.head = null;
    this.tail = null;
    this.length = 0;
  }
}

DoublyLinkedList

class DoublyLinkedList{
    constructor(){
        this.tail = null;
        this.head = null;
        this.length = 0;
    }

    push(val){
        let pushval = new Node(val);
        if(!this.head){
            this.head = pushval;
            this.tail = this.head;
        }else{
            this.tail.next = pushval;
            pushval.prev = this.tail;
            this.tail = pushval;
        }
        
        this.length++;
        return this;
    }

    pop(){
        if(!this.head) return undefined;
        let temp = this.tail;
        if(this.length === 1){
            this.head = null;
            this.tail = null;
        }else{
            this.tail = temp.prev;
            this.tail.next = null;
            temp.prev = null;
        }
        this.length--;
        return temp; 
    }

    shift(){
        if(!this.head) return undefined;
        let temp1 = this.head;
        if(this.length === 1){
            this.head = null;
            this.tail = null;
        }else{
            this.head = temp1.next;
            this.head.prev = null;
            temp1.next = null;
        }
        this.length--;
        return temp1;
    }

    unshift(val){
        let unshiftval = new Node(val);
        if(!this.head){
            this.head = unshiftval;
            this.tail = unshiftval;
        }else{
            this.head.prev = unshiftval;
            unshiftval.next = this.head;
            this.head = unshiftval;
        }
        this.length++;
        return this;
    }

    get(index){
        if(index < 0 || index >= this.length) return null;
        
        let count = 0;
        let result = 0;
        if(index <= this.length/2){
            result = this.head;
            while(count !== index){
                result = result.next;
                count++;
            }
        }else{
            count = this.length-1;
            result = this.tail;
            while(count !== index){
                result = result.prev;
                count--;
            }
        }
        return result;
    }

    set(index,val){
        let foundindex = this.get(index);
        if(foundindex){
            foundindex.val = val;
            return true;
        }
        return false;
    }

    insert(index,val){
        if(index < 0 || index > this.length) return false;
        let insertval = new Node(val);
        if(index === 0) return !!this.unshift(val);
        if(index === this.length) return !!this.push(val);

        let findindex = this.get(index-1);
        let temp3 = findindex.next;
        
        findindex.next = insertval, insertval.prev = findindex;
        temp3.prev = insertval, insertval.next = temp3;
        this.length++;
        return true;
    }

    remove(index){
        if(index < 0 || index >= this.length) return false;
        if(index === 0) return this.shift();
        if(index === this.length-1) return this.pop();

        let removeNode = this.get(index);
        removeNode.prev.next = removeNode.next;
        removeNode.next.prev = removeNode.prev;
        removeNode.next = null;
        removeNode.prev = null;
        
        this.length--;
        return removeNode;
    }
}

이중 연결 리스트의 성능

시간복잡도

  • 삽입 : O(1)
  • 제거 : O(1)
  • 탐색 : O(N)
  • 접근 : O(N)

결론

  • 이중 연결 리스트는 이전 노드를 향하는 포인터가 추가됐다는 점만 빼면 단일 연결 리스트와 거의 비슷하다.
  • 노드를 찾을 때는 이중 연결 리스트가 단일 연결리스트보다 시간을 절반으로 줄일 수 있으므로 더 낫다. 이 외의 이중 연결 리스트의 시간복잡도는 단일 연결 리스트의 성능과 같다.
  • 이중 연결 리스트는 추가 포인터 때문에 더 많은 메모리가 필요하다.
  • 배열에 비해 삽입과 제거에 유용하다.
profile
주니어 프론트엔드 개발자가 되고 싶습니다!

0개의 댓글