Algorithm/๐Ÿ“š Concept

[์ž๋ฃŒ๊ตฌ์กฐ] ๋‹จ์ˆœ/์›ํ˜•/์ด์ค‘ ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ(Linked List) ๊ตฌํ˜„ - ํŒŒ์ด์ฌ(Python)

J1Yun 2023. 3. 7. 18:12
728x90

์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ(Linked List)

  • ๋‹ค์Œ ์ˆœ์„œ์˜ ์ž๋ฃŒ๊ฐ€ ์žˆ๋Š” ์œ„์น˜๋ฅผ ๋ฐ์ดํ„ฐ์— ํฌํ•จ์‹œํ‚ค๋Š” ๋ฐฉ์‹์œผ๋กœ ์ž๋ฃŒ๋ฅผ ์ €์žฅํ•˜๋Š” ์„ ํ˜• ์ž๋ฃŒ๊ตฌ์กฐ
  • ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ๋Š” Node๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๊ณ , Node ์•ˆ์—๋Š” Data์™€ Link(Next)๋กœ ๊ตฌ์„ฑ
    • Data: ๋ฐ์ดํ„ฐ ๊ฐ’ ์ €์žฅ
    • Link(Next): ๋‹ค์Œ ๋…ธ๋“œ๋ฅผ ๊ฐ€๋ฆฌํ‚ด

์žฅ์ 

  • ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€, ์‚ญ์ œ์— ์œ ๋ฆฌ
    • ๋ฐฐ์—ด: ์‹œ๊ฐ„๋ณต์žก๋„ O(n)
    • ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ: ์‹œ๊ฐ„๋ณต์žก๋„ O(1)
  • ๊ณต๊ฐ„๋ณต์žก๋„ ์ธก๋ฉด์—์„œ ์œ ๋ฆฌ (๋ฐฐ์—ด์ฒ˜๋Ÿผ ์—ฐ์†๋œ ๊ณต๊ฐ„์„ ํ• ๋‹นํ•˜์ง€ ์•Š๊ณ  ํ•„์š” ์‹œ์—๋งŒ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋™์  ํ• ๋‹นํ•˜๊ธฐ ๋•Œ๋ฌธ)
    • ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ X
    • ์œ ์—ฐํ•œ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ

๋‹จ์ 

  • ๋ฐ์ดํ„ฐ ํƒ์ƒ‰ ์‹œ ๋ถˆ๋ฆฌ (๋ฐ์ดํ„ฐ์˜ ๋…ผ๋ฆฌ์  ์ €์žฅ ์ˆœ์„œ์™€ ๋ฌผ๋ฆฌ์  ์ €์žฅ ์ˆœ์„œ๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š์•„ ์ธ๋ฑ์Šค ์ ‘๊ทผ์ด ์•„๋‹Œ ์ „์ฒด๋ฅผ ์ˆœํšŒํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ)
    • ๋ฐฐ์—ด: ์‹œ๊ฐ„๋ณต์žก๋„ O(1)
    • ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ: ์‹œ๊ฐ„๋ณต์žก๋„ O(n)
  • ํ…Œ์ดํ„ฐ ์ •๋ ฌ ์‹œ ๋ถˆ๋ฆฌ

 

 

๋‹จ์ˆœ ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ(Singly Linked List)

  • ๊ฐ€์žฅ ๋‹จ์ˆœํžˆ ๋‹ค์Œ ๋…ธ๋“œ์— ๋Œ€ํ•œ ์ฐธ์กฐ๋งŒ ๊ณ ๋ คํ•œ ํ˜•ํƒœ์˜ ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ
  • ๋งˆ์ง€๋ง‰ ๋…ธ๋“œ๋Š” ํ•ญ์ƒ NULL์„ ๊ฐ€๋ฆฌํ‚ด
  • ํ—ค๋“œ ํฌ์ธํ„ฐ์˜ ์ฃผ์†Œ๋‚˜ ๋‹ค์Œ ๋…ธ๋“œ์˜ ์ฃผ์†Œ๊ฐ€ ๋ถ€์ •ํ™•ํ•  ๋•Œ ๋ฐ์ดํ„ฐ ์œ ์‹ค์˜ ์œ„ํ—˜์ด ๋†’์Œ (์•ˆ์ •์ X)

 

1. ๋…ธ๋“œ ์ƒ์„ฑ

