티스토리 뷰
'어서와! 자료구조와 알고리즘은 처음이지?'
양방향 연결리스트(이중 연결리스트)
양 쪽으로 링크를 연결하여 앞으로도 (다음 Node) 뒤로도 (이전 Node) 로도 진행이 가능한 연결리스트이다. 리스트의 처음과 끝에 Dummy Node를 두어 데이터를 담고 있는 Node들이 모두 같은 모양이 되도록 한다.
class Node:
def __init__(self, item):
self.data = item
self.prev = None
self.next = None
class DoubleLinkedList:
def __init__(self, item):
self.node_count = 0
self.head = Node(None)
self.tail = Node(None)
self.head.prev = None
self.tail.prev = self.head
self.tail.next = None
리스트 순회
# head와 tail 이 모두 dummy 노드인 경우에도 위의 traverse() 코드가 성립한다.
def traverse(self):
result = []
curr = self.head
while curr.next.next:
curr = curr.next
result.append(curr.data)
return result
리스트 역 순회
# head 와 tail 이 모두 dummy 노드인 경우에도 성립한다.
def reverse(self):
result = []
curr = self.tail
while curr.prev.prev:
curr = curr.prev
result.append(curr.data)
return result
원소의 삽입
def insert_after(self, prev, new_node):
next = prev.next
new_node.prev = prev
new_node.next = next
prev.next = new_node
next.prev = new_node
self.node_count += 1
return True
특정 원소 얻어내기
# 단일 연결리스트 get_at() 메서드와 완전히 동일
def get_at(self,pos):
if pos < 0 or pos > self.node_count:
return None
i = 0
curr = self.head
while i < pos:
curr = curr.next
i += 1
return curr
원소의 삽입( insert_after( ) )
def insert_at(self, pos, new_node):
if pos < 1 or pos > self.node_count + 1:
return False
prev = self.get_at(pos-1)
return self.insert_after(prev, new_node)
리스트 마지막에 원소를 삽입하려면 단일 연결리스트에서는 prev를 구하기 위해 get_at() 로 전체를 순회 했어야 했다. 하지만 양방향 연결리스트를 사용하면 get_at()을 다음과 같이 수정하여 prev 탐색 효율을 높일 수 있다.
def get_at(self, pos):
if pos < 0 or pos > self.node_count:
return None
if pos > self.node_count // 2:
i = 0
curr = self.tail
while i < self.node_count - pos + 1:
curr = curr.prev
i + =1
else:
i = 0
curr = self.head
while i < pos :
curr = curr.next
i += 1
return curr
[ 문1. 양방향 연결리스트 역방향 순회 ]
class Node:
def __init__(self, item):
self.data = item
self.prev = None
self.next = None
class DoublyLinkedList:
def __init__(self):
self.nodeCount = 0
self.head = Node(None)
self.tail = Node(None)
self.head.prev = None
self.head.next = self.tail
self.tail.prev = self.head
self.tail.next = None
def reverse(self):
result = []
# 끝에서 부터 순회 tail --> dummy node
curr = self.tail
# dummy node가 존재하므로 curr.prev.prev != None 인 경우까지 while문으로 순회한다.
while curr.prev.prev:
curr = curr.prev
result.append(curr.data)
return result
def getAt(self, pos):
if pos < 0 or pos > self.nodeCount:
return None
if pos > self.nodeCount // 2:
i = 0
curr = self.tail
while i < self.nodeCount - pos + 1:
curr = curr.prev
i += 1
else:
i = 0
curr = self.head
while i < pos:
curr = curr.next
i += 1
return curr
def insertAfter(self, prev, newNode):
next = prev.next
newNode.prev = prev
newNode.next = next
prev.next = newNode
next.prev = newNode
self.nodeCount += 1
return True
def insertAt(self, pos, newNode):
if pos < 1 or pos > self.nodeCount + 1:
return False
prev = self.getAt(pos - 1)
return self.insertAfter(prev, newNode)
def solution(x):
return 0
[ 문2. 양방향 연결리스트 노드 삽입 ]
class Node:
def __init__(self, item):
self.data = item
self.prev = None
self.next = None
class DoublyLinkedList:
def __init__(self):
self.nodeCount = 0
self.head = Node(None)
self.tail = Node(None)
self.head.prev = None
self.head.next = self.tail
self.tail.prev = self.head
self.tail.next = None
def traverse(self):
result = []
curr = self.head
while curr.next.next:
curr = curr.next
result.append(curr.data)
return result
# next 노드가 주어졌을 때 before 에 newNode 삽입
def insertBefore(self, next, newNode):
prev = next.prev
newNode.prev = prev
newNode.next = next
prev.next = newNode
next.prev = newNode
self.nodeCount += 1
return True
def solution(x):
return 0
[ 문3. 양방향 연결리스트 노드 삭제 ]
class Node:
def __init__(self, item):
self.data = item
self.prev = None
self.next = None
class DoublyLinkedList:
def __init__(self):
self.nodeCount = 0
self.head = Node(None)
self.tail = Node(None)
self.head.prev = None
self.head.next = self.tail
self.tail.prev = self.head
self.tail.next = None
def traverse(self):
result = []
curr = self.head
while curr.next.next:
curr = curr.next
result.append(curr.data)
return result
def getAt(self, pos):
if pos < 0 or pos > self.nodeCount:
return None
if pos > self.nodeCount // 2:
i = 0
curr = self.tail
while i < self.nodeCount - pos + 1:
curr = curr.prev
i += 1
else:
i = 0
curr = self.head
while i < pos:
curr = curr.next
i += 1
return curr
def insertAfter(self, prev, newNode):
next = prev.next
newNode.prev = prev
newNode.next = next
prev.next = newNode
next.prev = newNode
self.nodeCount += 1
return True
def insertAt(self, pos, newNode):
if pos < 1 or pos > self.nodeCount + 1:
return False
prev = self.getAt(pos - 1)
return self.insertAfter(prev, newNode)
def popAfter(self, prev):
curr = prev.next
next = prev.next.next
prev.next = next
next.prev = prev
self.nodeCount -= 1
return curr.data
def popBefore(self, next):
curr = next.prev
prev = next.prev.prev
prev.next = next
next.prev = prev
self.nodeCount -= 1
return curr.data
def popAt(self, pos):
# pos == 0: head, pos == self.nodeCount + 1 : tail
if pos < 1 or pos > self.nodeCount:
raise IndexError
else:
prev = self.getAt(pos-1)
return self.popAfter(prev)
def solution(x):
return 0
[ 문4. 양방향 연결리스트의 병합 ]
class Node:
def __init__(self, item):
self.data = item
self.prev = None
self.next = None
class DoublyLinkedList:
def __init__(self):
self.nodeCount = 0
self.head = Node(None)
self.tail = Node(None)
self.head.prev = None
self.head.next = self.tail
self.tail.prev = self.head
self.tail.next = None
def concat(self, L):
# l1, l2 가 각각 비어도 비어있지 않아도 head, tail 이 dummy 노드로 항상 존재하기 때문에
# L1, l2 가 None인 예외 상황을 고려하지 않아도 된다. 원소가 존재하는 것과 똑같이 처리가 가능하다.
l1_last_node = self.tail.prev
l2_first_node = L.head.next
l1_last_node.next = l2_first_node
l2_first_node.prev = l1_last_node
# 기존 tail 위치 변경
self.tail = L.tail
self.nodeCount += L.nodeCount
def traverse(self):
result = []
curr = self.head
while curr.next.next:
curr = curr.next
result.append(curr.data)
return result
def getAt(self, pos):
if pos < 0 or pos > self.nodeCount:
return None
if pos > self.nodeCount // 2:
i = 0
curr = self.tail
while i < self.nodeCount - pos + 1:
curr = curr.prev
i += 1
else:
i = 0
curr = self.head
while i < pos:
curr = curr.next
i += 1
return curr
def insertAfter(self, prev, newNode):
next = prev.next
newNode.prev = prev
newNode.next = next
prev.next = newNode
next.prev = newNode
self.nodeCount += 1
return True
def insertAt(self, pos, newNode):
if pos < 1 or pos > self.nodeCount + 1:
return False
prev = self.getAt(pos - 1)
return self.insertAfter(prev, newNode)
def solution(x):
return 0
'Algorithm > 알고리즘' 카테고리의 다른 글
[프로그래머스 강의] 12강 스택(Stack) (2) (0) | 2022.05.08 |
---|---|
[프로그래머스 강의] 11강 스택(Stack) (1) (0) | 2022.05.04 |
[프로그래머스 강의] 9강 연결리스트(Linked List) (3) (0) | 2022.04.30 |
[프로그래머스 강의] 8강 연결리스트(Linked List) (2) (0) | 2022.04.28 |
[프로그래머스 강의] 7강 연결리스트(Linked List) (1) (0) | 2022.04.28 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 프로그래머스
- 스터디
- 연결리스트활용
- 리스트2
- 리스트함축
- 네트워크
- 정렬
- 프로그래머스강의
- 이진탐색
- 완전탐색
- 보험
- 자료구조
- https
- Greedy sort
- CS
- 알고리즘
- 리스트 복사
- 자바
- 데이터베이스
- 이차 리스트
- CS 스터디
- SW
- It
- CS.
- 프로세스 주소공간
- 파이썬
- 운영체제
- 리스트
- 자료구조와알고리즘 23강
- 코드업 기초
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
글 보관함