๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๋นˆ ๊ตฌ๋ฉ ์ฑ„์šฐ๊ธฐ

[Java] LinkedList ๊ตฌํ˜„

์ถœ์ฒ˜

ChatGPT

์ž๋ฐ” 1.8 ์†Œ์Šค ์ฝ”๋“œ


์ž๋ฐ”์˜ LinkedList ํด๋ž˜์Šค๋Š” List, Deque, Queue ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ์ด์ค‘ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ(doubly linked list) ์ž๋ฃŒ๊ตฌ์กฐ์ด๋‹ค. ์ด์ค‘ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ๋Š” ๊ฐ ๋…ธ๋“œ๊ฐ€ ๋‘ ๊ฐœ์˜ ์ฐธ์กฐ๋ฅผ ๊ฐ€์ง€๋ฉฐ, ํ•˜๋‚˜๋Š” ์ด์ „ ๋…ธ๋“œ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ณ , ๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” ๋‹ค์Œ ๋…ธ๋“œ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. ์ด๋กœ ์ธํ•ด ์‚ฝ์ž…๊ณผ ์‚ญ์ œ ์ž‘์—…์ด ๋น ๋ฅต ์ˆ˜ํ–‰๋  ์ˆ˜ ์žˆ๋‹ค.

 

1. LinkedLists ์ฃผ์š” ํŠน์ง•

์ด์ค‘ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ

LinkedList๋Š” ์ด์ค‘ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ์–ด ์‚ฝ์ž…๊ณผ ์‚ญ์ œ๊ฐ€ ๋น ๋ฅด๋‹ค. ๋ฆฌ์ŠคํŠธ์ด ์ค‘๊ฐ„์— ์žˆ๋Š” ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์‚ญ์ œํ•  ๋•Œ, ์ธ๋ฑ์Šค๋ฅผ ์ฐพ์•„๊ฐ€๋Š” ์‹œ๊ฐ„์ด ํ•„์š”ํ•˜์ง€๋งŒ ์š”์†Œ์˜ ์ถ”๊ฐ€/์‚ญ์ œ ์ž‘์—… ์ž์ฒด๋ฅผ ๋น ๋ฅด๊ฒŒ ์ด๋ฃจ์–ด์ง„๋‹ค.

์–‘๋ฐฉํ–ฅ ํƒ์ƒ‰ ๊ฐ€๋Šฅ

์ด์ค‘ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ๋Š” ๋ฆฌ์ŠคํŠธ์˜ ์•ž์—์„œ๋ถ€ํ„ฐ ๋˜๋Š” ๋’ค์—์„œ๋ถ€ํ„ฐ ํƒ์ƒ‰ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ ์•ž์ชฝ์ด๋‚˜ ๋’ค์ชฝ์— ์ƒˆ๋กœ์šด ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์ œ๊ฑฐํ•˜๋Š” ์ž‘์—…์ด ๋น ๋ฅด๋‹ค.

๋™๊ธฐํ™”๋˜์ง€ ์•Š์Œ

LinkedList๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋™๊ธฐํ™”๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์™ธ๋ถ€์ ์œผ๋กœ ๋™๊ธฐํ™” ์ฒ˜๋ฆฌํ•ด์•ผ ํ•œ๋‹ค.

์ค‘๊ฐ„ ์‚ฝ์ž…/์‚ญ์ œ์— ์œ ๋ฆฌ

๋ฐฐ์—ด ๊ธฐ๋ฐ˜ ์ž๋ฃŒ๊ตฌ์กฐ์ธ ArrayList์™€ ๋‹ฌ๋ฆฌ, LinkedList๋Š” ์ค‘๊ฐ„์— ์‚ฝ์ž… ๋˜๋Š” ์‚ญ์ œํ•˜๋Š” ์ž‘์—…์ด ํšจ์œจ์ €๊ฑฐ์ด๋‹ค. ํ•˜์ง€๋งŒ ํŠน์ • ์ธ๋ฑ์Šค์— ์ ‘๊ทผํ•  ๋•Œ๋Š” ํƒ์ƒ‰ ์‹œ๊ฐ„์ด ํ•„์š”ํ•˜๋‹ค.

 

2. LinkedList์˜ ํด๋ž˜์Šค ์„ ์–ธ

public class LinkedList<E> extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable {
    // LinkedList์˜ ํฌ๊ธฐ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๋ณ€์ˆ˜
    transient int size = 0;

    // ์ฒซ ๋ฒˆ์งธ ๋…ธ๋“œ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ฐธ์กฐ
    transient Node<E> first;

    // ๋งˆ์ง€๋ง‰ ๋…ธ๋“œ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ฐธ์กฐ
    transient Node<E> last;