class Node:
    def __init__(self, val):
        self.data = val
        self.next = None

 

2. ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ ์ดˆ๊ธฐํ™”

class SimplyLinkedList:
    def __init__(self):
        self.nodeCount = 0  # ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ ๋‚ด ๋…ธ๋“œ ์ˆ˜
        self.head = None  # ์ฒซ ๋ฒˆ์งธ ๋…ธ๋“œ
        self.tail = None  # ๋งˆ์ง€๋ง‰ ๋…ธ๋“œ

 

3. ๋…ธ๋“œ ์‚ฝ์ž…

# ๋งจ ์•ž(head)์— ๋…ธ๋“œ ์‚ฝ์ž…
def insert_front(self, val):
    new_node = Node(val)
    
    if self.head is None:  # ๋นˆ ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ์ผ ๋•Œ
    	self.head = new_node
        self.tail = new_node
        
    else:  # ๋นˆ ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ๊ฐ€ ์•„๋‹ ๋•Œ
    	new_node.next = self.head
        self.head = new_node
    
    self.nodeCount += 1
 
 
# ์ค‘๊ฐ„์— ๋…ธ๋“œ ์‚ฝ์ž…
def insert_middle(self, target, val):
    current = self.head
    
    while current != None:
    	previous = current
        current = current.next
        
        if previous.data == target:  # target ๊ฐ’์„ ๊ฐ€์ง„ ๋…ธ๋“œ ๋’ค์— ์‚ฝ์ž…
        	new_node = Node(val)
            new_node.next = current
            previous.next = new_node
            self.nodeCount += 1
            break
                    	

# ๋งจ ๋(tail)์— ๋…ธ๋“œ ์‚ฝ์ž…
def insert_back(self, val):
    new_node = Node(val)
    
    if self.head is None:  # ๋นˆ ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ์ผ ๋•Œ
    	self.head = new_node
        self.head = new_node
        
    else:  # ๋นˆ ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ๊ฐ€ ์•„๋‹ ๋•Œ
    	self.tail.next = new_node
        self.tail = new_node
        
    self.nodeCount += 1

 

4. ๋…ธ๋“œ ์‚ญ์ œ

def delete_front(self):
    # ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ๊ฐ€ ๋น„์–ด์žˆ์ง€ ์•Š์„ ๊ฒฝ์šฐ
    current = self.head
    self.head = self.head.next
    del(current)
    self.nodeCount -= 1
 
 
def delete_middle(self, target):
    current = self.head
    
    while current != None:
    	previous = current
        currrent = current.next
        
        if curren.data == target:
            previous.next = current.next
            del(current)
            self.nodeCount -= 1
            break
            
            
def delete_back(self):
    # ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ๊ฐ€ ๋น„์–ด์žˆ์ง€ ์•Š์„ ๊ฒฝ์šฐ
    previous = None
    current = self.head
    
    while current.next != None:  # tail ๋…ธ๋“œ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ณ ์žˆ๋Š” ๋ฐ”๋กœ ์ด์ „ ๋…ธ๋“œ๋ฅผ ์ฐพ์•„์•ผํ•˜๋ฏ€๋กœ ์ „์ฒด ์ˆœํšŒ
    	previous = current
        currrent = current.next
    
    previous.next = None
    self.tail = previous
    del(current)
    self.nodeCount -= 1

 

 

์›ํ˜• ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ(Circular Linked List)

  • ๋‹จ์ˆœ ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ์—์„œ ๋งˆ์ง€๋ง‰ ๋…ธ๋“œ๊ฐ€ ๋‹ค์‹œ ์ฒซ ๋ฒˆ์งธ ๋…ธ๋“œ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋„๋ก ์„ค์ •ํ•œ ํ˜•ํƒœ์˜ ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ
  • NULL์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋…ธ๋“œ๊ฐ€ ์—†์Œ

 

โ€ป ์›ํ˜• ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ์˜ ๊ตฌํ˜„ ๋ฐฉ์‹์€ ๋‹จ์ˆœ ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ์™€ ๊ทธ ์›๋ฆฌ๊ฐ€ ๋น„์Šทํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์›ํ˜• ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ์˜ ๊ตฌํ˜„์€ ์ƒ๋žตํ•˜๊ฒ ์Œ.

 

 

