🌈 Linked List
🔥 연결 리스트(Linked List) 란?
🔥 연결 리스트 예시
🔥 객체지향 프로그래밍으로 연결 리스트 구현
🔥 연결 리스트 삭제 메서드 추가
🔥 이중 연결 리스트(Double linked list) 란?
1. 연결 리스트(Linked List) 란?
- 분리된 곳에 존재하는 데이터를 화살표로 연결해서 관리하는 데이터 구조를 연결 리스트라함
- python에서는 list 타입에서 연결 리스트 기능을 모두 지원함
- 연결 리스트 기본 구조와 용어
- 노드(Node) : 데이터 저장 단위(데이터값, 포인터)로 구성
- 포인터(Pointer) : 각 노드 안에서, 다음이나 이전의 노드와의 연결 정보를 가지고 있는 공간
- 즉, 연결 리스트는 일반 배열과 달리 데이터 뿐 아니라 다음 데이터를 가르키는 주소(포인터)를 함께 가지고 있음
2. 연결 리스트 예시
1. 기본 연결리스트
- 연결 리스트는 데이터와 pointer가 Node로 구성되어 있기 때문에 이를 class 속성으로 구현 가능
- 연결된 리스트가 없는 경우(노드가 1개 뿐이거나, 마지막 노드인 경우)에 pointer 값은 None을 가짐
- 연결 리스트는 맨 첫번째 노드만 알면, 모든 노드를 확인할 수 있기 때문에 맨 앞에 노드를 head에 저장
class Node:
def __init__(self, data, next=None):
self.data = data
self.next = next
node1 = Node(11)
node2 = Node(22)
node3 = Node(33)
node1.next = node2
node2.next = node3
head = node1
node = head
while node.next:
print(node.data)
node = node.next
print(node.data)
2. 추가된 node 마지막에 삽입하여 연결하는 방법
- add 함수를 통해 node 생성 및 연결 방법 : 맨 첫 node부터 next를 반복하여, pointer(node.next)가 없다면, 현재의 pointer를 새로운 데이터와 연결
class Node:
def __init__(self, data, next=None):
self.data = data
self.next = next
def add(data):
node = head
while node.next:
node = node.next
node.next = Node(data)
node1 = Node(0)
head = node1
for i in range(1,10):
add(i)
node = head
while node.next:
print(node.data)
node = node.next
print(node.data)
3. 추가된 node 중간에 삽입 방법
- 노드 중간에 삽입하려면, 추가할 위치를 찾은 뒤 새로운 값을 연결시켜주고 그 새로운 값의 pointer에 다시 그 다음 노드의 값을 연결시켜줘야함
- 추가할 node의 pointer를 새로운 값을 가르키게하기기 전, 기존 node가 갖고 있던 pointer값을 다른 변수에 담아두었다가 새로운 값 연결 후, 그 새로운 값에 연이어 연결시켜주는 로직
class Node:
def __init__(self, data, next=None):
self.data = data
self.next = next
def add(data):
node = head
while node.next:
node = node.next
node.next = Node(data)
node1 = Node(0)
head = node1
for i in range(1,10):
add(i)
node3 = Node(1.5)
node = head
search = True
while search:
if node.data == 1:
search = False
else:
node = node.next
node_next = node.next
node.next = node3
node3.next = node_next
node = head
while node.next:
print(node.data)
node = node.next
print(node.data)
3. 객체지향 프로그래밍으로 연결 리스트 구현
- class Node는 노드 속성을 갖고 있고, class NodeMamt에서는 메서드를 통해 node를 관리함
- add 메서드를 통해 haed 값이 아직 존재하지 않을 때에는 맨 첫번째 추가된 노드를 haed에 담을 수 있게 해두고, head가 있다면 마지막 노드의 pointer(node.next)에 추가되는 노드를 연결
class Node:
def __init__(self, data, next=None):
self.data = data
self.next = next
class NodeMgmt:
def __init__(self, data):
self.head = Node(data)
def add(self, data):
if self.head == '':
self.head = Node(data)
else:
node = self.head
while node.next:
node = node.next
node.next = Node(data)
def desc(self):
node = self.head
while node:
print(node.data)
node = node.next
linkedlist1 = NodeMgmt(0)
linkedlist1.desc()
for data in range(1,10):
linkedlist1.add(data)
linkedlist1.desc()
4. 연결 리스트 삭제 메서드 추가
- 노드를 지운다는 것을 4가지의 경우의 수를 가짐
- node가 없는데 node 삭제를 요청 할 경우 : node가 없음을 출력함
- haed를 지우는 경우 : 임시값에 삭제할 Node인 head를 보관 ⇢ head의 다음 Node를 head로 교체 ⇢ 임시값에 저장된 원래 head를 삭제
- 중간 node를 지우는 경우 : 삭제할 node인 node.next를 찾기 ⇢ 삭제할 현재 노드(node.next)를 임시 값에 보관 ⇢ 현재 node(node.netx)를 다음 노드로 교체 ⇢ 임시값 삭제
- 마지막 node를 지우는 경우 : 위와 동일
def delete(self, data):
if self.head == '':
print('Empty Node')
if self.head.data == data:
temp = self.head
self.head = self.head.next
del temp
else:
node = self.head
while node.next:
if node.next.data == data:
temp = node.next
node.next = node.next.next
del temp
else:
node = node.next
class Node:
def __init__(self, data, next=None):
self.data = data
self.next = next
class NodeMgmt:
def __init__(self, data):
self.head = Node(data)
def add(self, data):
if self.head == '':
self.head = Node(data)
else:
node = self.head
while node.next:
node = node.next
node.next = Node(data)
def desc(self):
node = self.head
while node:
print(node.data)
node = node.next
def delete(self, data):
if self.head == '':
print('Empty Node')
if self.head.data == data:
temp = self.head
self.head = self.head.next
del temp
else:
node = self.head
while node.next:
if node.next.data == data:
temp = node.next
node.next = node.next.next
del temp
else:
node = node.next
linkedlist1 = NodeMgmt(0)
for data in range(1,10):
linkedlist1.add(data)
linkedlist1.delete(0)
linkedlist1.desc()
linkedlist1.delete(5)
linkedlist1.desc()
linkedlist1.delete(9)
linkedlist1.desc()
5. 이중 연결 리스트(Double linked list) 란?
- 노드가 10000개일 때, 8000번째 노드를 찾으려면 head부터 7999번 이동 해야하는 비효율성이 존재함
- 뒤에서 부터 역순으로 노트를 탐색하기 위해 고안된 것이 이중 연결 리스트임
- 이에 이중 연결 리스트는 각 노드마다 이전 데이터 주소, 데이터, 다음 데이터 주소를 갖음
- 이중 연결 리스트는 head와 tail을 가지고, 연결 주소도 next(다음)와 prev(이전)를 가짐
1) 이중 연결 리스트 기본 구조
class Node:
def __init__(self, data, prev=None, next=None):
self.data = data
self.prev = prev
self.next = next
class NodeMgmt:
def __init__(self, data):
self.head = Node(data)
self.tail = self.head
def insert(self, data):
if self.head == None:
self.head = Node(data)
self.tail = self.head
else:
node = self.head
while node.next:
node = node.next
new = Node(data)
node.next = new
new.prev = node
self.tail = new
def desc(self):
node = self.head
while node:
print(node.data)
node = node.next
double_linked_list = NodeMgmt(0)
for data in range(1,10):
double_linked_list.insert(data)
double_linked_list.desc()
2) 이중 연결 리스트 검색 기능 추가
- 이중 연결 리스트에서 검색 기능은 head부터 찾는 매서드와 tail부터 찾는 메서드로 구현
class Node:
def __init__(self, data, prev=None, next=None):
self.data = data
self.prev = prev
self.next = next
class NodeMgmt:
def __init__(self, data):
self.head = Node(data)
self.tail = self.head
def insert(self, data):
if self.head == None:
self.head = Node(data)
self.tail = self.head
else:
node = self.head
while node.next:
node = node.next
new = Node(data)
node.next = new
new.prev = node
self.tail = new
def desc(self):
node = self.head
while node:
print(node.data)
node = node.next
def search_form_head(self, data):
if self.head == None:
return False
node = self.head
while node:
if node.data == data:
return node
else:
node = node.next
return False
def search_form_tail(self, data):
if self.tail == None:
return False
node = self.tail
while node:
if node.data == data:
return node
else:
node = node.prev
return False
double_linked_list = NodeMgmt(0)
for data in range(1,10):
double_linked_list.insert(data)
double_linked_list.desc()
get_data_head = double_linked_list.search_form_head(3)
if get_data_head:
print(get_data_head.data)
else:
print(None)
get_data_tail = double_linked_list.search_form_tail(8)
if get_data_tail:
print(get_data_tail.data)
else:
print(None)
3) 이중 연결 리스트 중간 삽입 기능 추가
class Node:
def __init__(self, data, prev=None, next=None):
self.data = data
self.prev = prev
self.next = next
class NodeMgmt:
def __init__(self, data):
self.head = Node(data)
self.tail = self.head
def insert(self, data):
if self.head == None:
self.head = Node(data)
self.tail = self.head
else:
node = self.head
while node.next:
node = node.next
new = Node(data)
node.next = new
new.prev = node
self.tail = new
def desc(self):
node = self.head
while node:
print(node.data)
node = node.next
def search_form_head(self, data):
if self.head == None:
return False
node = self.head
while node:
if node.data == data:
return True
else:
node = node.next
return False
def search_form_tail(self, data):
if self.tail == None:
return False
node = self.tail
while node:
if node.data == data:
return True
else:
node = node.prev
return False
def insert_before(self, data, before_data):
if self.head == None:
self.head = Node(data)
return True
else:
node = self.tail
while node.data != before_data:
node = node.prev
if node == None:
return False
new = Node(data)
before_new = node.prev
before_new.next = new
new.prev = before_new
new.next = node
node.prev = new
return True
double_linked_list = NodeMgmt(0)
for data in range(1,10):
double_linked_list.insert(data)
double_linked_list.desc()
double_linked_list.insert_before(1.5, 2)
double_linked_list.desc()