    // LinkedList์˜ ๊ฐ ๋…ธ๋“œ๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ๋‚ด๋ถ€ ํด๋ž˜์Šค Node
    private static class Node<E> {
        E item;         // ๋…ธ๋“œ์— ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ
        Node<E> next;   // ๋‹ค์Œ ๋…ธ๋“œ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ฐธ์กฐ
        Node<E> prev;   // ์ด์ „ ๋…ธ๋“œ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ฐธ์กฐ

        Node(Node<E> prev, E element, Node<E> next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
    }

    // ๊ธฐํƒ€ ๋ฉ”์„œ๋“œ ์ƒ๋žต...
}

 

LinkedList๋Š” List์™€ Deque ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, ์ด์ค‘ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ ๊ตฌ์กฐ๋กœ ๋˜์–ด ์žˆ๋‹ค. ๋ฆฌ์ŠคํŠธ์˜ ๊ฐ ์š”์†Œ๋Š” Node ๊ฐ์ฒด๋กœ ํ‘œํ˜„๋˜๋ฉฐ, Node๋Š” item, next, prev ์„ธ ๊ฐœ์˜ ํ•„๋“œ๋ฅผ ๊ฐ€์ง„๋‹ค.

  • first : ๋ฆฌ์ŠคํŠธ์˜ ์ฒซ ๋ฒˆ์งธ ์š”์†Œ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ฐธ์กฐ์ด๋‹ค.
  • last : ๋ฆฌ์ŠคํŠธ์˜ ๋งˆ์ง€๋ง‰ ์š”์†Œ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ฐธ์กฐ์ด๋‹ค.

 

3. ์ฃผ์š” ๋ฉ”์†Œ๋“œ์˜ ๊ตฌํ˜„

1. add(E e)

LinkedList์—์„œ ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” add ๋ฉ”์†Œ๋“œ๋Š” ๋ฆฌ์ŠคํŠธ์˜ ๋์— ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ์ž‘์—…์ด๋‹ค. ์ƒˆ๋กœ์šด ๋…ธ๋“œ๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์ด๋ฅผ ๋ฆฌ์ŠคํŠธ์˜ ๋์— ์—ฐ๊ฒฐํ•œ๋‹ค.

public boolean add(E e) {
    linkLast(e);
    return true;
}

void linkLast(E e) {
    final Node<E> l = last;
    final Node<E> newNode = new Node<>(l, e, null);  // ๋งˆ์ง€๋ง‰์— ์ƒˆ๋กœ์šด ๋…ธ๋“œ ์ƒ์„ฑ
    last = newNode;
    if (l == null)  // ๋ฆฌ์ŠคํŠธ๊ฐ€ ๋น„์–ด ์žˆ๋Š” ๊ฒฝ์šฐ
        first = newNode;
    else
        l.next = newNode;
    size++;
    modCount++;
}

 

  • linkLast(E e) ๋ฉ”์†Œ๋“œ๋Š” ์ƒˆ๋กœ์šด ์š”์†Œ๋ฅผ ๋งˆ์ง€๋ง‰ ๋…ธ๋“œ๋กœ ์ถ”๊ฐ€ํ•œ๋‹ค.
  • last ์ฐธ์กฐ๊ฐ€ null์ด๋ฉด ๋ฆฌ์ŠคํŠธ๊ฐ€ ๋น„์–ด ์žˆ์Œ์„ ์˜๋ฏธํ•˜๋ฏ€๋กœ, ์ƒˆ ๋…ธ๋“œ๋ฅผ first๋กœ ์„ค์ •ํ•œ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๋งˆ์ง€๋ง‰ ๋…ธ๋“œ์˜ next ํ•„๋“œ์— ์ƒˆ ๋…ธ๋“œ๋ฅผ ์—ฐ๊ฒฐํ•œ๋‹ค.

2. remove(Object o)

remove ๋ฉ”์†Œ๋“œ๋Š” ๋ฆฌ์ŠคํŠธ์—์„œ ํŠน์ • ๊ฐ์ฒด๋ฅผ ์‚ญ์ œํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค. ๊ฐ์ฒด๊ฐ€ ๋ฆฌ์ŠคํŠธ์— ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธํ•œ ํ›„, ํ•ด๋‹น ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋…ธ๋“œ๋ฅผ ์ œ๊ฑฐํ•œ๋‹ค.

public boolean remove(Object o) {
    if (o == null) {
        for (Node<E> x = first; x != null; x = x.next) {
            if (x.item == null) {
                unlink(x);
                return true;
            }
        }
    } else {
        for (Node<E> x = first; x != null; x = x.next) {
            if (o.equals(x.item)) {
                unlink(x);
                return true;
            }
        }
    }
    return false;
}

E unlink(Node<E> x) {
    final E element = x.item;
    final Node<E> next = x.next;
    final Node<E> prev = x.prev;

    if (prev == null) {
        first = next;
    } else {
        prev.next = next;
        x.prev = null;
    }

    if (next == null) {
        last = prev;
    } else {
        next.prev = prev;
        x.next = null;
    }

    x.item = null;
    size--;
    modCount++;
    return element;
}

 

