๐คLinked List๋?
: Node๋ผ๋ ๊ตฌ์กฐ์ฒด๊ฐ ์ฐ๊ฒฐ๋๋ ํ์์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ ์๋ฃ๊ตฌ์กฐ๋ฅผ ๋งํ๋ค.
๐Node: ๋ฐ์ดํฐ ๊ฐ(value)๊ณผ ๋ค์ ์ฃผ์๊ฐ(next)๋ก ๊ตฌ์ฑ๋์ด ์๋ ๊ตฌ์กฐ์ฒด

๐ปNode๋ ๊ฐ๋จํ๊ฒ ๋ค์๊ณผ ๊ฐ์ด ํด๋์ค๋ก ๊ตฌํํ ์ ์๋ค
class Node:
def __init__(self, value = 0, next = None):
self.value = value
self.next = next
๐ก์ง๋ ์๊ฐ์ ์ดํด๋ณธ Array๋ ๋ฉ๋ชจ๋ฆฌ์ Random Access๋ฅผ ์ด์ฉํด์ ์์ฐจ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ ๋ฐฉ์์ ์ฌ์ฉํ์์ง๋ง, Linked List๋ next ํฌ์ธํฐ๋ก ๋ค์ ๋ ธ๋์ ์ฃผ์๋ฅผ ์ ์ฅํ๋ฉด ๋ ผ๋ฆฌ์ ์ผ๋ก ์ฐ์์ฑ์ ๊ฐ๊ธฐ ๋๋ฌธ์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ์ด ์ข ๋ ์์ ๋กญ๋ค.
๐ป๋จผ์ ๊ธฐ๋ณธ์ ์ธ ๋งํฌ๋ ๋ฆฌ์คํธ์ ํด๋์ค๋ ๋ค์๊ณผ ๊ฐ๋ค.
class LinkedList:
def __init__(self):
self.head = None
self.head: Linked List์ ์ฒซ ๋ฒ์งธ ์์(๋
ธ๋)๋ฅผ ๊ฐ๋ฆฌํดNone์ผ๋ก ์ค์ ํด์ค๋ค.์ฐ๋ฆฌ๋ ๋
ธ๋๋ฅผ ์ถ๊ฐํ๊ณ , ๋
ธ๋๋ค์ "๋
ผ๋ฆฌ์ ์ผ๋ก" ์ฐ์์ฑ์ ๊ฐ๊ฒ ํ๋ append ํจ์๋ฅผ ์ดํด๋ณผ ๊ฒ์ด๋ค. ๊ตฌ์ฒด์ ์ผ๋ก ์ดํด๋ณด๊ธฐ ์ ์, ๋ค์ 2๊ฐ์ง๋ฅผ ๋ฐ๋์ ๊ธฐ์ตํ์.
1. ์ฒซ๋ฒ์งธ ๋
ธ๋๋ ๋ฌด์กฐ๊ฑด head๋ก ๊ณ ์ ์์ผ์ค๋ค.
2. ๋
ธ๋๋ฅผ ์ถ๊ฐํ ๋๋ ๋ง์ง๋ง ๋
ธ๋ ๋ค์์ ์ถ๊ฐํด์ผ ํ๋ค.
๐๋ง์ง๋ง ๋
ธ๋, ์ฆ Node.next๊ฐ์ด ์๋์ง "๊ณ์" ํ์ธํ๋ ์์
์ด ํ์ํจ
๐ผ๏ธ์์ 2๊ฐ์ง๋ฅผ ์์งํ ์ฑ๋ก, ๊ตฌ์ฒด์ ์ผ๋ก ๋งํฌ๋ ๋ฆฌ์คํธ์ append ํจ์์ ๋์ ๊ณผ์ ์ ์ดํด๋ณด์.
๐คptr๋ ๋ณ์์ ๋ถ๊ณผํ๋ฐ ์ด๋ป๊ฒ ptr.next๋ฅผ ์ฌ์ฉํ ์ ์๋์?
โptr = self.head = new_node, ๊ทธ๋ฌ๋๊น ptr์ด ๋
ธ๋์ ์ฃผ์๊ฐ์ ๊ฐ์ง๊ณ ์์ผ๋ฉด ๊ฐ๋ฆฌํค๊ณ ์๋ ๋
ธ๋์ next ํฌ์ธํฐ๋ฅผ ์ฌ์ฉํ ์๊ฐ ์๋ค.
๐์ง๊ธ๋ถํฐ ๋งํฌ๋ ๋ฆฌ์คํธ์ CRUD๋ฅผ ๊ตฌํํ๊ธฐ ์ ์, head๋ ํญ์ 1๋ฒ์งธ ๋ ธ๋(์์)๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ๊ณ , ptr๋ ์์ ์์ฌ๋ก ์์ง์ผ ์ ์๋ ํฌ์ธํฐ๋ผ๋ ๊ฒ์ ๊ธฐ์ตํด๋์.
๐ผ๏ธ์๋์ insert ๋์ ๊ณผ์ ์ ์ดํด๋ณด์.

