1. 사전 지식

"C로 배우는 알고리즘"[각주:1]에 설명된 Linked List에 대한 주요 내용은 다음과 같습니다.

1. Linked List는 Node와 Link로 구성됨

2. Linked List는 Link의 개수와 연결 상태에 따라 "단순 연결 리스트", "환형 연결 리스트", "이중 연결 리스트", "이중 환형 연결 리스트"등이 있음


2. Simple Linked List

  • Simple Linked List는 "정보를 저장하는 Node"와 "바로 다음 Node를 가리키는 Link" 하나로 구성됩니다.
  • Linked List의 최대 장점은 재배열(rearrangement)이 쉽다는 것입니다.
  • 관리를 위해서 Head Node와 Tail Node를 가집니다.
Python 배열은 그 자체로 append()나 remove()등을 제공합니다만, Python으로 Linked List를 구현한 웹문서들[각주:2],[각주:3],[각주:4],[각주:5]을 찾을 수 있었습니다. 이들 코드를 모두 참조하여 C로 배우는 알고리즘"에 있는 내용을 구현하였습니다.

Integer type의 key를 처리하는 class 구현을 목표로 하며, 구태여 Node 자체가 class 외부로 return되지는 않도록 설계합니다. 따라서 "C로 배우는 알고리즘"에 있는 insert_after(), delete_next(), find_node(), insert_node(), delete_all()는 구현하지 않고, delete_node(), ordered_insert(), print_list() 일부만 구현하는 것으로 합니다.

2. 동작 코드

Node는 class로 구현합니다. Node 생성시 Key 값이 입력되지 않으면 '-1'을 사용하도록 하였습니다. Key는 예제 목적상 integer를 입력 받는 것을 가정합니다.
class Node:
def __init__(self, key=-1):
self.key = key
self.next = None

Global로 head와 tail을 선언해서 작성해도 되겠지만, class 내에서 처리할 수 있도록 LinkedList라는 class를 작성했습니다. "C로 배우는 알고리즘"에 있듯이 head는 tail을, tail을 tail을 next로 지정하였습니다.

key 입력에 따라 정렬한 상태로 입력할 수 있도록 ordered_insert() 함수와 해당 key 값의 node를 지우고, 모든 node들을 print하는 함수를 작성하였습니다.

class LinkedList:
def __init__(self):
self.head = Node()
self.tail = Node()
self.head.next = self.tail
self.tail.next = self.tail

def ordered_insert(self, key):
newNode = Node(key)
p = self.head
s = p.next
while s.key <= key and s != self.tail:
p = p.next
s = p.next
p.next = newNode
newNode.next = s

def delete_node(self, key):
p = self.head
s = p.next
while s.key != key and s != self.tail:
p = p.next
s = p.next
if s != self.tail:
p.next = s.next
return True
else:
return False

def print_node(self):
p = self.head
p = p.next
print("Start", end=" ")
while p != self.tail:
print(p.key, "->", end=" ")
p = p.next
print("End")

3. 실행 코드

Simple Linked List 함수들의 실행 코드는 아래와 같습니다. ("C로 배우는 알고리즘" 리스트 3-4 : LINKED1.C에 대응)

ordered_insert() 함수로 임의의 integer type의 key값을 갖는 node들을 생성한 후 print합니다. 그리고 하나의 node를 그리고 다시 print합니다.


#main() function
if __name__ == "__main__":
list = LinkedList()
list.ordered_insert(7)
list.ordered_insert(8)
list.ordered_insert(1)
list.ordered_insert(9)
list.print_node()

list.delete_node(7)
list.print_node()


5. 코드



  1. http://www.yes24.com/24/goods/18003 [본문으로]
  2. https://wayhome25.github.io/cs/2017/04/17/cs-19/ [본문으로]
  3. http://onestep.tistory.com/33 [본문으로]
  4. http://sjce.tistory.com/8 [본문으로]
  5. http://doorbw.tistory.com/117 [본문으로]
반응형

1. 알고리즘

경로를 모두 저장한 다음, 동일한 좌표가 나오는 경우를 확인합니다. 만약 동일한 좌표가 확인되면, 일종의 jump를 한다고 생각하고, 그 사이에 있는 좌표를 모두 삭제합니다. 이후에 "최단 경로"로 동작을 합니다.


2. 동작 코드

경로를 저장하는 코드는 매우 간단하게 작성합니다.

def record(x, y):
rec.append(x)
rec.append(y)

동일한 좌표를 찾았을 때 삭제하는 코드는 다음과 같습니다.

def del_path(i, j):
k = i
while(rec[j] >=0 ):
rec[i] = rec[j]
i += 1
j += 1
rec[i] = -1

return k

최단 거리를 찾고, 다시 한번 애니메이션을 보여주는 코드는 다음과 같습니다.

