Ejemplo n.º 1
0
def wave1(graph, start):
    """ Хвильовий алгоритм, що використовує масив
        відстаней від стартової точки до поточної
        для визначення чи була вже відвідана вершина

    :param graph: Граф
    :param start: Вершина з якої починається обхід
    :return: Список відстаней від стартової верниши до кожної вернини графа
    """
    q = Queue()

    q.enqueue(start)

    # Введемо масив, що буде містити
    # відстані від стартової вершини start.
    # Ініціалізуємо масив значеннями -1 (тобто нескінченність)
    distances = [-1] * len(graph)
    distances[start] = 0  # Відстань від стартової точки до себе нуль.

    while not q.empty():

        current = q.dequeue()  # Беремо перший елемент з черги

        # Додаємо в чергу всіх сусідів поточного елементу
        for neighbour in graph[current].neighbors():
            if distances[neighbour] == -1:  # які ще не були відвідані
                q.enqueue(neighbour)
                distances[neighbour] = distances[current] + 1

    return distances
Ejemplo n.º 2
0
def wave2(graph: GraphForAlgorithms, start: int):
    """ Функція, що запускає хвильовий алгоритм.
        Використовує граф класу GraphForAlgorithms, вершини якого містять допоміжну інформацію.
        Функція модифікує вхідний граф, так, що в результаті його всі вершини
        містять інформацію про найкоротшу відстань від заданої стартової вершини.

    :param graph: Граф, вершини якого містять відстань від початкової вершини
    :param start: Стартова вершина, тобто з якої починається робота хвильового алгоритму
    :return: None
    """

    # Ініціалізуємо додаткову інформацію у графі для роботи алгоритму.
    for vertex in graph:
        vertex.set_unvisited()  # вершина ще не була відвідана

    # Відстань у старотовій вершині (тобто від стартової вершини до себе) визначається як 0
    graph[start].set_distance(0)

    q = Queue()  # Створюємо чергу
    q.enqueue(start)  # Додаємо у чергу початкову вершину

    while not q.empty():
        vertex_key = q.dequeue()  # Беремо перший елемент з черги
        vertex = graph[vertex_key]  # Беремо вершину за індексом

        # Для всіх сусідів (за ключами) поточної вершини
        for neighbor_key in vertex.neighbors():
            neighbour = graph[neighbor_key]  # Беремо вершину-сусіда за ключем
            if not neighbour.visited():  # Якщо сусід не був відвіданий
                q.enqueue(neighbor_key)  # додаємо його до черги
                neighbour.set_distance(
                    vertex.distance() +
                    1)  # Встановлюємо значення відстані у вершині-сусіді
Ejemplo n.º 3
0
def BFS(graph, start):
    """ Обхід графа в ширину починаючи з заданої вершини

    :param graph: Граф
    :param start: Вершина з якої відбувається запуск обходу в ширину
    :return: Список, i-й елемент якого містить позначку чи була відвідана i-та вершина
    """

    # Введемо масив, що буде містити ознаку чи відвідали вже вершину.
    # Ініціалізуємо масив значеннями False (тобто не відвідали)
    visited = [False] * len(graph)

    q = Queue()  # Створюємо чергу
    q.enqueue(start)  # Додаємо у чергу стартову вершину
    visited[start] = True  # та позначаємо її як відвідану

    while not q.empty():  # Поки черга не порожня
        current = q.dequeue()  # Беремо перший елемент з черги

        print(current)  # Опрацьовуємо взятий елемент

        # Додаємо в чергу всіх сусідів поточного елементу
        for neighbour in graph[current].neighbors():
            if not visited[neighbour]:  # які ще не були відвідані
                q.enqueue(neighbour)
                visited[neighbour] = True  # Помічаємо як відвідану

    return visited