  • ๊ฐ์ฒด๋ฅผ ํƒ์ƒ‰ : ๋ฆฌ์ŠคํŠธ๋ฅผ ์ˆœํšŒํ•˜๋ฉด์„œ, ์‚ญ์ œํ•˜๋ ค๋Š” ๊ฐ์ฒด๋ฅผ ์ฐพ๋Š”๋‹ค.
  • ๋…ธ๋“œ ์ œ๊ฑฐ : unlink(Node<E> x) ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด, ๋Œ€์ƒ ๋…ธ๋“œ๋ฅผ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ์—์„œ ์ œ๊ฑฐํ•œ๋‹ค. ๋…ธ๋“œ์˜ ์ด์ „ ๋…ธ๋“œ์™€ ๋‹ค์Œ ๋…ธ๋“œ๋ฅผ ์„œ๋กœ ์—ฐ๊ฒฐํ•˜๊ณ , ํ˜„์žฌ ๋…ธ๋“œ๋ฅผ null๋กœ ๋งŒ๋“ ๋‹ค.

3. get(int index)

get ๋ฉ”์†Œ๋“œ๋Š” ์ฃผ์–ด์ง„ ์ธ๋ฑ์Šค์— ์žˆ๋Š” ์š”์†Œ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์ธ๋ฑ์Šค์— ๋”ฐ๋ผ ๋ฆฌ์ŠคํŠธ์˜ ์•ž ๋˜๋Š” ๋’ค์—์„œ๋ถ€ํ„ฐ ์ˆœํšŒํ•˜์—ฌ ํ•ด๋‹น ์š”์†Œ๋ฅผ ์ฐพ๋Š”๋‹ค.

public E get(int index) {
    checkElementIndex(index);  // ์ธ๋ฑ์Šค๊ฐ€ ์œ ํšจํ•œ์ง€ ํ™•์ธ
    return node(index).item;
}

Node<E> node(int index) {
    if (index < (size >> 1)) {  // ์ธ๋ฑ์Šค๊ฐ€ ๋ฆฌ์ŠคํŠธ์˜ ์ค‘๊ฐ„๋ณด๋‹ค ์•ž์— ์žˆ์œผ๋ฉด
        Node<E> x = first;
        for (int i = 0; i < index; i++)
            x = x.next;
        return x;
    } else {  // ์ธ๋ฑ์Šค๊ฐ€ ๋ฆฌ์ŠคํŠธ์˜ ์ค‘๊ฐ„๋ณด๋‹ค ๋’ค์— ์žˆ์œผ๋ฉด
        Node<E> x = last;
        for (int i = size - 1; i > index; i--)
            x = x.prev;
        return x;
    }
}

 