def shortest_path():
i = 0

while rec[i] >= 0:
x = rec[i]
y = rec[i+1]
j = i + 2
while rec[j] >= 0:
x1 = rec[j]
y1 = rec[j + 1]
if x==x1 and y==y1:
j = del_path(i, j)
j += 2
i += 2

# Display shortest path
i = 0
while rec[i] >= 0:
x = rec[i]
y = rec[i+1]
i += 2
if TERMINAL:
stdscr.addstr(x + 1, 2*(y + 1), "*")
stdscr.refresh()
time.sleep(0.1)
stdscr.addstr(x + 1, 2*(y + 1), " ")
stdscr.refresh()

3. 실행 코드

최종적으로 미로를 그리고, right hand on wall 기법으로 출구를 찾고, 마지막으로 "최단거리"로 찾아가는 코드를 작성했습니다. ("C로 배우는 알고리즘" 리스트 3-3 : ROBOT.C) 아래 링크를 참고해 주십시오.


https://github.com/steady08/python_beginner_algorithm/blob/master/Chapter_03/Ch_03_1_2.py


이상으로 "미로에 갖힌 생쥐"편을 마칩니다.

반응형

1. 알고리즘

"C로 배우는 알고리즘"[각주:1]에 설명된 right hand on wall 알고리즘은 다음과 같습니다.


1. 앞으로 간다.

2.아직 미로 안에 갖혀 있다면

2.1. 오른쪽으로 방향을 90도 튼다.

2.2. 만약 벽이 앞에 있다면

2.2.1 왼쪽으로 방향을 90도 튼다.

2.3 앞으로 간다.

2.4 2로 돌아감

3. 미로 탈출 성공!


2. 동작 코드

앞으로 가는 함수은 forward() 함수는 다음과 같습니다.

def forward(x, y, dir):
# Delete mouse
if TERMINAL:
stdscr.addstr(x + 1, 2*(y + 1), " ")
stdscr.refresh()

if dir == LEFT:
y -= 1
if dir == RIGHT:
y += 1
if dir == UP:
x -= 1
if dir == DOWN:
x += 1

# Record movement of mouse
record(x, y)

# Draw mouse
if TERMINAL:
stdscr.addstr(x + 1, 2*(y + 1), ROBOT)
stdscr.refresh()

return x, y

책과는 달리 x와 y를 바꿔서 진행했습니다. TERMINAL 변수는 윈도우의 cmd창에서 진행할때는 '1'로, PyCharm에서 컴파일이나 기타 Debugging을 할때 '0'으로 설정했습니다.


Right hand on wall을 실제로 구현한 right_hand() 함수는 다음과 같습니다.

def right_hand(m, x, y, dir):
if TERMINAL:
stdscr.addstr(x + 1, 2*(y + 1), ROBOT)
stdscr.refresh()
time.sleep(0.1)

# Record movement of mouse
record(x, y)

x, y = forward(x, y, dir)
while still_in_maze(x, y):
# 100 ms sleep
time.sleep(0.1)
dir = right(dir)
while wall_ahead(m, x, y, dir):
dir = left(dir)
x, y = forward(x, y, dir)

# End of record
record(-1, -1)

최초 start point에 마우스를 그리고, 미로에 있는 동안 forward() 함수를 계속 호출합니다. 만약 벽을 만났다면(wall_ahead() 함수) 방향을 전환(left() 함수)합니다.

여기서 mouse를 그리거나 지울때 y 좌표를 그대로 사용하지 않고, 2를 곱해서 미로의 line이 지워지는 것을 최소화했습니다.

실행되는 코드를 사람이 확인할 수 있도록 time.sleep()을 사용했습니다. 여기서 sleep()의 인자로는 "초단위" 이외에 floating으로 msec 단위도 설정할 수 있습니다.[각주:2]


3. 실행 코드

미로를 그리고 마우스가 right hand on wall 기법으로 미로를 빠져나가는 것을 볼 수 있는 코드는 아래 링크를 참고해 주십시오. ("C로 배우는 알고리즘" 리스트 3-3 : ROBOT.C의 일부) 아직 "최단 경초 찾기" 코드는 추가하지 않았습니다.


https://github.com/steady08/python_beginner_algorithm/blob/master/Chapter_03/Ch_03_1_1.py


다음편에서 "최단 경로 찾기"까지를 포함해서 완성해 보겠습니다.




  1. http://www.yes24.com/24/goods/18003 [본문으로]
  2. http://hashcode.co.kr/questions/1008/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8%EC%9D%84-50-ms-sleep%ED%95%98%EB%A0%A4%EB%A9%B4-%EC%96%B4%EB%96%BB%EA%B2%8C-%ED%95%B4%EC%95%BC%EB%90%A0%EA%B9%8C%EC%9A%94 [본문으로]
반응형

+ Recent posts