Ejemplo n.º 4
0
def wave(maze, start, wall_cell):
    """ функція побудови хвильової матриці для лібіринту
        P54 зі стартовою точкою start
        wall_cell - символ, що позначає стіну лабіринта або непрохідну його клітину"""

    # P54 - матриця лабіринту
    # start - початкова позиція у лабіринті у вигляді кортежу (рядкок, стовпчик)

    dx = [-1, 0, 1, 0]
    dy = [0, -1, 0, 1]

    # dx = [-1, -1, 0, 1, 1, 1, 0, -1]
    # dy = [0, -1, -1, -1, 0, 1, 1, 1]

    n = len(maze)  # кількість рядків у матриці P54
    m = len(maze[0])  # кількість стовпчиків у матриці P54

    # створення та ініціалізація хвильової матриці
    # такої ж розмірності, що і матриця лабіринту
    waveMatrix = []
    for i in range(n):
        row = [-1] * m
        waveMatrix.append(row)

    # створення та ініціалізація sources-матриці
    # такої ж розмірності, що і матриця лабіринту
    sources = []
    for i in range(n):
        row = [None] * m
        sources.append(row)

    q = Queue()  # Створюємо чергу
    q.enqueue(start)  # Додаємо у чергу координати стартової клітини
    waveMatrix[start[0]][
        start[1]] = 0  # Відстань від стартової клітини до себе нуль

    while not q.empty():

        current = q.dequeue()  # Беремо перший елемент з черги
        i = current[0]  # координата поточного рядка матриці
        j = current[1]  # координата поточного стовчика матриці

        # Додаємо в чергу всі сусідні клітини
        for k in range(len(dx)):

            i1 = i + dy[k]  # координата рядка сусідньої клітини
            j1 = j + dx[k]  # координата стовпчика сусідньої клітини

            # які ще не були відвідані та у які можна пересуватися
            if waveMatrix[i1][j1] == -1 and maze[i1][j1] != wall_cell:
                q.enqueue((i1, j1))
                # Встановлюємо відстань на одиницю більшу ніж для поточної
                waveMatrix[i1][j1] = waveMatrix[i][j] + 1

                # Встановлюємо координати звідки ми прийшли у клітину
                sources[i1][j1] = (i, j)

    # Повертаємо хвильову матрицю, та sources-матрицю
    return waveMatrix, sources
Ejemplo n.º 5
0
def BFS(tree: BinaryTree):
    """ Обхід бінарного дерева в ширину

    :param tree: Бінарне дерево
    :return: None
    """
    q = Queue()
    q.enqueue(tree)  # Додаємо у чергу корінь дерева

    while not q.empty():
        current = q.dequeue()  # Беремо перший елемент з черги
        print(current.node())  # Опрацьовуємо взятий елемент

        # Додаємо в чергу лівий і правий нащадки поточного вузла
        if current.has_left():  # якщо поточний вузол має лівого нащадка
            q.enqueue(current.left_subtree())  # додаємо у чергу лівого нащадка
        if current.has_right():  # якщо поточний вузол має правого нащадка
            q.enqueue(
                current.right_subtree())  # додаємо у чергу правого нащадка
Ejemplo n.º 6
0
def waySearch(graph, start, end):
    """ Пошук найкоротшого шляху між двома заданими вершинами графа

    :param graph: Граф
    :param start: Початкова вершина
    :param end: Кінцева вершина
    :return: Кортеж, що містить список вершин - найкоротший шлях, що сполучає вершини start та end та його вагу
    """

    assert start != end

    distances = [-1] * len(graph)  # Масив відстаней
    sources = [None] * len(graph)  # Масив вершин звідки прийшли

    q = Queue()  # Створюємо чергу
    q.enqueue(start)  # Додаємо у чергу стартову вершину
    distances[start] = 0  # Відстань від стартової точки до себе нуль.

    while not q.empty():

        current = q.dequeue()  # Беремо перший елемент з черги

        # Додаємо в чергу всіх сусідів поточного елементу
        for neighbour in graph[current].neighbors():
            if distances[neighbour] == -1:  # які ще не були відвідані
                q.enqueue(neighbour)
                distances[neighbour] = distances[current] + 1
                sources[neighbour] = current  # Вказуємо для сусіда neighbour,
                # що ми прийшли з вершини current

    if sources[end] is None:  # шляху не існує
        return None, INF

    # будуємо шлях за допомогою стеку
    stack = Stack()
    current = end
    while True:
        stack.push(current)
        if current == start:
            break
        current = sources[current]

    way = []  # Послідовність вершин шляху
    while not stack.empty():
        way.append(stack.pop())

    # Повертаємо шлях та його довжину
    return way, distances[end]