class Node {
int value;
Node next;
public Node(int value) {
this.value = value;
this.next = null;
}
}
public class MyLinkedList {
Node head;
public MyLinkedList() {
this.head = null;
}
public void append(int value) {
Node newNode = new Node(value);
if (head == null) {
head = newNode;
} else {
Node ptr = head;
while (ptr.next != null)
ptr = ptr.next;
ptr.next = newNode;
}
}
public int get(int idx) {
Node ptr = head;
for (int i = 0; i < idx; i++) {
ptr = ptr.next;
}
return ptr.value;
}
public void insert(int idx, int value) {
Node newNode = new Node(value);
Node ptr = head;
if (idx == 0) {
newNode.next = head;
head = newNode;
} else {
for (int i = 0; i < idx - 1; i++) {
ptr = ptr.next;
}
newNode.next = ptr.next;
ptr.next = newNode;
}
}
}
๐กnext ํฌ์ธํฐ๋ฅผ Node ํ์
์ผ๋ก ์ ์ธํ ์ด์ ๋ ๊ทธ๋์ผ ๋ค๋ฅธ Node ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
๐กappend ํจ์๋ ์คํ ์์ญ์์ ์์ฑ๋์ด ์ง์ญ ๋ณ์๋ค์ด ์ฌ๋ผ์ง์ง๋ง, ํ ์์ญ์ ์๋ Node ๊ฐ์ฒด๋ ์ฌ์ ํ ๋จ์์๊ธฐ ๋๋ฌธ์ ํฌ์ธํฐ๊ฐ ๊ฐ๋ฆฌํค๊ณ ์๋ ์ฃผ์๊ฐ๋ ๋ง์ฐฌ๊ฐ์ง๋ก ์ ์ง๋๋ค.
๐ผ๏ธremove ๋์ ๊ณผ์ ๋ insert์ ์ ์ฌํ๋ค.

public void remove(int idx) {
Node ptr = head;
if (idx == 0) {
head = head.next; // head๋ฅผ ์ด๋
} else {
for (int i = 0; i < idx - 1; i++) {
ptr = ptr.next; // ๋ฐ๋ก ์ง์ ๋
ธ๋๊น์ง ์ด๋
}
ptr.next = ptr.next.next; // ์ญ์ ํ๋ ค๊ณ ํ๋ ๋
ธ๋์ next๊ฐ์ ๋ฐ๋ก ์ง์ ๋
ธ๋๊ฐ ๊ฐ๋ฆฌํค๊ฒ ํจ
}
}
์ด์ ์ ๊ตฌํํ append ํจ์๋ ptr ๋
ธ๋๊ฐ newNode๋ฅผ ๊ฐ๋ฆฌํค๊ฒ ํ๊ธฐ ์ํด while๋ฌธ์ ํ๊ณ ์ด๋์์ผฐ์ง๋ง, tail์ด ํญ์ newNode๋ฅผ ๊ฐ๋ฆฌํค๊ฒ ๋ง๋ค๋ฉด append ํจ์๋ O(1)๋ง ๊ฑธ๋ฆฌ๊ฒ ๊ตฌํํ ์ ์๋ค.