  • ํƒ์ƒ‰ ์ตœ์ ํ™” : ์ธ๋ฑ์Šค๊ฐ€ ๋ฆฌ์ŠคํŠธ์˜ ์ค‘๊ฐ„๋ณด๋‹ค ์•ž์— ์žˆ์œผ๋ฉด first๋ถ€ํ„ฐ, ์ค‘๊ฐ„๋ณด๋‹ค ๋’ค์— ์žˆ์œผ๋ฉด last๋ถ€ํ„ฐ ํƒ์ƒ‰ํ•ด ํšจ์œจ์ ์œผ๋กœ ์š”์†Œ๋ฅผ ์ฐพ๋Š”๋‹ค.
  • ์‹œ๊ฐ„ ๋ณต์žก๋„ : ์ตœ์•…์˜ ๊ฒฝ์šฐ O(n) ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฌ๋ฉฐ, ๋ฆฌ์ŠคํŠธ์˜ ์ค‘๊ฐ„์— ๊ฐ€๊นŒ์šด ์ธ๋ฑ์Šค์ผ์ˆ˜๋ก ํƒ์ƒ‰ ์‹œ๊ฐ„์ด ๊ธธ์–ด์ง„๋‹ค.

4. addFirst(E e), addLast(E e), removeFirsts(), removeLast()

LinkedList๋Š” Deque ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋ฏ€๋กœ, ๋ฆฌ์ŠคํŠธ์˜ ์•ž๊ณผ ๋’ค์—์„œ ์š”์†Œ๋ฅผ ์‚ฝ์ž…ํ•˜๊ฑฐ๋‚˜ ์ œ๊ฑฐํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋„ ์ œ๊ณตํ•œ๋‹ค.

public void addFirst(E e) {
    linkFirst(e);
}

public void addLast(E e) {
    linkLast(e);
}

public E removeFirst() {
    final Node<E> f = first;
    if (f == null)
        throw new NoSuchElementException();
    return unlinkFirst(f);
}

public E removeLast() {
    final Node<E> l = last;
    if (l == null)
        throw new NoSuchElementException();
    return unlinkLast(l);
}

 

์ด ๋ฉ”์†Œ๋“œ๋“ค์€ ๋ฆฌ์ŠคํŠธ์˜ ์–‘ ๋์—์„œ ์‚ฝ์ž…๊ณผ ์‚ญ์ œ๋ฅผ ์ง€์›ํ•˜๋ฉฐ, O(1) ์‹œ๊ฐ„ ๋ณต์žก๋„๋กœ ์‹คํ–‰๋œ๋‹ค.

 

4. ์‹œ๊ฐ„ ๋ณต์žก๋„

์‚ฝ์ž…๊ณผ ์‚ญ์ œ

๋ฆฌ์ŠคํŠธ์˜ ์–‘ ๋์—์„œ ์‚ฝ์ž…๊ณผ ์‚ญ์ œ๋Š” O(1) ์‹œ๊ฐ„ ๋ณต์žก๋„๋ฅผ ๊ฐ€์ง„๋‹ค. ๋ฆฌ์ŠคํŠธ์˜ ์ค‘๊ฐ„์—์„œ ์‚ฝ์ž…์ด๋‚˜ ์‚ญ์ œ๋Š” ํŠน์ • ์ธ๋ฑ์Šฌ๋ฅด ์ฐพ๊ธฐ ์œ„ํ•ด ํƒ์ƒ‰ ์‹œ๊ฐ„์ด ํ•„์š”ํ•˜๋ฏ€๋กœ O(n) ์‹œ๊ฐ„ ๋ณต์žก๋„๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

ํƒ์ƒ‰

์ธ๋ฑ์Šค๋ฅผ ํ†ตํ•ด ์š”์†Œ๋ฅผ ์ฐพ๋Š” ์ž‘์—…์€ O(n) ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฐ๋‹ค. ๋ฐฐ์—ด ๊ธฐ๋ฐ˜์ธ ArrayList์™€ ๋‹ฌ๋ฆฌ, LinkedList๋Š” ์ž„์˜ ์ ‘๊ทผ์ด ๋น ๋ฅด์ง€ ์•Š๋‹ค.

 

5. LinkedList vs ArrayList

  • LinkedList๋Š” ์š”์†Œ์˜ ์ค‘๊ฐ„์— ์‚ฝ์ž… ๋ฐ ์‚ญ์ œ๊ฐ€ ๋นˆ๋ฒˆํ•  ๋•Œ ์œ ๋ฆฌํ•˜๋‹ค. ํŠนํžˆ ๋ฆฌ์ŠคํŠธ ์•ž ๋’ค์— ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์ œ๊ฑฐํ•˜๋Š” ๊ฒฝ์šฐ ๋น ๋ฅธ ์„ฑ๋Šฅ์„ ๋ฐœํœ˜ํ•œ๋‹ค.
  • ArrayList๋Š” ์ž„์˜ ์ ‘๊ทผ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ์— ๋” ์ ํ•ฉํ•˜๋‹ค. ๋ฐฐ์—ด ๊ธฐ๋ฐ˜์ด๋ฏ€๋กœ ์ธ๋ฑ์Šค ๊ธฐ๋ฐ˜์˜ ์š”์†Œ ์ ‘๊ทผ์ด ๋น ๋ฅด๋ฉฐ, ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์„ฑ ๋ฉด์—์„œ๋„ ๋” ์ข‹์„ ์ˆ˜ ์žˆ๋‹ค.

 

๊ฒฐ๋ก 

์ž๋ฐ”์˜ LinkedList๋Š” ์ด์ค‘ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ์œผ๋ฉฐ, ์–‘๋ฐฉํ–ฅ ํƒ์ƒ‰์ด ๊ฐ€๋Šฅํ•˜๊ณ  ์‚ฝ์ž…๊ณผ ์‚ญ์ œ๊ฐ€ ๋น ๋ฅด๋‹ค. List, Deque, Queue ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•ด ๋‹ค์–‘ํ•˜๋‚˜ ์ž๋ฃŒ๊ตฌ์กฐ๋กœ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์š”์†Œ์˜ ์ค‘๊ฐ„ ์‚ฝ์ž…/์‚ญ์ œ ์ž‘์—…์ด ๋งŽ์€ ๊ฒฝ์šฐ์— ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ž„์˜ ์ ‘๊ทผ ์†๋„๊ฐ€ ๋Š๋ฆฌ๋ฏ€๋กœ, ์ž์ฃผ ์‚ฌ์šฉ๋˜๋Š” ์ž‘์—…์— ๋งž๋Š” ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ์„ ํƒํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•˜๋‹ค.