Advertisement
C3EQUALZ

Алгоритм поиска кратчайшего пути

Nov 24th, 2022 (edited)
858
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.82 KB | None | 0 0
  1. ###Поиск в глубину. Используется для нахождения всех путей в графе от заданной точки. В качестве графа должен быть задан словарь. В ином случае функция не будет работать. start - это начальная точка графа, а end - конец, data - наш путь, visited - точки, которые уже посетили. В начале добавлю в data нашу стартовую точку, так как с неё начинаем движение. Рассматриваем соседи нашей точки, исключая уже посещенные. Если нашли подходящего соседа, то добавляем в data и visited, заходим рекурсивно, посещая каждого соседа данной точки. Работает с помощью метода исключения, где мы оставляем только один способ поиска пути.
  2. def dfs(start, end, graph, data, visited):
  3.     if len(data) == 0:
  4.         data.append(start)
  5.         visited.add(start)
  6.  
  7.     if start == end:
  8.         return print(f'Путь - {data}, а количество ребер {len(data) - 1}')
  9.  
  10.     for next in set(graph[start]) - visited:
  11.         data.append(next)
  12.         visited.add(next)
  13.         dfs(next, end, graph, data, visited)
  14.         data.pop()
  15.         visited.remove(next)
  16.  
  17. ###Алгоритм Дейкстры. В качестве графа принимаем словарь, где value тоже словарь, содержащий точки, в которые можем попасть, и вес. Каждое практически действие сопровождается комментарием.
  18. ----------------------------------------------------------------
  19. Если хотите не вручную создавать словарь словарей, то вот код.
  20. from itertools import combinations
  21.  
  22. def matr():
  23.     m = int(input('Введите количество вершин '))
  24.     matr = {}
  25.     for i, j in combinations([x for x in range(m+1)], 2):
  26.         a = input(f'Введите расстояние между вершиной {chr(ord("A") + i)} и {chr(ord("A") + j)} (если связи нет введите {0}): ')
  27.         if a != '0':
  28.             try:
  29.                 matr[chr(ord("A") + i)].update({f'{chr(ord("A") + j)}': int(a)})
  30.             except KeyError:
  31.                 matr[chr(ord("A") + i)] = {f'{chr(ord("A") + j)}': int(a)}
  32.             try:
  33.                 matr[chr(ord("A") + j)].update({f'{chr(ord("A") + i)}': int(a)})
  34.             except KeyError:
  35.                 matr[chr(ord("A") + j)] = {f'{chr(ord("A") + i)}': int(a)}
  36.     return matr
  37. -----------------------------------------------------------------------
  38. graph = {
  39.     'a': {'b': 5, 'c': 2},
  40.     'b': {'a': 5, 'c': 7, 'd': 8},
  41.     'c': {'a': 2, 'b': 7, 'd': 4, 'e': 8},
  42.     'd': {'b': 8, 'c': 4, 'e': 6, 'f': 4},
  43.     'e': {'c': 8, 'd': 6, 'f': 3},
  44.     'f': {'e': 3, 'd': 4},
  45.     }
  46. start = input('Введите начальную точку ')
  47. end = input('Введите конечную точку ')
  48.  
  49. def dejksra(start, end, graph):
  50.     ### Задаем начальные переменные
  51.     shortest_distances = {i: float('inf') for i in graph} ##самые короткие расстояния до каждой точки
  52.     shortest_distances[start] = 0 #нет расстояния между стартом и стартом
  53.     path = {} #самые короткий путь для каждой точки, здесь именно буква
  54.     travel = [] #наша траектория движения.
  55.     ###
  56.     while len(graph) > 0:
  57.         min_node = None #каждый раз буду заходить в новую точку, поэтому обнуляю
  58.         for current_node in graph: #прохожусь по ключам графу
  59.             if min_node == None:
  60.                 min_node = current_node #в первый раз у нас будет None, а дальше будет наша текущая точка
  61.             elif shortest_distances[min_node] > shortest_distances[current_node]: #сравниваем с каждым элементом по ключу
  62.                 min_node = current_node
  63.         for node, value in graph[min_node].items(): #раскрываем словарь внутри словаря {(b,5),(c,2)]
  64.             if value + shortest_distances[min_node] < shortest_distances[node]: #расстояние от старта до данной точки сравниваем
  65.                 shortest_distances[node] = value + shortest_distances[min_node] #запоминаем самый короткий путь от начала до данной точки
  66.                 path[node] = min_node #запоминаем в словарь самую минимальную точку
  67.         graph.pop(min_node) #удаляем минимальную точку, чтобы в неё не вернуться
  68.     ###Восстановление пути из словаря. Каждый раз так возвращаем.
  69.     while end != start:
  70.         try:
  71.             travel.insert(0, end)  
  72.             end = path[end]
  73.         except:
  74.             print('Невозможно восстановить путь.')
  75.             break
  76.     travel.insert(0, start)
  77.     if shortest_distances[min_node] != float('inf'):
  78.         return print(f'Минимальный путь - {travel}, а самая минимальная сумма - {shortest_distances[min_node]}')
  79.  
  80.  
  81. dejksra(start, end, graph)
  82.  
  83. ###Поиск в ширину. Для удобства можно использовать deque. Создаем словарь, где для каждой точки будет запоминаться путь от старта. Расстояние старта принимаем за 0 (расстояние от 1 до 1 == 0). Текущее число удаляем для поиска соседей с помощью словаря графа. Если мы его не проходили, то от прошлого добавляем 1. Добавляем в очередь для повторной итерации. Делается все, пока не пройдем полностью граф.
  84.  
  85. from collections import deque
  86.  
  87. def bfs(graph, root):
  88.     distances = {}
  89.     distances[root] = 0
  90.     q = deque([root])
  91.     while q:
  92.         current = q.popleft()
  93.         for neighbor in graph[current]:
  94.             if neighbor not in distances:
  95.                 distances[neighbor] = distances[current] + 1
  96.                 q.append(neighbor)
  97.     return distances
  98.  
  99. graph = {1:[2,3], 2:[1,3], 3:[1,2,4], 4:[1]}
  100. root = 1
  101. print(bfs(graph, root))
  102.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement