Data structure & Algorithms study
단일 연결 리스트 (Singly Linked List)
adulty22
2024. 5. 27. 17:15
단일 연결 리스트 (Singly Linked List)
단일 연결 리스트(Singly Linked List)는 선형 자료 구조 중 하나로, 각 노드가 하나의 데이터 요소와 다음 노드를 가리키는 포인터를 포함하는 형태로 구성된다. 연결 리스트는 배열과 달리 요소들이 메모리상에 연속적으로 배치되지 않으며, 각 노드가 다음 노드를 가리키고 있어 동적 메모리 할당이 가능하다.
구조
- 노드 (Node): 연결 리스트의 기본 구성 요소로, 데이터와 다음 노드를 가리키는 포인터를 포함한다.
- 데이터 (Data): 노드가 저장하는 값.
- 다음 (Next): 다음 노드를 가리키는 포인터.
- 헤드 (Head): 리스트의 첫 번째 노드를 가리키는 포인터. 리스트의 시작점이다.
- 꼬리 (Tail): 리스트의 마지막 노드를 가리키는 포인터 (단일 연결 리스트에서는 일반적으로 사용되지 않음).
단일 연결 리스트의 연산
- 삽입 (Insertion):
- 앞쪽 삽입 (Insert at the Beginning): 새 노드를 헤드 앞에 추가하고, 헤드를 새 노드로 갱신한다.
- 끝쪽 삽입 (Insert at the End): 새 노드를 리스트의 끝에 추가한다.
- 중간 삽입 (Insert in the Middle): 특정 위치에 새 노드를 삽입한다.
- 삭제 (Deletion):
- 앞쪽 삭제 (Delete from the Beginning): 첫 번째 노드를 삭제하고, 헤드를 다음 노드로 갱신한다.
- 끝쪽 삭제 (Delete from the End): 마지막 노드를 삭제한다.
- 중간 삭제 (Delete in the Middle): 특정 위치의 노드를 삭제한다.
- 탐색 (Search): 리스트를 순회하면서 특정 값을 가진 노드를 찾는다.
- 길이 반환 (Get Length): 리스트에 포함된 노드의 개수를 반환한다.
- 출력 (Display): 리스트의 모든 노드를 순서대로 출력한다.
단일 연결 리스트의 활용 예
- 동적 메모리 할당: 메모리의 크기를 동적으로 조정할 수 있어, 크기가 가변적인 데이터 구조를 만들 수 있다.
- 구현 용이성: 삽입과 삭제가 용이하여, 자주 삽입과 삭제가 일어나는 응용 프로그램에서 사용된다.
- 기타 자료 구조의 기반: 스택, 큐, 덱 등 다른 자료 구조의 구현에 기반이 될 수 있다.
단일 연결 리스트의 장단점
장점:
- 동적 크기 조정: 배열과 달리 리스트의 크기를 동적으로 조정할 수 있다.
- 삽입 및 삭제 연산의 용이성: 리스트의 특정 위치에서의 삽입과 삭제가 빠르게 이루어질 수 있다.
단점:
- 임의 접근 불가: 배열과 달리 임의의 인덱스로 접근하는 데 시간이 오래 걸린다 (O(n)).
- 추가 메모리 사용: 각 노드가 데이터 외에도 다음 노드를 가리키는 포인터를 저장해야 하므로 추가 메모리를 사용한다.
구현 코드
class Node:
def __init__(self, data=None):
self._data = data
self._next = None
def setNext(self, next):
self._next = next
def getNext(self):
return self._next
def getData(self):
return self._data
class SinglyLinkedList:
def __init__(self):
self._head = None
def insertBeginning(self, data):
new_node = Node(data)
new_node.setNext(self._head)
self._head = new_node
def insertEnd(self, data):
new_node = Node(data)
if self._head is None:
self._head = new_node
return
last = self._head
while last.getNext():
last = last.getNext()
last.setNext(new_node)
def insertMiddle(self, data, index):
if index < 0:
print("Invalid position")
return
new_node = Node(data)
if index == 0:
new_node.setNext(self._head)
self._head = new_node
return
cur = self._head
for i in range(index - 1):
if cur is None:
print("Index out of bounds")
return
cur = cur.getNext()
if cur is None:
print("Index out of bounds")
return
new_node.setNext(cur.getNext())
cur.setNext(new_node)
def deleteNode(self, key):
temp = self._head
if temp is not None:
if temp.getData() == key:
self._head = temp.getNext()
temp = None
return
while temp is not None:
if temp.getData() == key:
break
prev = temp
temp = temp.getNext()
if temp == None:
return
prev.setNext(temp.getNext())
temp = None
def search(self, key):
cur = self._head
while cur is not None:
if cur.getData() == key:
return True
cur = cur.getNext()
return False
def getLength(self) -> int:
count = 0
cur = self._head
while cur:
count += 1
cur = cur.getNext()
return count
def display(self):
cur = self._head
while cur:
print(cur.getData(), end=" -> ")
cur = cur.getNext()
print("None")
sll = SinglyLinkedList()
sll.insertEnd(10)
sll.insertEnd(20)
sll.insertBeginning(5)
sll.insertMiddle(15, 2) # Insert 15 at position 2
sll.display() # 5 -> 10 -> 15 -> 20 -> None
print(sll.search(10)) # True
print(sll.getLength()) # 4
sll.deleteNode(10)
sll.display() # 5 -> 15 -> 20 -> None
모든 코드는 github에 저장되어 있습니다.
https://github.com/SeongUk18/Algorithm/tree/main/Data_structure_algorithms
728x90