public class LinkedList {
Node head;
Node tail;
public LinkedList() {
this.head = null;
this.tail = null;
}
public void append(int value) {
Node newNode = new Node(value);
if (head == null) {
head = newNode;
tail = newNode;
} else {
tail.next = newNode;
tail = tail.next; // tail์ ํญ์ ๋ง์ง๋ง ๋
ธ๋๋ฅผ ๊ฐ๋ฆฌํด
}
}
}
๋ณ๊ฑฐ์๋ค. ๊ทธ๋ฅ Node ํด๋์ค์์ ์ด์ ์ ๋
ธ๋๋ฅผ ๊ฐ๋ฆฌํค๊ธฐ ์ํ prev ํฌ์ธํฐ๋ฅผ ์ถ๊ฐํ๊ณ , ์์ ๊ตฌํํ tail ํฌ์ธํฐ๋ฅผ ํ์ฉํ append ํจ์์์ ์ฝ๊ฐ์ ์ฝ๋๋ง ์์ ํด์ฃผ๋ฉด ๋๋ค.

class DoublyNode {
int value;
DoublyNode next;
DoublyNode prev;
public DoublyNode(int value) {
this.value = value;
this.next = null;
this.prev = null;
}
}
public class MyDoublyLinkedList {
DoublyNode head = null;
DoublyNode tail = null;
public void append(int value) {
DoublyNode newNode = new DoublyNode(value);
if (head == null) {
head = newNode;
tail = newNode;
} else {
tail.next = newNode;
newNode.prev = tail;
tail = tail.next; // tail ์
๋ฐ์ดํธ
}
}
}
์์๋ ๋งํฌ๋ ๋ฆฌ์คํธ๊ฐ ๋ฌด์์ด๊ณ CRUD ๋์ ๊ณผ์ ์ด ์ด๋ป๊ฒ ๋๋์ง ์ฌ์ค์ด ์ข ๊ธธ์์ง๋ง, ๋ฌผ๋ฆฌ์ ์ธ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๊ตฌํํ Array์ ์๊ฐ๋ณต์ก๋๋ฅผ ๋น๊ตํด๋ณด๋ฉด์ ์ ๋งํฌ๋ ๋ฆฌ์คํธ๋ฅผ ์ฌ์ฉํ๋์ง๋ฅผ ์์๋ณด์.
๐ขArray๋ ๋ฉ๋ชจ๋ฆฌ์ Random Access๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๊ธฐ ๋๋ฌธ์ ์ฐ์์ฑ์ ๊ฐ๋ ๋ฐ๋ฉด, Linked List๋ ๋ฌผ๋ฆฌ์ ์ผ๋ก ์ฐ์์ฑ์ ๊ฐ์ง๋ ์์ง๋ง, next ํฌ์ธํฐ๋ก ๋ค์ ๋ ธ๋์ ์ฐธ์กฐ๊ฐ์ ๊ฐ๊ธฐ ๋๋ฌธ์ "๋ ผ๋ฆฌ์ ์ผ๋ก ์ฐ์์ฑ์ ๊ฐ๋๋ค"๋ ์ ์ ์ ์ํ์.
| Linked List | Array | |
|---|---|---|
| access/update | O(N) | O(1) |
| insert_front | O(1) | O(N) |
| insert_at | O(N) | O(N) |
| insert_back | O(N) ๋๋ O(1) | O(1) |
| remove_front | O(1) | O(N) |
| remove_at | O(N) | O(N) |
| remove_back | O(N) ๋๋ O(1) | O(1) |
๐กinsert_back๊ณผ remove_back์ ๊ฒฝ์ฐ tail ํฌ์ธํฐ๊ฐ ์ถ๊ฐ๋ Doubly Linked List๋ก ๊ตฌํ๋์ด์์ผ๋ฉด O(1)๋ง ๊ฑธ๋ฆฐ๋ค.
๐๊ฒฐ๊ตญ, (๋๋ธ)๋งํฌ๋ ๋ฆฌ์คํธ๋ฅผ ์ฌ์ฉํ๋ ์ด์ ๋ head ํฌ์ธํฐ(ํ์ํ๋ค๋ฉด tail ํฌ์ธํฐ)๋ฅผ ์ฌ์ฉํจ์ผ๋ก์จ ์ฝ์ /์ญ์ ๊ฐ O(1)๋ง ๊ฑธ๋ฆฌ๊ธฐ ๋๋ฌธ์ ์ฌ์ฉํ๋ค๊ณ ์ ๋ฆฌํ ์ ์๋ค.