Ejemplo n.º 7
0
def waySearchByWave(graph: GraphForAlgorithms, start: int, end: int):
    """ Пошук найкоротшої відстані, використовуючи хвильовий алгоритм

    :param graph: Граф
    :param start: Початкова вершина
    :param end:   Кінцева вершина
    :return: Кортеж, що містить список вершин - найкоротший шлях, що сполучає вершини start та end та його вагу
    """

    # Ініціалізуємо додаткову інформацію у графі для роботи алгоритму.
    for vertex in graph:
        vertex.set_unvisited()  # вершина ще не була відвідана
        vertex.set_source(
            None)  # Вершина з якої прийшли по найкорошому шляху невизначена

    # Відстань у старотовій вершині (тобто від стартової вершини до себе) визначається як 0
    graph[start].set_distance(0)

    q = Queue()  # Створюємо чергу
    q.enqueue(start)  # Додаємо у чергу початкову вершину

    while not q.empty():
        vertex_key = q.dequeue()  # Беремо перший елемент з черги
        vertex = graph[vertex_key]  # Беремо вершину за індексом

        # Для всіх сусідів (за ключами) поточної вершини
        for neighbor_key in vertex.neighbors():
            neighbour = graph[neighbor_key]  # Беремо вершину-сусіда за ключем
            if not neighbour.visited():  # Якщо сусід не був відвіданий
                neighbour.set_distance(
                    vertex.distance() +
                    1)  # Встановлюємо значення відстані у вершині-сусіді
                # значенням на 1 більшии ніж у поточній вершині
                neighbour.set_source(
                    vertex_key
                )  # Встановлюємо для сусідньої вершини ідентифікатор звідки ми прийшли у неї
                q.enqueue(neighbor_key)  # додаємо сусіда до черги

    return graph.construct_way(start, end)  # Повертаємо шлях та його вагу
Ejemplo n.º 8
0
def wave(graph, start):
    """ Хвильовий алгоритм

    :param graph: Граф
    :param start: Вершина з якої починається обхід
    :return: Список відстаней від стартової верниши до кожної вернини графа
    """
    # Введемо масив, що буде містити ознаку чи відвідали вже вершину.
    # Ініціалізуємо масив значеннями False (тобто відвідали)
    visited = [False] * len(graph)

    # Введемо масив, що буде містити
    # відстані від стартової вершини start.
    # Ініціалізуємо масив значеннями -1 (тобто нескінченність)
    distances = [-1] * len(graph)

    q = Queue()  # Створюємо чергу

    q.enqueue(start)  # Додаємо у чергу стартову вершину
    visited[start] = True  # та позначаємо її як відвідану
    distances[start] = 0  # Відстань від стартової точки до себе нуль.

    while not q.empty():

        current = q.dequeue()  # Беремо перший елемент з черги

        # Тут Опрацьовуємо взятий елемент, за необхідності

        # Додаємо в чергу всіх сусідів поточного елементу
        for neighbour in graph[current].neighbors():
            if not visited[neighbour]:  # які ще не були відвідані
                q.enqueue(neighbour)
                visited[neighbour] = True
                # Встановлюємо відстань на одиницю більшу ніж для поточної
                distances[neighbour] = distances[current] + 1

    # Повертаємо масив відстаней від start до всіх вершин графа
    return distances