ํ์ด์ฌ์์ ๋ฐฐ์ด์ ์์ฃผ ์ฌ์ฉ๋์ง๋ง, ๋ ๋ณต์กํ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ํ์๋ก ํ ๋ ์ฐ๊ฒฐ ๋ฆฌ์คํธ๊ฐ ์ค์ํฉ๋๋ค. ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ ๋ฐ์ดํฐ์ ์์๋ฅผ ์ ์งํ๋ฉด์ ์ฝ์ ๊ณผ ์ญ์ ๊ฐ ์ฉ์ดํ ์๋ฃ๊ตฌ์กฐ์ ๋๋ค. ์ด ํฌ์คํ ์์๋ ํ์ด์ฌ์ผ๋ก ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ฅผ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ๋จ๊ณ๋ณ๋ก ์ค๋ช ํ๊ณ , ๊ทธ ํ์ฉ๋ฒ์ ์๊ฐํฉ๋๋ค.
โฃ ๋ชฉ์ฐจ
01. ์ฐ๊ฒฐ ๋ฆฌ์คํธ ๊ธฐ๋ณธ ๊ฐ๋ ๐
์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ ๊ฐ ๋ ธ๋๊ฐ ๋ฐ์ดํฐ์ ๋ค์ ๋ ธ๋์ ๋ํ ์ฐธ์กฐ๋ฅผ ํฌํจํ๋ ๊ตฌ์กฐ์ ๋๋ค. ๋ฐฐ์ด๊ณผ ๋ฌ๋ฆฌ ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ์ฐ์์ ์ผ๋ก ์ฌ์ฉํ ํ์๊ฐ ์์ด ํจ์จ์ ์ ๋๋ค.
์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ์ฃผ์ ํน์ง
- ๋์ ํฌ๊ธฐ: ๋ฐฐ์ด์ ๊ณ ์ ํฌ๊ธฐ์ง๋ง, ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ ์์๋ฅผ ์ถ๊ฐํ๊ฑฐ๋ ์ญ์ ํ ๋๋ง๋ค ํฌ๊ธฐ๊ฐ ๋์ ์ผ๋ก ๋ณํ ์ ์์ต๋๋ค.
- ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ์ ํจ์จ์ฑ: ํ์ํ ๋งํผ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ฏ๋ก ๋ฉ๋ชจ๋ฆฌ ๋ญ๋น๊ฐ ์ ์ต๋๋ค.
- ์ฝ์ ๋ฐ ์ญ์ ๊ฐ ์ฉ์ด: ํน์ ์์น์ ์์๋ฅผ ์ฝ์ ํ๊ฑฐ๋ ์ญ์ ํ๋ ์์ ์ด ๋ฐฐ์ด๋ณด๋ค ํจ์จ์ ์ ๋๋ค. ๋ฐฐ์ด์์๋ ์ฝ์ ๋๋ ์ญ์ ํ ์์๋ค์ ์ด๋์์ผ์ผ ํ์ง๋ง, ์ฐ๊ฒฐ ๋ฆฌ์คํธ์์๋ ์ฐธ์กฐ๋ฅผ ๋ณ๊ฒฝํ๋ ๊ฒ์ผ๋ก ์ถฉ๋ถํฉ๋๋ค.
์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ๊ตฌ์ฑ ์์
- ๋
ธ๋(Node): ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ๊ธฐ๋ณธ ๋จ์๋ก, ๋ฐ์ดํฐ์ ๋ค์ ๋
ธ๋์ ๋ํ ์ฐธ์กฐ๋ฅผ ํฌํจํฉ๋๋ค.
- ๋ฐ์ดํฐ: ๋ ธ๋๊ฐ ์ ์ฅํ๋ ์ค์ ๊ฐ.
- ํฌ์ธํฐ: ๋ค์ ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ์ฐธ์กฐ. - ํค๋ ํฌ์ธํฐ(Head Pointer): ๋ฆฌ์คํธ์ ์์์ ์ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ๋ก, ์ฒซ ๋ฒ์งธ ๋ ธ๋๋ฅผ ์ฐธ์กฐํฉ๋๋ค.
์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ์ข ๋ฅ
- ๋จ์ผ ์ฐ๊ฒฐ ๋ฆฌ์คํธ(Singly Linked List): ๊ฐ ๋
ธ๋๊ฐ ํ๋์ ๋ค์ ๋
ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ๋ฅผ ๊ฐ์ง๋ ๊ตฌ์กฐ์
๋๋ค.
๊ตฌ์ฑ: ๋ ธ๋(Node)์ ํฌ์ธํฐ(Next)๋ก ๊ตฌ์ฑ. - ์ด์ค ์ฐ๊ฒฐ ๋ฆฌ์คํธ(Doubly Linked List): ๊ฐ ๋
ธ๋๊ฐ ๋ ๊ฐ์ ํฌ์ธํฐ(ํ๋๋ ๋ค์ ๋
ธ๋, ํ๋๋ ์ด์ ๋
ธ๋)๋ฅผ ๊ฐ์ง๋ ๊ตฌ์กฐ์
๋๋ค.
๊ตฌ์ฑ: ๋ ธ๋(Node), ๋ค์ ๋ ธ๋ ํฌ์ธํฐ(Next), ์ด์ ๋ ธ๋ ํฌ์ธํฐ(Prev). - ํํ ์ฐ๊ฒฐ ๋ฆฌ์คํธ(Circular Linked List): ๋ง์ง๋ง ๋
ธ๋๊ฐ ์ฒซ ๋ฒ์งธ ๋
ธ๋๋ฅผ ๊ฐ๋ฆฌ์ผ ์ํ์ผ๋ก ์ฐ๊ฒฐ๋ ๊ตฌ์กฐ์
๋๋ค.
- ๋จ์ผ ํํ ์ฐ๊ฒฐ ๋ฆฌ์คํธ: ๋จ์ผ ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ๋ณํ์ผ๋ก ๋ง์ง๋ง ๋ ธ๋์ ๋ค์ ํฌ์ธํฐ๊ฐ ์ฒซ ๋ฒ์งธ ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํต๋๋ค.
- ์ด์ค ํํ ์ฐ๊ฒฐ ๋ฆฌ์คํธ: ์ด์ค ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ๋ณํ์ผ๋ก ๋ง์ง๋ง ๋ ธ๋์ ๋ค์ ํฌ์ธํฐ๊ฐ ์ฒซ ๋ฒ์งธ ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํค๊ณ , ์ฒซ ๋ฒ์งธ ๋ ธ๋์ ์ด์ ํฌ์ธํฐ๊ฐ ๋ง์ง๋ง ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํต๋๋ค.
์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ๊ธฐ๋ณธ ์ฐ์ฐ
- ์ฝ์ (Insertion): ์๋ก์ด ๋ ธ๋๋ฅผ ๋ฆฌ์คํธ์ ํน์ ์์น์ ์ถ๊ฐํฉ๋๋ค.
- ์ญ์ (Deletion): ๋ฆฌ์คํธ์์ ํน์ ๋ ธ๋๋ฅผ ์ ๊ฑฐํฉ๋๋ค.
- ํ์(Search): ๋ฆฌ์คํธ์์ ํน์ ๊ฐ์ ์ฐพ์ต๋๋ค.
- ์ํ(Traversal): ๋ฆฌ์คํธ์ ๋ชจ๋ ๋ ธ๋๋ฅผ ์์๋๋ก ๋ฐฉ๋ฌธํฉ๋๋ค.
02. ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ๋ ธ๋ ๊ตฌํ๐ ๏ธ
์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ๋ ธ๋๋ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ๊ธฐ๋ณธ ๋จ์๋ก, ๋ค์ ๋ ธ๋์ ๋ํ ์ฐธ์กฐ(ํฌ์ธํฐ)์ ํจ๊ป ๋ฐ์ดํฐ๋ฅผ ํฌํจํฉ๋๋ค. Python์์๋ ํด๋์ค๋ฅผ ์ฌ์ฉํ์ฌ ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ๋ ธ๋๋ฅผ ๊ตฌํํ ์ ์์ต๋๋ค. ๋ค์์ ๋จ์ผ ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ์ด์ค ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ๋ ธ๋ ๊ตฌํ ์์ ์ ๋๋ค.
๋จ์ผ ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ๋ ธ๋ ๊ตฌํ
๋จ์ผ ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ๋ ธ๋๋ ๋ค์ ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ(next)์ ๋ฐ์ดํฐ๋ฅผ ํฌํจํฉ๋๋ค.
class Node:
def __init__(self, data):
self.data = data # ๋
ธ๋๊ฐ ์ ์ฅํ ๋ฐ์ดํฐ
self.next = None # ๋ค์ ๋
ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ
# ๋
ธ๋ ์์ฑ ์์
node1 = Node(1)
node2 = Node(2)
node1.next = node2 # node1์ด node2๋ฅผ ๊ฐ๋ฆฌํค๋๋ก ์ค์
print(node1.data) # Output: 1
print(node1.next.data) # Output: 2
์ด์ค ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ๋ ธ๋ ๊ตฌํ
์ด์ค ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ๋ ธ๋๋ ์ด์ ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ(prev)์ ๋ค์ ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ(next), ๊ทธ๋ฆฌ๊ณ ๋ฐ์ดํฐ๋ฅผ ํฌํจํฉ๋๋ค.
class DoublyNode:
def __init__(self, data):
self.data = data # ๋
ธ๋๊ฐ ์ ์ฅํ ๋ฐ์ดํฐ
self.prev = None # ์ด์ ๋
ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ
self.next = None # ๋ค์ ๋
ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ
# ๋
ธ๋ ์์ฑ ์์
dnode1 = DoublyNode(1)
dnode2 = DoublyNode(2)
dnode1.next = dnode2 # dnode1์ด dnode2๋ฅผ ๊ฐ๋ฆฌํค๋๋ก ์ค์
dnode2.prev = dnode1 # dnode2๊ฐ dnode1์ ๊ฐ๋ฆฌํค๋๋ก ์ค์
print(dnode1.data) # Output: 1
print(dnode1.next.data) # Output: 2
print(dnode2.prev.data) # Output: 1
๋จ์ผ ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ์ด์ค ์ฐ๊ฒฐ ๋ฆฌ์คํธ ๋น๊ต
- ๋จ์ผ ์ฐ๊ฒฐ ๋ฆฌ์คํธ: ๊ฐ ๋ ธ๋๊ฐ ํ๋์ ๋ค์ ๋ ธ๋์ ๋ํ ํฌ์ธํฐ๋ง ๊ฐ์ง๊ณ ์์ต๋๋ค. ์ฝ์ ๊ณผ ์ญ์ ์ฐ์ฐ์ด ๊ฐ๋จํ์ง๋ง, ๋จ๋ฐฉํฅ์ผ๋ก๋ง ํ์ํ ์ ์์ต๋๋ค.
- ์ด์ค ์ฐ๊ฒฐ ๋ฆฌ์คํธ: ๊ฐ ๋ ธ๋๊ฐ ์ด์ ๋ ธ๋์ ๋ค์ ๋ ธ๋์ ๋ํ ๋ ๊ฐ์ ํฌ์ธํฐ๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค. ์๋ฐฉํฅ์ผ๋ก ํ์์ด ๊ฐ๋ฅํ๋ฉฐ, ์ฝ์ ๊ณผ ์ญ์ ์ฐ์ฐ์ด ๋ ์ ์ฐํ์ง๋ง, ์ถ๊ฐ์ ์ธ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ด ํ์ํฉ๋๋ค.
03. ๋จ์ผ ์ฐ๊ฒฐ ๋ฆฌ์คํธ ๊ตฌํ๐ก
class Node:
def __init__(self, data):
self.data = data # ๋
ธ๋๊ฐ ์ ์ฅํ ๋ฐ์ดํฐ
self.next = None # ๋ค์ ๋
ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ
class SinglyLinkedList:
def __init__(self):
self.head = None # ๋ฆฌ์คํธ์ ์์์ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ
def insert(self, data):
"""๋ฆฌ์คํธ์ ๋งจ ์์ ์๋ก์ด ๋
ธ๋๋ฅผ ์ฝ์
ํฉ๋๋ค."""
new_node = Node(data)
new_node.next = self.head
self.head = new_node
def delete(self, key):
"""๋ฆฌ์คํธ์์ ์ฃผ์ด์ง ๊ฐ์ ๊ฐ์ง ์ฒซ ๋ฒ์งธ ๋
ธ๋๋ฅผ ์ญ์ ํฉ๋๋ค."""
temp = self.head
if temp is not None:
if temp.data == key:
self.head = temp.next
temp = None
return
while temp is not None:
if temp.data == key:
break
prev = temp
temp = temp.next
if temp == None:
return
prev.next = temp.next
temp = None
def search(self, key):
"""๋ฆฌ์คํธ์์ ์ฃผ์ด์ง ๊ฐ์ ๊ฐ์ง ๋
ธ๋๋ฅผ ์ฐพ์ต๋๋ค."""
current = self.head
while current is not None:
if current.data == key:
return True
current = current.next
return False
def traverse(self):
"""๋ฆฌ์คํธ์ ๋ชจ๋ ๋
ธ๋๋ฅผ ์์๋๋ก ๋ฐฉ๋ฌธํฉ๋๋ค."""
current = self.head
while current:
print(current.data, end=" -> ")
current = current.next
print("None")
# ์ฌ์ฉ ์์
sll = SinglyLinkedList()
sll.insert(1)
sll.insert(2)
sll.insert(3)
sll.traverse() # Output: 3 -> 2 -> 1 -> None
sll.delete(2)
sll.traverse() # Output: 3 -> 1 -> None
print(sll.search(1)) # Output: True
print(sll.search(4)) # Output: False
์ฝ๋ ์ค๋ช
Node ํด๋์ค:
- __init__ ๋ฉ์๋๋ ๋ ธ๋๊ฐ ์ ์ฅํ ๋ฐ์ดํฐ(data)์ ๋ค์ ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ(next)๋ฅผ ์ด๊ธฐํํฉ๋๋ค.
SinglyLinkedList ํด๋์ค:
- __init__ ๋ฉ์๋๋ ๋ฆฌ์คํธ์ ์์์ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ(head)๋ฅผ ์ด๊ธฐํํฉ๋๋ค.
- insert ๋ฉ์๋๋ ๋ฆฌ์คํธ์ ๋งจ ์์ ์๋ก์ด ๋ ธ๋๋ฅผ ์ฝ์ ํฉ๋๋ค. ์๋ก์ด ๋ ธ๋์ next ํฌ์ธํฐ๋ ํ์ฌ์ head๋ฅผ ๊ฐ๋ฆฌํค๋ฉฐ, head๋ ์ ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋๋ก ์ ๋ฐ์ดํธ๋ฉ๋๋ค.
- delete ๋ฉ์๋๋ ๋ฆฌ์คํธ์์ ์ฃผ์ด์ง ๊ฐ์ ๊ฐ์ง ์ฒซ ๋ฒ์งธ ๋ ธ๋๋ฅผ ์ญ์ ํฉ๋๋ค. head๊ฐ ์ญ์ ๋ ๋ ธ๋์ธ์ง ํ์ธํ ํ, ๊ทธ๋ ์ง ์์ผ๋ฉด ๋ฆฌ์คํธ๋ฅผ ์ํํ๋ฉฐ ์ญ์ ํ ๋ ธ๋๋ฅผ ์ฐพ๊ณ , ์ด์ ๋ ธ๋์ next ํฌ์ธํฐ๋ฅผ ์ ๋ฐ์ดํธํฉ๋๋ค.
- search ๋ฉ์๋๋ ๋ฆฌ์คํธ๋ฅผ ์ํํ๋ฉฐ ์ฃผ์ด์ง ๊ฐ์ ๊ฐ์ง ๋ ธ๋๋ฅผ ์ฐพ์ต๋๋ค. ๊ฐ์ ์ฐพ์ผ๋ฉด True๋ฅผ ๋ฐํํ๊ณ , ๊ทธ๋ ์ง ์์ผ๋ฉด False๋ฅผ ๋ฐํํฉ๋๋ค.
- traverse ๋ฉ์๋๋ ๋ฆฌ์คํธ์ ๋ชจ๋ ๋ ธ๋๋ฅผ ์์๋๋ก ๋ฐฉ๋ฌธํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์ถ๋ ฅํฉ๋๋ค. ๋ ธ๋๊ฐ ๋๋๋ฉด None์ ์ถ๋ ฅํฉ๋๋ค.
04. ์ด์ค ์ฐ๊ฒฐ ๋ฆฌ์คํธ ๊ตฌํ๐
์ด์ค ์ฐ๊ฒฐ ๋ฆฌ์คํธ(Doubly Linked List)๋ ๊ฐ ๋ ธ๋๊ฐ ์ด์ ๋ ธ๋์ ๋ค์ ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ๋ ๊ฐ์ ํฌ์ธํฐ๋ฅผ ๊ฐ์ง๊ณ ์๋ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ๋๋ค. ์ด ๊ตฌ์กฐ๋ฅผ Python ํด๋์ค๋ก ๊ตฌํํด๋ณด๊ฒ ์ต๋๋ค. ๊ตฌํ์๋ ์ฝ์ , ์ญ์ , ํ์, ์ํ ๋ฑ์ ๊ธฐ๋ณธ ์ฐ์ฐ์ ํฌํจํฉ๋๋ค.
class DoublyNode:
def __init__(self, data):
self.data = data # ๋
ธ๋๊ฐ ์ ์ฅํ ๋ฐ์ดํฐ
self.prev = None # ์ด์ ๋
ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ
self.next = None # ๋ค์ ๋
ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ
class DoublyLinkedList:
def __init__(self):
self.head = None # ๋ฆฌ์คํธ์ ์์์ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ
def insert_front(self, data):
"""๋ฆฌ์คํธ์ ๋งจ ์์ ์๋ก์ด ๋
ธ๋๋ฅผ ์ฝ์
ํฉ๋๋ค."""
new_node = DoublyNode(data)
new_node.next = self.head
if self.head is not None:
self.head.prev = new_node
self.head = new_node
def insert_end(self, data):
"""๋ฆฌ์คํธ์ ๋งจ ๋์ ์๋ก์ด ๋
ธ๋๋ฅผ ์ฝ์
ํฉ๋๋ค."""
new_node = DoublyNode(data)
if self.head is None:
self.head = new_node
return
last = self.head
while last.next:
last = last.next
last.next = new_node
new_node.prev = last
def delete_node(self, node):
"""์ฃผ์ด์ง ๋
ธ๋๋ฅผ ์ญ์ ํฉ๋๋ค."""
if self.head is None or node is None:
return
if self.head == node:
self.head = node.next
if node.next is not None:
node.next.prev = node.prev
if node.prev is not None:
node.prev.next = node.next
node = None
def search(self, key):
"""๋ฆฌ์คํธ์์ ์ฃผ์ด์ง ๊ฐ์ ๊ฐ์ง ๋
ธ๋๋ฅผ ์ฐพ์ต๋๋ค."""
current = self.head
while current is not None:
if current.data == key:
return True
current = current.next
return False
def traverse_forward(self):
"""๋ฆฌ์คํธ์ ๋ชจ๋ ๋
ธ๋๋ฅผ ์์๋๋ก ๋ฐฉ๋ฌธํฉ๋๋ค (์ ๋ฐฉํฅ)."""
current = self.head
while current:
print(current.data, end=" <-> ")
current = current.next
print("None")
def traverse_backward(self):
"""๋ฆฌ์คํธ์ ๋ชจ๋ ๋
ธ๋๋ฅผ ์์๋๋ก ๋ฐฉ๋ฌธํฉ๋๋ค (์ญ๋ฐฉํฅ)."""
current = self.head
last = None
while current:
last = current
current = current.next
while last:
print(last.data, end=" <-> ")
last = last.prev
print("None")
# ์ฌ์ฉ ์์
dll = DoublyLinkedList()
dll.insert_front(1)
dll.insert_front(2)
dll.insert_end(3)
dll.traverse_forward() # Output: 2 <-> 1 <-> 3 <-> None
dll.traverse_backward() # Output: 3 <-> 1 <-> 2 <-> None
dll.delete_node(dll.head.next) # ๋
ธ๋ 1์ ์ญ์
dll.traverse_forward() # Output: 2 <-> 3 <-> None
print(dll.search(2)) # Output: True
print(dll.search(4)) # Output: False
์ฝ๋ ์ค๋ช
DoublyNode ํด๋์ค:
- __init__ ๋ฉ์๋๋ ๋ ธ๋๊ฐ ์ ์ฅํ ๋ฐ์ดํฐ(data), ์ด์ ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ(prev), ๋ค์ ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ(next)๋ฅผ ์ด๊ธฐํํฉ๋๋ค.
DoublyLinkedList ํด๋์ค:
- __init__ ๋ฉ์๋๋ ๋ฆฌ์คํธ์ ์์์ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ(head)๋ฅผ ์ด๊ธฐํํฉ๋๋ค.
- insert_front ๋ฉ์๋๋ ๋ฆฌ์คํธ์ ๋งจ ์์ ์๋ก์ด ๋ ธ๋๋ฅผ ์ฝ์ ํฉ๋๋ค. ์๋ก์ด ๋ ธ๋์ next ํฌ์ธํฐ๋ ํ์ฌ์ head๋ฅผ ๊ฐ๋ฆฌํค๋ฉฐ, head๊ฐ ๊ฐ๋ฆฌํค๋ ๋ ธ๋์ prev ํฌ์ธํฐ๋ ์๋ก์ด ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํต๋๋ค. ๊ทธ๋ฆฌ๊ณ head๋ ์ ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋๋ก ์ ๋ฐ์ดํธ๋ฉ๋๋ค.
- insert_end ๋ฉ์๋๋ ๋ฆฌ์คํธ์ ๋งจ ๋์ ์๋ก์ด ๋ ธ๋๋ฅผ ์ฝ์ ํฉ๋๋ค. ๋ฆฌ์คํธ๊ฐ ๋น์ด ์์ผ๋ฉด head๊ฐ ์๋ก์ด ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋๋ก ํ๊ณ , ๊ทธ๋ ์ง ์์ผ๋ฉด ๋ฆฌ์คํธ์ ๋๊น์ง ์ด๋ํ์ฌ ์ ๋ ธ๋๋ฅผ ์ถ๊ฐํฉ๋๋ค.
- delete_node ๋ฉ์๋๋ ๋ฆฌ์คํธ์์ ์ฃผ์ด์ง ๋ ธ๋๋ฅผ ์ญ์ ํฉ๋๋ค. ์ญ์ ํ ๋ ธ๋๊ฐ head์ธ์ง, ์ค๊ฐ์ ์๋์ง, ๋์ ์๋์ง์ ๋ฐ๋ผ ํฌ์ธํฐ๋ฅผ ์ ์ ํ ์ ๋ฐ์ดํธํฉ๋๋ค.
- search ๋ฉ์๋๋ ๋ฆฌ์คํธ๋ฅผ ์ํํ๋ฉฐ ์ฃผ์ด์ง ๊ฐ์ ๊ฐ์ง ๋ ธ๋๋ฅผ ์ฐพ์ต๋๋ค. ๊ฐ์ ์ฐพ์ผ๋ฉด True๋ฅผ ๋ฐํํ๊ณ , ๊ทธ๋ ์ง ์์ผ๋ฉด False๋ฅผ ๋ฐํํฉ๋๋ค.
- traverse_forward ๋ฉ์๋๋ ๋ฆฌ์คํธ์ ๋ชจ๋ ๋ ธ๋๋ฅผ ์ ๋ฐฉํฅ์ผ๋ก ์์๋๋ก ๋ฐฉ๋ฌธํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์ถ๋ ฅํฉ๋๋ค. ๋ ธ๋๊ฐ ๋๋๋ฉด None์ ์ถ๋ ฅํฉ๋๋ค.
- traverse_backward ๋ฉ์๋๋ ๋ฆฌ์คํธ์ ๋ชจ๋ ๋ ธ๋๋ฅผ ์ญ๋ฐฉํฅ์ผ๋ก ์์๋๋ก ๋ฐฉ๋ฌธํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์ถ๋ ฅํฉ๋๋ค. ๋ ธ๋๊ฐ ๋๋๋ฉด None์ ์ถ๋ ฅํฉ๋๋ค.
05. ์ํ ์ฐ๊ฒฐ ๋ฆฌ์คํธ ๊ตฌํ๐
์ํ ์ฐ๊ฒฐ ๋ฆฌ์คํธ(Circular Linked List)๋ ๋ง์ง๋ง ๋ ธ๋๊ฐ ์ฒซ ๋ฒ์งธ ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค. ์ด ๊ตฌ์กฐ๋ ๋จ์ผ ๋๋ ์ด์ค ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ก ๊ตฌํํ ์ ์์ต๋๋ค. ์ฌ๊ธฐ์๋ ๋จ์ผ ์ํ ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ฅผ ๊ตฌํํด๋ณด๊ฒ ์ต๋๋ค. ์ด ๊ตฌํ์๋ ์ฝ์ , ์ญ์ , ํ์, ์ํ ๋ฑ์ ๊ธฐ๋ณธ ์ฐ์ฐ์ ํฌํจํฉ๋๋ค.
class Node:
def __init__(self, data):
self.data = data # ๋
ธ๋๊ฐ ์ ์ฅํ ๋ฐ์ดํฐ
self.next = None # ๋ค์ ๋
ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ
class CircularLinkedList:
def __init__(self):
self.head = None # ๋ฆฌ์คํธ์ ์์์ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ
def insert_front(self, data):
"""๋ฆฌ์คํธ์ ๋งจ ์์ ์๋ก์ด ๋
ธ๋๋ฅผ ์ฝ์
ํฉ๋๋ค."""
new_node = Node(data)
if not self.head:
self.head = new_node
self.head.next = self.head
else:
temp = self.head
while temp.next != self.head:
temp = temp.next
new_node.next = self.head
temp.next = new_node
self.head = new_node
def insert_end(self, data):
"""๋ฆฌ์คํธ์ ๋งจ ๋์ ์๋ก์ด ๋
ธ๋๋ฅผ ์ฝ์
ํฉ๋๋ค."""
new_node = Node(data)
if not self.head:
self.head = new_node
self.head.next = self.head
else:
temp = self.head
while temp.next != self.head:
temp = temp.next
temp.next = new_node
new_node.next = self.head
def delete_node(self, key):
"""๋ฆฌ์คํธ์์ ์ฃผ์ด์ง ๊ฐ์ ๊ฐ์ง ์ฒซ ๋ฒ์งธ ๋
ธ๋๋ฅผ ์ญ์ ํฉ๋๋ค."""
if self.head is None:
return
temp = self.head
prev = None
# ๋ฆฌ์คํธ์ ๋
ธ๋๊ฐ ํ๋์ธ ๊ฒฝ์ฐ
if temp.data == key and temp.next == self.head:
self.head = None
return
# ๋ฆฌ์คํธ์ ์ฒซ ๋ฒ์งธ ๋
ธ๋๋ฅผ ์ญ์ ํ๋ ๊ฒฝ์ฐ
if temp.data == key:
while temp.next != self.head:
temp = temp.next
temp.next = self.head.next
self.head = self.head.next
return
# ๋ฆฌ์คํธ์ ์ค๊ฐ ๋๋ ๋ง์ง๋ง ๋
ธ๋๋ฅผ ์ญ์ ํ๋ ๊ฒฝ์ฐ
while temp.next != self.head:
prev = temp
temp = temp.next
if temp.data == key:
prev.next = temp.next
return
def search(self, key):
"""๋ฆฌ์คํธ์์ ์ฃผ์ด์ง ๊ฐ์ ๊ฐ์ง ๋
ธ๋๋ฅผ ์ฐพ์ต๋๋ค."""
if self.head is None:
return False
temp = self.head
while True:
if temp.data == key:
return True
temp = temp.next
if temp == self.head:
break
return False
def traverse(self):
"""๋ฆฌ์คํธ์ ๋ชจ๋ ๋
ธ๋๋ฅผ ์์๋๋ก ๋ฐฉ๋ฌธํฉ๋๋ค."""
if self.head is None:
print("List is empty")
return
temp = self.head
while True:
print(temp.data, end=" -> ")
temp = temp.next
if temp == self.head:
break
print("HEAD")
# ์ฌ์ฉ ์์
cll = CircularLinkedList()
cll.insert_front(1)
cll.insert_front(2)
cll.insert_end(3)
cll.traverse() # Output: 2 -> 1 -> 3 -> HEAD
cll.delete_node(1)
cll.traverse() # Output: 2 -> 3 -> HEAD
print(cll.search(2)) # Output: True
print(cll.search(4)) # Output: False
์ฝ๋ ์ค๋ช
Node ํด๋์ค:
- __init__ ๋ฉ์๋๋ ๋ ธ๋๊ฐ ์ ์ฅํ ๋ฐ์ดํฐ(data)์ ๋ค์ ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ(next)๋ฅผ ์ด๊ธฐํํฉ๋๋ค.
CircularLinkedList ํด๋์ค:
- __init__ ๋ฉ์๋๋ ๋ฆฌ์คํธ์ ์์์ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ(head)๋ฅผ ์ด๊ธฐํํฉ๋๋ค.
- insert_front ๋ฉ์๋๋ ๋ฆฌ์คํธ์ ๋งจ ์์ ์๋ก์ด ๋ ธ๋๋ฅผ ์ฝ์ ํฉ๋๋ค. ๋ฆฌ์คํธ๊ฐ ๋น์ด ์์ผ๋ฉด ์ ๋ ธ๋์ next ํฌ์ธํฐ๋ ์๊ธฐ ์์ ์ ๊ฐ๋ฆฌํค๋๋ก ์ค์ ํฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ๋ฆฌ์คํธ๋ฅผ ์ํํ์ฌ ๋ง์ง๋ง ๋ ธ๋๋ฅผ ์ฐพ๊ณ , ์ ๋ ธ๋๋ฅผ head๋ก ์ค์ ํ๋ฉฐ, ๋ง์ง๋ง ๋ ธ๋์ next ํฌ์ธํฐ๋ฅผ ์ ๋ ธ๋๋ก ์ค์ ํฉ๋๋ค.
- insert_end ๋ฉ์๋๋ ๋ฆฌ์คํธ์ ๋งจ ๋์ ์๋ก์ด ๋ ธ๋๋ฅผ ์ฝ์ ํฉ๋๋ค. ๋ฆฌ์คํธ๊ฐ ๋น์ด ์์ผ๋ฉด ์ ๋ ธ๋์ next ํฌ์ธํฐ๋ ์๊ธฐ ์์ ์ ๊ฐ๋ฆฌํค๋๋ก ์ค์ ํฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ๋ฆฌ์คํธ๋ฅผ ์ํํ์ฌ ๋ง์ง๋ง ๋ ธ๋๋ฅผ ์ฐพ๊ณ , ์ ๋ ธ๋๋ฅผ ๋ง์ง๋ง ๋ ธ๋์ next ํฌ์ธํฐ์ ์ฐ๊ฒฐํฉ๋๋ค.
- delete_node ๋ฉ์๋๋ ๋ฆฌ์คํธ์์ ์ฃผ์ด์ง ๊ฐ์ ๊ฐ์ง ์ฒซ ๋ฒ์งธ ๋ ธ๋๋ฅผ ์ญ์ ํฉ๋๋ค. ์ญ์ ํ ๋ ธ๋๊ฐ head์ธ์ง, ์ค๊ฐ์ ์๋์ง, ๋์ ์๋์ง์ ๋ฐ๋ผ ํฌ์ธํฐ๋ฅผ ์ ์ ํ ์ ๋ฐ์ดํธํฉ๋๋ค.
- search ๋ฉ์๋๋ ๋ฆฌ์คํธ๋ฅผ ์ํํ๋ฉฐ ์ฃผ์ด์ง ๊ฐ์ ๊ฐ์ง ๋ ธ๋๋ฅผ ์ฐพ์ต๋๋ค. ๊ฐ์ ์ฐพ์ผ๋ฉด True๋ฅผ ๋ฐํํ๊ณ , ๊ทธ๋ ์ง ์์ผ๋ฉด False๋ฅผ ๋ฐํํฉ๋๋ค.
- traverse ๋ฉ์๋๋ ๋ฆฌ์คํธ์ ๋ชจ๋ ๋ ธ๋๋ฅผ ์์๋๋ก ๋ฐฉ๋ฌธํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์ถ๋ ฅํฉ๋๋ค. ๋ง์ง๋ง์๋ HEAD๋ฅผ ์ถ๋ ฅํ์ฌ ์ํ ๋ฆฌ์คํธ์ ๋์ ๋ํ๋ ๋๋ค.
06. ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ๊ด๋ จ๋ ๋ฌธ์ ํด๊ฒฐ๐
์ฐ๊ฒฐ ๋ฆฌ์คํธ์์ ์ค๋ณต ์ ๊ฑฐ ํด๊ฒฐ ๋ฐฉ๋ฒ:
- ๋ฐฉ๋ฒ 1: set์ ์ฌ์ฉํ์ฌ O(n) ์๊ฐ ๋ณต์ก๋๋ก ์ค๋ณต์ ์ ๊ฑฐํ ์ ์์ต๋๋ค. ๊ฐ ๋ ธ๋๋ฅผ ์ํํ๋ฉด์ ์ด๋ฏธ ๋ฑ์ฅํ ๊ฐ์ set์ ์ ์ฅํ๊ณ , ๋ค์์ ๋์ผํ ๊ฐ์ด ๋ฑ์ฅํ๋ฉด ์ญ์ ํฉ๋๋ค.
- ๋ฐฉ๋ฒ 2: ๋ ๊ฐ์ ํฌ์ธํฐ๋ฅผ ์ฌ์ฉํ์ฌ ๋ชจ๋ ๋ ธ๋๋ฅผ ๋น๊ตํ๋ฉฐ ์ค๋ณต์ ์ ๊ฑฐํฉ๋๋ค. ์ด ๋ฐฉ๋ฒ์ ์ถ๊ฐ์ ์ธ ๋ฉ๋ชจ๋ฆฌ ์์ด ํด๊ฒฐํ ์ ์์ต๋๋ค.
Python ์ฝ๋ (๋ฐฉ๋ฒ 1, set ์ฌ์ฉ):
class Node:
def __init__(self, data):
self.data = data
self.next = None
class SinglyLinkedList:
def __init__(self):
self.head = None
def insert_end(self, data):
new_node = Node(data)
if self.head is None:
self.head = new_node
return
last = self.head
while last.next:
last = last.next
last.next = new_node
def remove_duplicates(self):
seen = set()
current = self.head
prev = None
while current:
if current.data in seen:
prev.next = current.next
else:
seen.add(current.data)
prev = current
current = current.next
def traverse(self):
current = self.head
while current:
print(current.data, end=" -> ")
current = current.next
print("None")
# ์ฌ์ฉ ์์
sll = SinglyLinkedList()
sll.insert_end(1)
sll.insert_end(2)
sll.insert_end(2)
sll.insert_end(3)
sll.insert_end(3)
sll.traverse() # Output: 1 -> 2 -> 2 -> 3 -> 3 -> None
sll.remove_duplicates()
sll.traverse() # Output: 1 -> 2 -> 3 -> None
Python ์ฝ๋ (๋ฐฉ๋ฒ 2, ๋ ํฌ์ธํฐ ์ฌ์ฉ):
class SinglyLinkedList:
def __init__(self):
self.head = None
def insert_end(self, data):
new_node = Node(data)
if self.head is None:
self.head = new_node
return
last = self.head
while last.next:
last = last.next
last.next = new_node
def remove_duplicates(self):
current = self.head
while current:
runner = current
while runner.next:
if runner.next.data == current.data:
runner.next = runner.next.next
else:
runner = runner.next
current = current.next
def traverse(self):
current = self.head
while current:
print(current.data, end=" -> ")
current = current.next
print("None")
# ์ฌ์ฉ ์์
sll = SinglyLinkedList()
sll.insert_end(1)
sll.insert_end(2)
sll.insert_end(2)
sll.insert_end(3)
sll.insert_end(3)
sll.traverse() # Output: 1 -> 2 -> 2 -> 3 -> 3 -> None
sll.remove_duplicates()
sll.traverse() # Output: 1 -> 2 -> 3 -> None
์ฐ๊ฒฐ ๋ฆฌ์คํธ ๊ธธ์ด ๊ตฌํ๊ธฐ:
๋ฌธ์ : ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ๊ธธ์ด๋ฅผ ๊ตฌํฉ๋๋ค.
ํด๊ฒฐ ๋ฐฉ๋ฒ: ๋ฆฌ์คํธ๋ฅผ ์ํํ๋ฉฐ ๋ ธ๋์ ๊ฐ์๋ฅผ ์นด์ดํธํฉ๋๋ค.
Python ์ฝ๋:
class SinglyLinkedList:
def __init__(self):
self.head = None
def insert_end(self, data):
new_node = Node(data)
if self.head is None:
self.head = new_node
return
last = self.head
while last.next:
last = last.next
last.next = new_node
def length(self):
count = 0
current = self.head
while current:
count += 1
current = current.next
return count
def traverse(self):
current = self.head
while current:
print(current.data, end=" -> ")
current = current.next
print("None")
# ์ฌ์ฉ ์์
sll = SinglyLinkedList()
sll.insert_end(1)
sll.insert_end(2)
sll.insert_end(3)
print(sll.length()) # Output: 3
์ฐ๊ฒฐ ๋ฆฌ์คํธ์์ ํน์ ๊ฐ ์ฐพ๊ธฐ:
๋ฌธ์ : ์ฐ๊ฒฐ ๋ฆฌ์คํธ์์ ํน์ ๊ฐ์ ๊ฐ์ง ๋ ธ๋๋ฅผ ์ฐพ์ต๋๋ค.
ํด๊ฒฐ ๋ฐฉ๋ฒ: ๋ฆฌ์คํธ๋ฅผ ์ํํ๋ฉด์ ๊ฐ ๋ ธ๋์ ๊ฐ์ ํ์ธํฉ๋๋ค.
Python ์ฝ๋:
class SinglyLinkedList:
def __init__(self):
self.head = None
def insert_end(self, data):
new_node = Node(data)
if self.head is None:
self.head = new_node
return
last = self.head
while last.next:
last = last.next
last.next = new_node
def search(self, key):
current = self.head
while current:
if current.data == key:
return True
current = current.next
return False
def traverse(self):
current = self.head
while current:
print(current.data, end=" -> ")
current = current.next
print("None")
# ์ฌ์ฉ ์์
sll = SinglyLinkedList()
sll.insert_end(1)
sll.insert_end(2)
sll.insert_end(3)
print(sll.search(2)) # Output: True
print(sll.search(4)) # Output: False