추상 데이터 타입의 리스트를 구현한 자료구조이다.
순서가 있는 값을 저장하지만 링크드리스트에는 인덱스가 없다.
링크드 리스트는 순서가 있는 자료구조이지만 연속적인 메모리 블록에 저장되지 않는다.
그 대신 링크드 리스트는 노드로 이루어져있다.
노드 = 필드 + 포인터
데이터가 평균일 때
접근 | 탐색 | 삽입 | 삭제 | |
---|---|---|---|---|
배열 | O(1) | O(n) | O(n) | O(1) |
링크드 리스트 | O(n) | O(n) | O(1) | O(1) |
배열 접근이 O(1)인 이유
인덱스를 알고 있으면 바로 접근이 가능하다.
링크드 리스트 접근이 O(n)인 이유
노드로 연결되어 있는 리스트를 선형 탐색해야만 원하는 요소에 접근할 수 있기 때문이다.
⭐ 링크드 리스트 삽입이 O(1)인 이유
한 노드를 삽입하려고 할 때, 앞선 노드의 포인터 값을 추가하려는 노드의 주소값으로 변경하고, 삽입하려고하는 노드의 포인터를 이후 노드의 주소로 추가하면 된다.
따라서 메모리 할당이나 추가적인 작업이 필요하지 않다.
👉 링크드 리스트의 장점
포인터를 저장하기 위한 추가적인 메모리 공간이 필요하다.
임의 접근이 힘들다.
인덱스 값이 없기 때문에, 무조건 포인터를 따라 움직여야한다.
왜 자료구조를 C언어로 듣는지 알 것 같다..ㅎ
class Node:
def __init__(self,data,next=None):
self.data = data
self.next = next
class LinkedList:
def __init__(self):
self.head = None
def append(self,data):
if not self.head:
self.head = Node(data)
return
current = self.head
while current.next:
current = current.next
current.next = Node(data)
이 링크드 리스트는 맨 뒤에 추가하도록 했다.
따라서 current
가 맨 마지막일 때까지 반복문을 돌리고,
current.next
에 해당 값을 추가하도록 했다.
def __str__(self):
re = ""
node = self.head
while node is not None:
re += str(node.data) +" "
node = node.next
return re
교재에서는 직접 print
를 하도록 되어있는데, 파이썬에서 __str__
는 기본적으로 문자열을 반환하는 것으로 되어있다.
따라서 문자열을 반환하도록 수정하였다.
def serch(self,target):
current = self.head
if current is None:
return False
while current is not None:
if current.data == target:
return True
current = current.next
return False
아주 간단했다 👍
def removeAll(self,target):
while self.head.data is target:
self.head = self.head.next
currnet = self.head.next
pre = self.head
while currnet:
if currnet.data == target:
pre.next = currnet.next
else:
pre = currnet
currnet = currnet.next
만약 현재 노드의 데이터 값이 삭제하고자 하는 값이었다면 제거한다.
이때 제거 하고 나서는 이전 노드를 의미하는 pre
를 현재 노드로 업데이트 해주면 안된다.
def reverse_list(self):
current = self.head
previous = None
while current: #지금
next = current.next
current.next = previous
previous = current
current = next
self.head = previous
맨 처음의 next
에 None
을 넣어야하는게 까다로웠다.
class LinkedListCycle:
def __init__(self):
self.head = None
def append(self,data):
if not self.head:
self.head = Node(data)
self.head.next = self.head
return
current = self.head
while current.next != self.head:
current = current.next
current.next = Node(data)
current = current.next
current.next = self.head
def __str__(self):
re = ""
node = self.head
if node is not None:
re += str(node.data) +" "
node = node.next
while node is not self.head:
re += str(node.data) +" "
node = node.next
return re
def serch(self,target):
current = self.head
if current is None:
return False
if current.data == target:
return True
current = current.next
while current is not self.head:
if current.data == target:
return True
current = current.next
return False
def removeAll(self,target):
while self.head.data is target:
if self.head.next == self.head:
self.head = None
return
else:
self.head = self.head.next
currnet = self.head.next
pre = self.head
while currnet != self.head:
if currnet.data == target:
pre.next = currnet.next
else:
pre = currnet
currnet = currnet.next
def detect_cycle(self):
slow = self.head
fast = self.head
while True:
try:
slow = slow.next
fast = fast.next.next
if slow is fast:
return True
except:
return False
def detect_cycle(self):
slow = self.head
fast = self.head
while True:
try:
slow = slow.next
fast = fast.next.next
if slow is fast:
return True
except:
return False
사이클이 있다면 언젠가는 동일해진다.