자료구조

링크드 리스트

아몬드바 2023. 8. 10. 00:35
728x90

정의

 노드라는 단위의 데이터를 저장하고 테이터가 저장된 각 노드들을 순서대로 연결시켜서 만든 자료 구조

 

노드(각각의 객체)

 1. 데이터 : 값, 정보

 2. next : 다음노드에 대한 레퍼런스

 ex) n_1 -> n_2

       n_1.next = n_2

 3. head : 링크드리스트의 첫번째 노드 객체

 

 링크드 리스트 [접근] 시간 복잡도

  1. 접근하고 싶은 인덱스가 x라면

      -> 인덱스 x에 있는 노드에 접근하려면 head에서 다음 노드로 x번 간다.

      -> 최악의 경우 맨마지막 데이터까지 접근해야한다. 즉, head에서 다음 노드로 n -1 번 움직인다.

      -> O(n)

  링크드 리스트 [탐색] 시간 복잡도

   1. 접근하고 싶은 인덱스가 x라면

       -> 최악의 경우 맨마지막 데이터까지 접근해야한다.

       -> O(n)

  링크드 리스트 삽입, 삭제 시간 복잡도

   1. 삭제할 인덱스의 주변 노드들에 연결된 레퍼런스만 수정

       -> O(1)

 

class Node:
	"""링크드리스트의 노드 클래스"""
    def __init__(self, data):
    	self.data = data # 노드가 저장하는 데이터
        self.next = None # 다음 노드에 대한 레퍼런스
        
class LinkedList:
	"""링크드 리스트 클래스"""
    
    def __init__(self):
    	self.head = None
        self.tail = None
    
    def delete_after(self, previous_node):
    	"""링크드 리스트 삭제연산. 주어진 노드 뒤 노드를 삭제한다"""
        data = previous_node.next.data
        
        # 지우려는 노드가 tail 노드일 때:
        if previous_node.next is self.tail:
        	previous_node.next = None
            self.tail = previous_node
        # 두 노드 사이 노드를 지울 때:
        else:
        	previous_node.next = previous_node.next.next
        
        return data
        
    def insert_after(self, previous_node, data):
    	"""링크드 리스트 주어진 노드 뒤 삽입 연산 메소드"""
        # 새로운 데이터를 저장하는 노드
        # 원래 있는 링크드 리스트에 연결
        new_node = Node(data)
        # tail 노드 다음에 노드를 삽입할 때
        if previous_node is self.tail:
        	self.tail.next = new_node
            self.tail = new_node
        else: # 두 노드 사이에 삽입
        	new_node.next = previous_node.next
            previous_node.next = new_node
        	
    def find_node_at(self, index):
    	"""링크드 리스트 접근 연산 메소드. 파라미터 인덱스는 항상 있다고 가정"""
        iterator = self.head
        
        for _ in range(index):
        	iterator = iterator.next
        # n번째 노드를 가르킬려면 n번 연산해야하므로
        return iterator
    
    
    def append(self, data):
    	"""링크드 리스트 추가 연산 메소드"""
        new_node = Node(data)
        
        # 어차피 하나밖에 없으니까 head 이면서 tail이다.
        if self.head is None:
        	self.head = new_node
            self.tail = new_node
        else:
            # 현재 tail을 새로운 노드로
            # 추가된 노드가 tail 이므로 tail 설정
        	self.tail.next = new_node
            self.tail = new_node

# 새로운 링크드 리스트 생성
my_list = LinkedList()

# 링크드 리스트에 데이터 추가
my_list.append(2)
my_list.append(3)
my_list.append(5)
my_list.append(7)
my_list.append(11)

print(my_list)

node_2 = my_list.find_node_at(2) # 인덱스 2 노드 접근
my_list.delete_after(node_2) # 인덱스 2 뒤 데이터 삭제

print(my_list)

second_to_last_node = my_list.find_node_at(2) # 맨 끄텡서 두 번째 노드 접근
print(my_list.delete_after(second_to_last_node)) # tail 노드 삭제

print(my_list)

# 링크드 리스트 노드에 접근 (데이터 가지고 오기)
# 인덱스 3의 노드의 .data에 접근
print(my_list.find_node_at(3).data)

# 링크드 리스트 노드에 접근 (데이터 바꾸기)
my_list.find_node_at(2).data = 13

print(my_list) # 전체 링크드 리스트 출력

node_2 = my_list.find_node_at(2) # 인덱스 2에 있는 노드 접근
my_list.insert_after(node_2, 6) # 인덱스 2 뒤에 6 삽입

print(my_list)

head_node = my_list.head # 헤드 노드 접근
my_list.insert_after(head_node, 9) # 헤드 노드 뒤에 9 삽입


# 링크드 리스트 출력
iterator = my_list.head

while iterator is not None:
	print(iterator.data)
    iterator = iterator.next
        	
    
       
# 데이터 2, 3, 5, 7, 11을 담는 노드들 생성
head_node = Node(2)
node_1 = Node(3)
node_2 = Node(5)
node_3 = Node(7)
tail_node = Node(11)

# 노드들을 연결
head_node.next = node_1
node_1.next = node_2
node_2.next = node_3
node_3.next = tail_node

# 노드 순서대로 출력
iterator = head_noe

while iterator is not None:
	print(iterator.data)
    iterator = iterator.next
728x90