Python Algorithm Study - Week 3, 4
2017-08-03
Problem Solving with Algorithms and Data Structures using Python ์ฑ ์ ์ฝ์ผ๋ฉฐ ์คํฐ๋ํ ๋ด์ฉ์ ์ ๋ฆฌํ์ฌ ์ฐ์ฌํฉ๋๋ค.
pop()
์ด๋ append()
๋ O(1)
์ด๋ค. ์๋ฆฌ์ ์๊ด ์์ด ๋งจ ๋ง์ง๋ง์ ๋ค์ด๊ฐ๊ธฐ ๋๋ฌธ.pop(0)
, insert(0, x)
๋ O(n)
์ด๋ค. ์์์๋ถํฐ ์๋ฆฌ์๊ฐ ๋ค ๋ฐ๋๊ธฐ ๋๋ฌธ.Linked list ๋? (Wikipedia)
Linear ํ ๋ฐ์ดํฐ์ ๋ชจ์. ์ธ๋ฑ์ค(?)๊ฐ ๋ถ์ฌ๋์ด ์์ง ์์ (๊ทธ๋งํผ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์๋จน์)
ํ์ด์ฌ์ ๋ฆฌ์คํธ๋ ์ธ๋ฑ์ค๊ฐ ๋ถ์ฌ๋์ด ์๋ค! ๊ทธ๋์ ์ค๊ฐ์ insert ํ๋๊ฑด
O(n)
Linked list ๋ฅผ ๊ตฌํํ๋ ์ด์
Linked list ์ ๋จ์
# Pythonic way to define getter/setter/deleter - @property๋ฅผ ์ฐ์ธ์!
class Node:
def __init__(self, initdata):
self.data = initdata
self.next = None
# Note in the constructor that a node is initially created with next set to None. Since this is sometimes referred to as โgrounding the node,โ we will use the standard ground symbol to denote a reference that is referring to None. It is always a good idea to explicitly assign None to your initial next reference values.
def getData(self):
return self.data
def getNext(self):
return self.next
def setData(self,newdata):
self.data = newdata
def setNext(self,newnext):
self.next = newnext
class PythonicNode:
def __init__(self, initdata):
self.data = initdata
self.next = None
@property
def x(self):
return self.data
@x.setter
def x(self, newdata):
self.data = newdata
@x.deleter
def x(self):
del self.data
temp = PythonicNode(93)
# getter
temp.x # 93
# setter
temp.x = 1234
temp.x # 1234
# deleter
del temp.x
class UnorderedList:
def __init__(self):
self.head = None
# ์ด ํด๋์ค๋ ์ฒซ ๋
ธ๋์ ๋ํ ๋ ํผ๋ฐ์ค๋ฅผ ๋ฐ๋์ ๊ฐ์ ธ์ผ ํ๋ค. (... class must maintain a reference to the first node.)
# ๊ทธ๋ฐ๋ฐ ์ด ์์ฑ์์ head๊ฐ none ์ธ ์ด์ ๋ ๋ง ์์ฑ๋ ๋ฆฌ์คํธ๋ ์๋ฌด ๋
ธ๋๋ ์๊ธฐ ๋๋ฌธ!
def isEmpty(self):
return self.head == None
# ์ด ๋ฆฌ์คํธ๊ฐ ์๋์ง ์๋์ง ๋ณด๋ ค๋ฉด head๊ฐ ์๋์ง ์๋์ง๋ง ๋ณด๋ฉด ๋จ. ๊ทธ๋์ boolean์์ผ๋ก ์์๋ด
def add(self, item):
temp = Node(item) # temp๋ ๋
ธ๋ ํด๋์ค์ ์ธ์คํด์ค์ฌ์ผ ํ๊ณ ,
temp.setNext(self.head) # ์๋ก์ด temp๊ฐ ๋ค์ด์ค๋ฉด, ์๋ ์๋ head(None)๋ temp์ next๊ฐ ๋๊ณ ,
self.head = temp # temp๋ ์๋ก์ด head๊ฐ ๋๋ค! - modify the head of the list to refer to the new node
# 3,4๋ฒ์งธ ๋ผ์ธ์ ์์๊ฐ ์ค์ํ๋ค!
# x.next == None ์ด๋ฉด, x ๋ ์ด ๋ฆฌ์คํธ์ ์ฒซ ๋ฐ์ดํฐ
def size(self):
current = self.head
count = 0
while current != None: # head ๊ฐ None์ด ๋์ฌ๋๊น์ง, ๋๊น์ง ๋๋ค.
count = count + 1 # while loop๊ฐ ๋๋ ํ์๋ฅผ ์ผ๋ค.
current = current.getNext()
return count
def search(self, item):
current = self.head
found = False
while current != None and not found:
if current.getData() == item:
found = True
else:
current = current.getNext()
return found
# head๋ถํฐ ์ฐจ๊ทผ์ฐจ๊ทผ ์ฐพ์๋๊ฐ๋ค. ์ผ์นํ์ง ์์ผ๋ฉด found๊ฐ False๋ฅผ, ์ผ์นํ๋ฉด True๋ฅผ ๋ฑ์ด๋.
def print_all(self):
current = self.head
while current != None:
print(current.getData())
current = current.getNext()
def remove(self, item): # ์ ๊ฑฐํ๊ณ ์ถ์ ๋
ธ๋์ ์,๋ค ๋งํฌ๋ฅผ ๋์ด์ฃผ๋ฉด ๋๋ค.
current = self.head
previous = None
found = False
while not found:
if current.getData() == item:
found = True
else:
previous = current
current = current.getNext()
if previous == None:
self.head = current.getNext()
else:
previous.setNext(current.getNext())
# ์์๋ ๋ฐ๊ฟจ๋๋ฐ, node ์ธ์คํด์ค๋ ๊ทธ๋๋ก ๋จ์์์์? (size๋ ๊ทธ๋๋ก ์๋๊ฐ?)
# ํจ๊ป ํ์ด๋ด
์๋ค!!
def append(self, item): # item์ด last๊ฐ ๋๋ ค๋ฉด? ์ฒ์ ๋ค์ด์จ ์์ดํ
๊น์ง ๊ฐ์ ๊ทธ next์ item์ ๋ถ์ธ๋ค.
temp = Node(item)
current = self.head
while current.getNext() != None:
current = current.getNext()
current.setNext(temp)
mylist = UnorderedList()
print(mylist.head)
# None
mylist.add(31)
mylist.add(77)
mylist.add(17)
mylist.add(93)
mylist.add(26)
mylist.add(54)
print(mylist.head)
# <__main__.Node object at 0x1045acf28>
mylist.size()
# 6
mylist.print_all()
# 54
# 26
# 93
# 17
# 77
# 31
mylist.search(17)
# True
mylist.remove(17)
mylist.print_all()
# 54
# 26
# 93
# 77
# 31
mylist.append(14923)
mylist.print_all()
# 54
# 26
# 93
# 77
# 31
# 14923
OrderedList()
- add(item)
- remove(item)
- search(item)
- isEmpty()
- size()
- append(item)
- index(item)
- insert(pos,item)
- pop()
- pop(pos)
(append, insert ๊ฐ ์๋จ)
class OrderedList:
def __init__(self):
self.head = None
def search(self, item): # ํฌ๊ธฐ์ ์์๊ฐ ์๊ธฐ ๋๋ฌธ์ ๋๊น์ง ๋์ง ์์๋ ๋๋ค.
current = self.head
found = False
stop = False
while current != None and not found and not stop:
if current.getData() == item:
found = True
else:
if current.getData() > item: # ์ฐพ๋ ๋ฐ์ดํฐ๋ณด๋ค ํฐ๊ณณ๊น์ง ์๋๋ฐ๋ ์๋ค๋ฉด, ์ฌ๊ธด ์๋ค๋ ๋ป. iteration์ stop ํด๋ ๋๋ค.
stop = True
else:
current = current.getNext()
return found
def add(self,item): # unordered๋ ๋ค๋ฅด๊ฒ, ์๋ฌด๋ฐ๋ ๋ค์ด๊ฐ์ ์๋๊ณ , ํฌ๊ธฐ์ ๋ง๊ฒ ๋ค์ด๊ฐ์ผํ๋ค.
current = self.head
previous = None
stop = False
while current != None and not stop:
if current.getData() > item:
stop = True
else:
previous = current
current = current.getNext()
temp = Node(item) # ์ธ์คํด์ค ์์ฑํด์ฃผ๊ณ ,
if previous == None:
temp.setNext(self.head)
self.head = temp
else:
temp.setNext(current) # item ๋ณด๋ค ํฐ current ๋ item ๋ค์ ๋ฃ์ด์ฃผ๊ณ
previous.setNext(temp) # item๋ณด๋ค ์์ previous์ next ์ item์ ๋ฃ์ด์ค๋ค.
def print_all(self):
current = self.head
while current != None:
print(current.getData())
current = current.getNext()
mylist = OrderedList()
mylist.add(31)
mylist.add(77)
mylist.add(17)
mylist.add(93)
mylist.add(26)
mylist.add(54)
mylist.print_all()
# 17
# 26
# 31
# 54
# 77
# 93