์ถ์ฒ
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 ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํด ๋ค์ํ๋ ์๋ฃ๊ตฌ์กฐ๋ก ํ์ฉํ ์ ์์ผ๋ฉฐ, ์์์ ์ค๊ฐ ์ฝ์ /์ญ์ ์์ ์ด ๋ง์ ๊ฒฝ์ฐ์ ์ ์ฉํฉ๋๋ค. ํ์ง๋ง ์์ ์ ๊ทผ ์๋๊ฐ ๋๋ฆฌ๋ฏ๋ก, ์์ฃผ ์ฌ์ฉ๋๋ ์์ ์ ๋ง๋ ์๋ฃ๊ตฌ์กฐ๋ฅผ ์ ํํ๋ ๊ฒ์ด ์ค์ํ๋ค.
'๋น ๊ตฌ๋ฉ ์ฑ์ฐ๊ธฐ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Java] Fail-fast ๋ฉ์ปค๋์ฆ (0) | 2024.09.11 |
---|---|
[Java] Map์์๋ Collection View๋ฅผ ์ฌ์ฉํ๋ค. (0) | 2024.09.11 |
[Java] HashSet์ load factor (0) | 2024.09.10 |
[Java] TreeSet ๊ตฌํ (1) | 2024.09.10 |
[์๋ฃ ๊ตฌ์กฐ] ๋ ๋-๋ธ๋ ํธ๋ฆฌ Red-Black Tree (1) | 2024.09.09 |