์ด์ค‘ ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ(Doubly Linked List)

  • ๋‹จ์ˆœ ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ์—์„œ ๋‹ค์Œ ๋…ธ๋“œ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์ด์ „ ๋…ธ๋“œ์— ๋Œ€ํ•œ ์ฐธ์กฐ๋„ ๊ณ ๋ คํ•œ ํ˜•ํƒœ์˜ ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ
  • ๋…ธ๋“œ์™€ ๋…ธ๋“œ๊ฐ€ ์ƒํ˜ธ ์—ฐ๊ฒฐ
  • ์—ญ์ˆœ ์ ‘๊ทผ ๋ฐ ํƒ์ƒ‰ ๊ฐ€๋Šฅ

 

1. ๋…ธ๋“œ ์ƒ์„ฑ

class Node:
    def __init__(self, val):
        self.data = val
        self.prev = None
        self.next = None

 

2. ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ ์ดˆ๊ธฐํ™”

class DoublyLinkedList:
    def __init__(self):
        self.head = None  # ์ฒซ ๋ฒˆ์งธ ๋…ธ๋“œ
        self.tail = None  # ๋งˆ์ง€๋ง‰ ๋…ธ๋“œ
        self.head.next = self.tail
        self.tail.prev = self.head

 

3. ๋…ธ๋“œ ์‚ฝ์ž…

# ๋งจ ์•ž(head)์— ๋…ธ๋“œ ์‚ฝ์ž…
def insert_front(self, val):
    new_node = Node(val)
    
    if self.head is None:  # ๋นˆ ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ์ผ ๋•Œ
    	self.head = new_node
        self.tail = new_node
        self.head.next = tail
        self.tail.prev = head
        
    else:  # ๋นˆ ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ๊ฐ€ ์•„๋‹ ๋•Œ
    	new_node.next = self.head
        self.head.prev = new_node
        self.head = new_node
    
    self.nodeCount += 1
 
 
# ์ค‘๊ฐ„์— ๋…ธ๋“œ ์‚ฝ์ž…
def insert_middle(self, target, val):
    current = self.head
    
    while current != None:
    	previous = current
        current = current.next
        
        if previous.data == target:  # target ๊ฐ’์„ ๊ฐ€์ง„ ๋…ธ๋“œ ๋’ค์— ์‚ฝ์ž…
        	new_node = Node(val)
            new_node.next = current
            current.prev = new_node
            previous.next = new_node
            new_node.prev = previous
            self.nodeCount += 1
            break
                    	

# ๋งจ ๋(tail)์— ๋…ธ๋“œ ์‚ฝ์ž…
def insert_back(self, val):
    new_node = Node(val)
    
    if self.head is None:  # ๋นˆ ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ์ผ ๋•Œ
    	self.head = new_node
        self.head = new_node
        self.head.next = tail
        self.tail.prev = head
        
    else:  # ๋นˆ ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ๊ฐ€ ์•„๋‹ ๋•Œ
    	self.tail.next = new_node
        new_node.prev = self.tail
        self.tail = new_node
        
    self.nodeCount += 1

 

4. ๋…ธ๋“œ ์‚ญ์ œ

def delete_front(self):
    # ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ๊ฐ€ ๋น„์–ด์žˆ์ง€ ์•Š์„ ๊ฒฝ์šฐ
    current = self.head
    self.head = self.head.next
    self.head.prev = None
    del(current)
    self.nodeCount -= 1
 
 
def delete_middle(self, target):
    current = self.head
    
    # target์€ ์••์ชฝ์— ์œ„์น˜ํ•œ๋‹ค๊ณ  ๊ฐ€์ • (target ๋ฐ์ดํ„ฐ๊ฐ€ tail๊ณผ ๊ฐ€๊น๊ฒŒ(๋’ท์ชฝ์—) ์œ„์น˜ํ•œ๋‹ค๋ฉด ์—ญ์ˆœํšŒ๋กœ ๊ตฌํ˜„)
    while current != None:
        currrent = current.next
        
        if curren.data == target:
        	left = current.prev
            right = current.next
            left.next = right
            right.prev = left
            del(current)
            self.nodeCount -= 1
            break
            
            
def delete_back(self):
    # ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ๊ฐ€ ๋น„์–ด์žˆ์ง€ ์•Š์„ ๊ฒฝ์šฐ
    current = self.tail
    self.tail = self.tail.prev
    self.tail.next = None
    del(current)
    self.nodeCount -= 1

 

728x90