연결 리스트 : 고정 크기의 배열 등에 의해 구현된 선형 리스트의 단점을 보완한 자료구조
각 노드가 데이터와 포인터를 가지고 한 줄로 연결되어있는 방식으로 데이터를 저장하는 자료구조
각 노드는 다음 노드를 가리키는 포인터 포함
- 다음 노드를 가리키는 포인터 : 다음 노드의 주소를 값으로 가짐
{ node : (data, link) }
데이터 및 링크(포인터)에 의해 비연속적으로 연결된 선형 자료구조
배열 :
index
를 통해 원소 접근 - 데이터 주소의 식별자리스트 :
link
를 통해 원소 접근 - 데이터의 순서 식별자포인터로 연결됨
null
을 지시하여 리스트의 끝을 알림가변적인 메모리의 크기
원소의 순서 유지 및 접근
O(n)
소요구현 난이도 ↑
타 자료구조(ex. 추상자료형, ADT ...)의 기반
값(데이터) : 링크(포인터)
를 가짐데이터 | 링크
→ 다음 노드
→ 다음 노드
→ ...null
값을 가짐{ node : (prev link, data, next link) }
data
와 다음 노드로의 연결을 위한 next
포인터를 멤버 변수로 가짐class Node:
def __init__(self, data, next):
self.data = data # 데이터
self.next = next # 링크(포인터)
LinkedList
클래스에서는 링크드리스트의 노드 개수를 가리키는 no
, 첫 노드인 head
, 현재 노드인 current
멤버변수를 가짐
__len__
메소드를 통해 링크드리스트의 노드 개수, 즉 길이를 반환하는 기능 구현
연결리스트 용어
Head
노드Tail
노드, End
노드class LinkedList:
def __init__(self):
self.no = 0 # 링크드리스트 노드 개수
self.head = None # 머리 노드
self.current = None # 주목 노드
def __len__(self):
return self.no # 링크드리스트 노드 개수 반환
search
) 메소드, 포함 여부 확인(__contains__
) 메소드 구현search
메소드
ptr
)의 값을 head
~ tail
으로 선형탐색data
와 일치하는 노드를 발견하였을 때 해당 노드의 위치인 cnt
를 반환__contains__
메소드
search
메소드 실행을 통해 파라미터로 전달받은 data
의 포함 여부를 확인def search(self, data):
# data와 값이 같은 노드를 검색
cnt = 0
ptr = self.head
while ptr is not None:
if ptr.data == data:
self.current = ptr
return cnt
cnt += 1
ptr = ptr.next
return -1
def __contains__(self, data):
# 링크드리스트의 data 포함 여부를 확인
return self.search(data) >= 0
add_first
& add_last
) 구현add_first
: 링크드리스트의 앞에 노드를 추가하는 메소드
head
를 새로운 노드로 교체head
가 가리키던 노드를 새로운 노드의 다음 노드로 연결add_last
: 링크드리스트의 뒤에 노드를 추가하는 메소드
head
의 empty 여부add_first
)tail
노드로 이동해 tail노드의 다음 노드에 새로운 노드 추가# 맨 앞에 노드 삽입
def add_first(self, data):
ptr = self.head # 삽입 전의 머리 노드
self.head = self.current = Node(data, ptr)
self.no += 1
# 맨 뒤에 노드 삽입
def add_last(self, data):
if self.head is None : # 리스트가 비어 있으면
self.add_first(data) # 맨앞에 노드 삽입
else:
ptr = self.head
while ptr.next is not None:
ptr = ptr.next # while문을 종료할 때 ptr은 꼬리 노드를 참조
ptr.next = self.current = Node(data, None)
self.no += 1
remove_first
& remove_last
) 구현# 맨 앞 노드(head) 삭제
def remove_first(self):
if self.head is not None: # 리스트가 비어 있으면
self.head = self.current = self.head.next
self.no -= 1
# 맨 뒤 노드(tail) 삭제
def remove_last(self):
if self.head is not None:
if self.head.next is None : # 노드가 1개 뿐이라면
self.remove_first() # 머리 노드를 삭제
else:
ptr = self.head # 스캔 중인 노드
pre = self.head # 스캔 중인 노드의 앞쪽 노드
while ptr.next is not None:
pre = ptr
ptr = ptr.next # while문 종료시 ptr은 꼬리 노드를 참조하고 pre는 맨끝에서 두 번째 노드를 참조
pre.next = None # pre는 삭제 뒤 꼬리 노드
self.current = pre
self.no -= 1
remove
) 구현remove
메소드 p
를 head
노드부터 선형 탐색해 일치하는 노드를 삭제def remove(self, p):
if self.head is not None:
if p is self.head: # p가 머리 노드이면
self.remove_first() # 머리 노드를 삭제
else:
ptr = self.head
while ptr.next is not p:
ptr = ptr.next
if ptr is None:
return # ptr은 리스트에 존재하지 않음
ptr.next = p.next
self.current = ptr
self.no -= 1