노드가 한 방향으로 연결되어 있는 형태
head, tail, nodeCount로 구성
head : 제일 앞 노드
tail : 제일 뒷 노드
nodeCount : 노드 개수
장점 : 데이터를 자유롭게 삽입하고 삭제 가능 → Dummy Node(빈 노드) 사용
class LinkedList:
def __init__(self):
self.nodeCount = 0
self.head = Node(None) # dummy node
self.tail = None
self.head.next = self.tail
배열 | 연결리스트 | |
---|---|---|
저장공간 | 연속한 위치 | 임의의 위치 |
특정 원소 지칭 | 매우 간편 | 선형탐색과 유사 |
시간 복잡도 | O(1) | O(n) |
def getAt(self, pos):
if pos < 0 or pos > self.nodeCount:
return None
i = 0 # 시작 노드 = dummy node
curr = self.head
while i < pos:
curr = curr.next
i += 1
return curr
def traverse(self):
result = []
curr = self.head
while curr.next:
curr = curr.next
result.append(curr.data)
return result
def concat(self, L):
self.tail.next = L.head.next
if L.tail:
self.tail = L.tail
self.nodeCount += L.nodeCount
def insertAfter(self, prev, newNode):
newNode.next = prev.next
if prev.next is None:
self.tail = newNode
prev.next = newNode
self.nodeCount += 1
return True
def insertAt(self, pos, newNode):
if pos < 1 or pos > self.nodeCount + 1:
return False
if pos != 1 and pos == self.nodeCount + 1:
prev = self.tail
else:
prev = self.getAt(pos - 1)
return self.insertAfter(prev, newNode)
def getLength(self):
return self.nodeCount
노드가 양방향으로 연결되어 있는 형태
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 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 concat(self, L):
self.tail = self.tail.prev
L.head = L.head.next
self.tail.next = L.head
L.head.prev = self.tail
self.tail = L.tail
self.nodeCount += L.nodeCount
추가된 데이터 원소들을 끄집어내면 마지막에 넣었던 것부터 넣은 순서의 역순으로 꺼내지는 자료구조
class ArrayStack:
def __init__(self):
self.data = []
def size(self):
return len(self.data)
def isEmpty(self):
return self.size() == 0
def push(self, item):
self.data.append(item)
def pop(self):
return self.data.pop()
def peek(self):
return self.data[-1]
from doublylinkedlist import Node
from doublylinkedlist import DoublyLinkedList
class LinkedListStack:
def __init__(self):
self.data = DoublyLinkedList()
def size(self):
return self.data.getLength()
def isEmpty(self):
return self.size() == 0
def push(self, item):
node = Node(item)
self.data.insertAt(self.size() + 1, node)
def pop(self):
return self.data.popAt(self.size())
def peek(self):
return self.data.getAt(self.size()).data
연산자가 피연산자들의 뒤에 위치
(A + B) * (C + D) → A B + C D + *
A + B * C → A B C * +
prec = {
'*' : 3, '/' : 3,
'+' : 2, '-' : 2,
'(' : 1
}
class ArrayStack:
def __init__(self):
self.data = []
def size(self):
return len(self.data)
def isEmpty(self):
return self.size() == 0
def push(self, item):
self.data.append(item)
def pop(self):
return self.data.pop()
def peek(self):
return self.data[-1]
prec = {
'*': 3, '/': 3,
'+': 2, '-': 2,
'(': 1
}
def solution(S):
opstack = ArrayStack()
ans = ""
for s in S:
if s == "(":
opstack.push(s)
elif s in prec:
while not opstack.isEmpty() and prec[s] <= prec[opstack.peek()]:
ans += opstack.pop()
opstack.push(s)
elif s == ")":
while opstack.peek() != "(":
ans += opstack.pop()
opstack.pop()
else:
ans += s
while not opstack.isEmpty():
ans += opstack.pop()
return ans
class ArrayStack:
def __init__(self):
self.data = []
def size(self):
return len(self.data)
def isEmpty(self):
return self.size() == 0
def push(self, item):
self.data.append(item)
def pop(self):
return self.data.pop()
def peek(self):
return self.data[-1]
def splitTokens(exprStr):
tokens = []
val = 0
valProcessing = False
for c in exprStr:
if c == ' ':
continue
if c in '0123456789':
val = val * 10 + int(c)
valProcessing = True
else:
if valProcessing:
tokens.append(val)
val = 0
valProcessing = False
tokens.append(c)
if valProcessing:
tokens.append(val)
return tokens
def infixToPostfix(tokenList):
prec = {
'*': 3,
'/': 3,
'+': 2,
'-': 2,
'(': 1,
}
opStack = ArrayStack()
postfixList = []
for s in tokenList:
if s == "(":
opStack.push(s)
elif s in prec:
while not opStack.isEmpty() and prec[s] <= prec[opStack.peek()]:
postfixList.append(opStack.pop())
opStack.push(s)
elif s == ")":
while opStack.peek() != "(":
postfixList.append(opStack.pop())
opStack.pop()
else:
postfixList.append(s)
while not opStack.isEmpty():
postfixList.append(opStack.pop())
return postfixList
def postfixEval(tokenList):
valStack = ArrayStack()
for t in tokenList:
if type(t) is int:
valStack.push(t)
else:
if t == "*":
a = valStack.pop()
b = valStack.pop()
valStack.push(b * a)
elif t == "/":
a = valStack.pop()
b = valStack.pop()
valStack.push(b / a)
elif t == "+":
a = valStack.pop()
b = valStack.pop()
valStack.push(b + a)
elif t == "-":
a = valStack.pop()
b = valStack.pop()
valStack.push(b - a)
return valStack.pop()
def solution(expr):
tokens = splitTokens(expr)
postfix = infixToPostfix(tokens) # 중위→후위
val = postfixEval(postfix)
return val