Автор оригинала: Neeraj Sujan.
В этом руководстве вы узнаете, как реализовать простую программу Python для обнаружения, если связанный список состоит из цикла или нет. Если вам нужен краткий переподготовка к подключенным спискам, проверить этот блог.
Определение цикла в связанном списке
Связанный список может состоять из цикла, если хвостовой узел связанного списка указывает на другой узел в списке. Давайте увидим небольшой пример, чтобы понять концепцию цикла в связанном списке.
В приведенной выше показателе вы можете видеть, что узел хвостового узла связанного списка, а не указывает на NULL, указывает на другой узел – второй узел в списке. Если такой сценарий возникает, мы говорим, что есть цикл или цикл в списке.
Инициализация и настройка
Сначала мы начнем с помощью инициализации узлов и построении связанного списка.
from linked_list import Node, LinkedList node1 = Node(5) node2 = Node(6) node3 = Node(7) node4 = Node(8) node5 = Node(9) ll = LinkedList() ll.insert_back(node1) ll.insert_back(node2) ll.insert_back(node3) ll.insert_back(node4) ll.insert_back(node5)
Теперь мы подключам пятый узел к 3-м узлу, образующему цикл.
node5.next = node3
Подход 1: наивный подход
Теперь мы посмотрим на простой подход к реализации логики, чтобы узнать, состоит ли список цикла или нет. Один из подходов будет хранить адрес узла в словаре, когда мы проходим через список, и, как только мы столкнулись с узлом, адрес которого уже был в словаре, можно сказать, что в списке был цикл. Давайте посмотрим, как мы можем реализовать это в Python
addresses = {} temp_node = node1 while (temp_node): address = id(temp_node) print(address) if address not in addresses: addresses[address] = 1 else: print('cycle in a linked list') print(temp_node.data) break temp_node = temp_node.next
Недостатком предыдущего подхода заключается в том, что он занимает 0 (N) сложность пространства. Можем ли мы решить эту проблему в O (1) космической сложности?
Подход 2: алгоритм обнаружения цикла Floyd
Мы можем решить эту проблему путем инициализации двух указателей, медленного указателя и быстрой указателя. На каждой итерации мы увеличиваем медленный указатель на 1 и быстрый указатель на 2. Затем мы проверяем, будет ли медленный указатель равен быстрой указателю I.e. Сделайте оба указывающие на тот же узел. Если это так, мы можем сказать, что в связанном списке есть цикл или цикл. Как только мы найдем цикл, мы можем вырваться из цикла While.
Демонстрация
Представьте, что у нас есть список с 5 узлами, как показано на рисунке ниже. Как вы можете видеть хвостовой узел I.E. Узел со значением 9 указывает на узел со значением 7 или 3-м узлом в списке, тем самым формируя цикл или цикл.
Итерация 1:
В первой итерации медленный указатель увеличивается на 1 и быстрый указатель на 2. Как вы можете видеть на рисунке ниже, медленный указатель теперь указывает на узел со значением 6, и быстрый указатель указывает на узел со значением 7.
Итерация 2:
Во второй итерации медленный указатель указывает на узел со значением 7 и быстрыми указывающими указывающими на узел со значением 9 или последним узлом.
Итерация 3:
В третьей итерации мы наблюдаем, что как медленные, так и быстрые указатели указывают на тот же узел I.e. Узел со значением 8. В этом случае мы можем сделать вывод, что в списке есть цикл.
Дайте нам знать, как мы можем реализовать логику Adobe в Python.
Сначала мы инициализируем медленный указатель и быстрый указатель, указывающий на головной узел или первый узел. Затем мы запустим Wide Plup, и мы запускаем петлю, пока медленный указатель действителен, быстрый указатель действителен, и следующее значение быстрого указателя является действительным. Затем мы продолжаем увеличивать медленные и быстрые указатели на 1 и 2 соответственно, и если оба указателя имеют одинаковое значение адреса, мы вырвались из цикла и распечатаем, что был цикл в связанном списке. Вы можете найти всю логику ниже.
slow_ptr = node1 fast_ptr = node1 while (slow_ptr and fast_ptr and fast_ptr.next): slow_ptr = slow_ptr.next fast_ptr = fast_ptr.next.next if slow_ptr == fast_ptr: print('loop in a linked list', slow_ptr.data) break else: print(slow_ptr.data, fast_ptr.data)
Этот алгоритм также называется Алгоритм обнаружения цикла Флойда Отказ
Вывод
В этом руководстве мы видели, как мы можем обнаружить цикл в цикле с использованием алгоритма обнаружения цикла Floyd. Этот алгоритм может обнаружить петлю в O (1) Космическая сложность и O (n) Сложность времени.