데이터를 삽입/삭제함에 따라 다른 데이터의 위치를 모두 옮겨야 하므로 효율적이지 않음
Node : 데이터와 다음 데이터를 가리키는 주소(포인터)로 이루어져 있다.
Pointer : 각 노드에서 다음 데이터를 가리키는 주소값을 가진다.
Head : 링크드리스트에서 가장 시작점인 데이터를 의미한다.
Tail : 링크드리스트에서 가장 마지막 데이터를 의미
Next=None(또는 Null) : 다음 데이터가 없을 경우 포인터의 주소값은 None(또는 Null)이다.
from __future__ import annotations
from typing import Any, Type
class Node:
"""연결 리스트용 노드 클래스"""
def __init__(self, data: Any = None, next: Node = None):
"""초기화"""
self.data = data # 데이터
self.next = next # 뒤쪽 포인터
class LinkedList:
"""연결 리스트 클래스"""
def __init__(self) -> None:
"""초기화"""
self.no = 0 # 노드의 개수
self.head = None # 머리 노드
self.current = None # 주목 노드
def __len__(self) -> int:
"""연결 리스트의 노드 개수를 반환"""
return self.no
def search(self, data: Any) -> int:
"""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: Any) -> bool:
"""연결 리스트에 data가 포함되어 있는가?"""
return self.search(data) >= 0
def add_first(self, data: Any) -> None:
"""맨 앞에 노드를 삽입"""
ptr = self.head # 삽입 전의 머리 노드
self.head = self.current = Node(data, ptr)
self.no += 1
def add_last(self, data: Any):
"""맨 끝에 노드를 삽입"""
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
def remove_first(self) -> None:
"""머리 노드를 삭제"""
if self.head is not None: # 리스트가 비어 있으면
self.head = self.current = self.head.next
self.no -= 1
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
def remove(self, p: Node) -> None:
"""노드 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
def remove_current_node(self) -> None:
"""주목 노드를 삭제"""
self.remove(self.current)
def clear(self) -> None:
"""전체 노드를 삭제"""
while self.head is not None: # 전체가 비어 있게 될 때까지
self.remove_first() # 머리 노드를 삭제
self.current = None
self.no = 0
def next(self) -> bool:
"""주목 노드를 한 칸 뒤로 진행"""
if self.current is None or self.current.next is None:
return False # 진행할 수 없음
self.current = self.current.next
return True
def print_current_node(self) -> None:
"""주목 노드를 출력"""
if self.current is None:
print('주목 노드가 존재하지 않습니다.')
else:
print(self.current.data)
def print(self) -> None:
"""모든 노드를 출력"""
ptr = self.head
while ptr is not None:
print(ptr.data)
ptr = ptr.next
def __iter__(self) -> LinkedListIterator:
"""이터레이터(반복자)를 반환"""
return LinkedListIterator(self.head)
class LinkedListIterator:
"""클래스 LinkedList의 이터레이터(반복자)용 클래스"""
def __init__(self, head: Node):
self.current = head
def __iter__(self) -> LinkedListIterator:
return self
def __next__(self) -> Any:
if self.current is None:
raise StopIteration
else:
data = self.current.data
self.current = self.current.next
return data
from __future__ import annotations
from typing import Any, Type
Null = -1
class Node:
"""선형 리스트용 노드 클래스(배열 커서 버전)"""
def __init__(self, data = Null, next = Null, dnext = Null):
"""초기화"""
self.data = data # 데이터
self.next = next # 리스트의 뒤쪽 포인터
self.dnext = dnext # 프리 리스트의 뒤쪽 포인터
class ArrayLinkedList:
"""선형 리스트 클래스(배열 커서 버전)"""
def __init__(self, capacity: int):
"""초기화"""
self.head = Null # 머리 노드
self.current = Null # 주목 노드
self.max = Null # 사용 중인 맨끝 레코드
self.deleted = Null # 프리 리스트의 머리 노드
self.capacity = capacity # 리스트의 크기
self.n = [Node()] * self.capacity # 리스트 본체
self.no = 0
def __len__(self) -> int:
"""선형 리스트의 노드 수를 반환"""
return self.no
def get_insert_index(self):
"""다음에 삽입할 레코드의 첨자를 구합니다"""
if self.deleted == Null: # 삭제 레코드는 존재하지 않습니다
if self.max+1 < self.capacity:
self.max += 1
return self.max # 새 레코드를 사용
else:
return Null # 크기 초과
else:
rec = self.deleted # 프리 리스트에서
self.deleted = self.n[rec].dnext # 맨 앞 rec를 꺼내기
return rec
def delete_index(self, idx: int) -> None:
"""레코드 idx를 프리 리스트에 등록"""
if self.deleted == Null: # 삭제 레코드는 존재하지 않습니다
self.deleted = idx # idx를 프리 리스트의
self.n[idx].dnext = Null # 맨 앞에 등록
else:
rec = self.deleted # idx를 프리 리스트의
self.deleted = idx # 맨 앞에 삽입
self.n[idx].dnext = rec
def search(self, data: Any) -> int:
"""data와 값이 같은 노드를 검색"""
cnt = 0
ptr = self.head # 현재 스캔 중인 노드
while ptr != Null:
if self.n[ptr].data == data:
self.current = ptr
return cnt # 검색 성공
cnt += 1
ptr = self.n[ptr].next # 뒤쪽 노드에 주목
return Null # 검색 실패
def __contains__(self, data: Any) -> bool:
"""선형 리스트에 data가 포함되어 있는지 확인"""
return self.search(data) >= 0
def add_first(self, data: Any):
"""머리 노드에 삽입"""
ptr = self.head # 삽입하기 전의 머리 노드
rec = self.get_insert_index()
if rec != Null:
self.head = self.current = rec # rec번째 레코드에 삽입
self.n[self.head] = Node(data, ptr)
self.no += 1
def add_last(self, data: Any) -> None:
"""꼬리 노드에 삽입"""
if self.head == Null: # 리스트가 비어 있으면
self.add_first(data) # 맨 앞에 노드 삽입
else:
ptr = self.head
while self.n[ptr].next != Null:
ptr = self.n[ptr].next
rec = self.get_insert_index()
if rec != Null: # rec번째 레코드에 삽입
self.n[ptr].next = self.current = rec
self.n[rec] = Node(data)
self.no += 1
def remove_first(self) -> None:
"""머리 노드를 삭제"""
if self.head != Null: # 리스트가 비어 있으면
ptr = self.n[self.head].next
self.delete_index(self.head)
self.head = self.current = ptr
self.no -= 1
def remove_last(self) -> None:
"""꼬리 노드를 삭제"""
if self.head != Null:
if self.n[self.head].next == Null: # 노드가 1개 뿐이면
self.remove_first() # 머리 노드를 삭제
else:
ptr = self.head # 스캔 중인 노드
pre = self.head # 스캔 중인 노드의 앞쪽 노드
while self.n[ptr].next != Null:
pre = ptr
ptr = self.n[ptr].next
self.n[pre].next = Null # pre는 삭제한 뒤의 꼬리 노드
self.delete_index(ptr)
self.current = pre
self.no -= 1
def remove(self, p: int) -> None:
"""레코드 p를 삭제"""
if self.head != Null:
if p == self.head: # p가 머리 노드면
self.remove_first() # 머리 노드를 삭제
else:
ptr = self.head
while self.n[ptr].next != p:
ptr = self.n[ptr].next
if ptr == Null:
return # p는 리스트에 존재하지 않음
#self.n[ptr].next = Null
self.delete_index(p)
self.n[ptr].next = self.n[p].next
self.current = ptr
self.no -= 1
def remove_current_node(self) -> None:
"""주목 노드를 삭제"""
self.remove(self.current)
def clear(self) -> None:
"""모든 노드를 삭제"""
while self.head != Null: # 리스트 전체가 빌 때까지
self.remove_first() # 머리 노드를 삭제
self.current = Null
def next(self) -> bool:
"""주목 노드를 한 칸 뒤로 진행"""
if self.current == Null or self.n[self.current].next == Null:
return False # 진행할 수 없음
self.current = self.n[self.current].next
return True
def print_current_node(self) -> None:
"""주목 노드를 출력"""
if self.current == Null:
print('주목 노드가 없습니다.')
else:
print(self.n[self.current].data)
def print(self) -> None:
"""모든 노드를 출력"""
ptr = self.head
while ptr != Null:
print(self.n[ptr].data)
ptr = self.n[ptr].next
def dump(self) -> None:
"""배열을 덤프"""
for i in self.n:
print(f'[{i}] {i.data} {i.next} {i.dnext}')
def __iter__(self) -> ArrayLinkedListIterator:
"""이터레이터를 반환"""
return ArrayLinkedListIterator(self.n, self.head)
class ArrayLinkedListIterator:
"""클래스 ArrayLinkedList의 이터레이터용 클래스"""
def __init__(self, n: int, head: int):
self.n = n
self.current = head
def __iter__(self) -> ArrayLinkedListIterator:
return self
def __next__(self) -> Any:
if self.current == Null:
raise StopIteration
else:
data = self.n[self.current].data
self.current = self.n[self.current].next
return data
꼬리 노드의 뒤쪽 포인터가 None이 아니라 머리 노드의 포인터 값임
from __future__ import annotations
from typing import Any, Type
class Node:
"""원형 이중 연결 리스트용 노드 클래스"""
def __init__(self, data: Any = None, prev: Node = None,
next: Node = None) -> None:
"""초기화"""
self.data = data # 데이터
self.prev = prev or self # 앞쪽 포인터
self.next = next or self # 뒤쪽 포인터
class DoubleLinkedList:
"""원형 이중 연결 리스트 클래스"""
def __init__(self) -> None:
"""초기화"""
self.head = self.current = Node() # 더미 노드를 생성
self.no = 0
def __len__(self) -> int:
"""선형 리스트의 노드 수를 반환"""
return self.no
def is_empty(self) -> bool:
"""리스트가 비어 있는가?"""
return self.head.next is self.head
def search(self, data: Any) -> Any:
"""data와 값이 같은 노드를 검색"""
cnt = 0
ptr = self.head.next # 현재 스캔 중인 노드
while ptr is not self.head:
if data == ptr.data:
self.current = ptr
return cnt # 검색 성공
cnt += 1
ptr = ptr.next # 뒤쪽 노드에 주목
return -1 # 검색 실패
def __contains__(self, data: Any) -> bool:
"""연결 리스트에 data가 포함되어 있는가?"""
return self.search(data) >= 0
def print_current_node(self) -> None:
"""주목 노드를 출력"""
if self.is_empty():
print('주목 노드는 없습니다.')
else:
print(self.current.data)
def print(self) -> None:
"""모든 노드를 출력"""
ptr = self.head.next # 더미 노드의 뒤쪽 노드
while ptr is not self.head:
print(ptr.data)
ptr = ptr.next
def print_reverse(self) -> None:
"""모든 노드를 역순으로 출력"""
ptr = self.head.prev # 더미 노드의 앞쪽 노드
while ptr is not self.head:
print(ptr.data)
ptr = ptr.prev
def next(self) -> bool:
"""주목 노드를 한 칸 뒤로 이동"""
if self.is_empty() or self.current.next is self.head:
return False # 이동할 수 없음
self.current = self.current.next
return True
def prev(self) -> bool:
"""주목 노드를 한 칸 앞으로 이동"""
if self.is_empty() or self.current.prev is self.head:
return False # 이동할 수 없음
self.current = self.current.prev
return True
def add(self, data: Any) -> None:
"""주목 노드의 바로 뒤에 노드를 삽입"""
node = Node(data, self.current, self.current.next)
self.current.next.prev = node
self.current.next = node
self.current = node
self.no += 1
def add_first(self, data: Any) -> None:
"""맨 앞에 노드를 삽입"""
self.current = self.head # 더미 노드 head의 바로 뒤에 삽입
self.add(data)
def add_last(self, data: Any) -> None:
"""맨 뒤에 노드를 삽입"""
self.current = self.head.prev # 꼬리 노드 head.prev의 바로 뒤에 삽입
self.add(data)
def remove_current_node(self) -> None:
"""주목 노드 삭제"""
if not self.is_empty():
self.current.prev.next = self.current.next
self.current.next.prev = self.current.prev
self.current = self.current.prev
self.no -= 1
if self.current is self.head:
self.current = self.head.next
def remove(self, p: Node) -> None:
"""노드 p를 삭제"""
ptr = self.head.next
while ptr is not self.head:
if ptr is p: # p를 발견
self.current = p
self.remove_current_node()
break
ptr = ptr.next
def remove_first(self) -> None:
"""머리 노드 삭제"""
self.current = self.head.next # 머리 노드 head.next를 삭제
self.remove_current_node()
def remove_last(self) -> None:
"""꼬리 노드 삭제"""
self.current = self.head.prev # 꼬리 노드 head.prev를 삭제
self.remove_current_node()
def clear(self) -> None:
"""모든 노드를 삭제"""
while not self.is_empty(): # 리스트 전체가 빌 때까지
self.remove_first() # 머리 노드를 삭제
self.no = 0
# Do it! 실습 8-5[F]
def __iter__(self) -> DoubleLinkedListIterator:
"""반복자를 반환"""
return DoubleLinkedListIterator(self.head)
def __reversed__(self) -> DoubleLinkedListReverseIterator:
"""내림차순 반복자를 반환"""
return DoubleLinkedListReverseIterator(self.head)
class DoubleLinkedListIterator:
"""DoubleLinkedList의 반복자용 클래스"""
def __init__(self, head: Node):
self.head = head
self.current = head.next
def __iter__(self) -> DoubleLinkedListIterator:
return self
def __next__(self) -> Any:
if self.current is self.head:
raise StopIteration
else:
data = self.current.data
self.current = self.current.next
return data
class DoubleLinkedListReverseIterator:
"""DoubleLinkedList의 내림차순 반복자용 클래스"""
def __init__(self, head: Node):
self.head = head
self.current = head.prev
def __iter__(self) -> DoubleLinkedListReverseIterator:
return self
def __next__(self) -> Any:
if self.current is self.head:
raise StopIteration
else:
data = self.current.data
self.current = self.current.prev
return data