1. 程式人生 > >演算法:棧與佇列的經典案例,模擬迷宮演算法

演算法:棧與佇列的經典案例,模擬迷宮演算法

在這裡插入圖片描述

模擬迷宮

# 1代表牆壁0代表通道
maze = [
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
    [1, 0, 0, 1, 0, 0, 0, 1, 0, 1],
    [1, 0, 0, 1, 0, 0, 0, 1, 0, 1],
    [1, 0, 0, 0, 0, 1, 1, 0, 0, 1],
    [1, 0, 1, 1, 1, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 1, 0, 0, 0, 0, 1],
    [1, 0, 1, 0, 0, 0, 1, 0, 0, 1],
    [1, 0, 1, 1, 1, 0, 1, 1, 0, 1],
    [1, 1, 0, 0,
0, 0, 0, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] ]

棧思路 == 深度優先搜尋

# 封裝四個方向列表
dirs = [
    lambda x, y: (x + 1, y),
    lambda x, y: (x - 1, y),
    lambda x, y: (x, y - 1),
    lambda x, y: (x, y + 1)
]


# 用棧的思路
def maze_path(x1, y1, x2, y2):
    """x1起點 x2終點"""
    stack = [(x1, y1)]
    # 棧不空就迴圈(棧空代表沒有路了)
while len(stack) > 0: curNode = stack[-1] # 當前節點位置 if curNode[0] == x2 and curNode[1] == y2: print('找到迷宮出路') for p in stack: print(p) break # 下一個點 上(x-1,y)、下(x+1,y)、左(x,y-1)、右(x,y+1) for di in dirs: nextNode =
di(curNode[0], curNode[1]) # 如果下一個節點能走 if maze[nextNode[0]][nextNode[1]] == 0: # 能走就加到棧裡 stack.append(nextNode) maze[nextNode[0]][nextNode[1]] = 2 # 隨便標記一個數代表之前走過 break else: # 如果一個都找不到就回退 maze[curNode[0]][curNode[1]] = 2 # 這個位置也要標記為走過了 stack.pop() # 出棧 else: print('該迷宮沒有出路') return False # 測試效果 maze_path(1, 1, 8, 8)

佇列思路 == 深度優先搜尋

from collections import deque


# 封裝四個方向列表
dirs = [
    lambda x, y: (x + 1, y),
    lambda x, y: (x - 1, y),
    lambda x, y: (x, y - 1),
    lambda x, y: (x, y + 1)
]


def print_r(path):
    real_path = []  # 真實路徑
    i = len(path) - 1
    while i >= 0:
        real_path.append(path[i][0:2])
        i = path[i][2]
    real_path.reverse()
    for node in real_path:
        print(node)


# 廣度優先: 同時考慮多條路
def maze_path_queue(x1, y1, x2, y2):
    queue = deque()
    path = []  # 初始的時候起點座標放進去,額外的列表儲存
    queue.append((x1, y1, -1))  # -1為記錄而已
    # 佇列空代表沒有路
    while len(queue) > 0:
        cur_Node = queue.popleft()  # 從左邊出去
        path.append(cur_Node)  # 加入
        if cur_Node[0] == x2 and cur_Node[1] == y2:
            print('找到迷宮出路')
            print_r(path)
            return True

        for di in dirs:
            # 下一個節點
            next_node = di(cur_Node[0], cur_Node[1])
            # 如果可以走就進隊
            if maze[next_node[0]][next_node[1]] == 0:
                # len(path)-1) 表示 cur_Node在當前的下標
                queue.append((next_node[0], next_node[1], len(path) - 1))
                maze[next_node[0]][next_node[1]] = 2  # 標記已走過
    return False


# 測試效果
maze_path_queue(1, 1, 8, 8)