Ваш общий подход выглядит правильным, при условии, что вы в порядке с экспоненциальным временем работы, но есть некоторые детали, которые могут вызвать сбои.Вот пара, которую я заметил случайно:
Если список имеет длину 1, if current.get_data() != new.get_data():
потерпит крах, потому что new
равен None
.
Эти строки:
current = current.get_next()
previous = current
new = current
new = new.get_next() # boom!
потерпит крах, когда вы достигнете конца списка.current
- это последний узел, и вы получаете следующий, который является None
, а затем попытаетесь None.get_next()
.
Чтобы исправить это, проследуйте по списку по одному узлу за раз и проверяйте на None
каждый раз, когда вы next
, чтобы избежать сбоев.То же самое относится и к отсоединению: отсоединяйте только один узел за раз, сохраняя prev
там, где он есть и устанавливая prev.next_node
и curr
на curr.next
, затем проверьте, если curr
равно None
, прежде чем делать что-либо еще.
Вот простая, рабочая версия:
def remove(self):
curr = self.head
while curr:
runner = curr.next_node
prev = curr
while runner:
if runner.data == curr.data:
prev.next_node = runner.next_node
else:
prev = runner
runner = runner.next_node
curr = curr.next_node
Идея состоит в том, чтобы использовать curr
для перехода по списку узел за узлом.Для каждого узла создайте runner
и prev
, который будет перебирать оставшуюся часть узла списка по узлу и отсоединять любые узлы, которые соответствуют curr
.
. Существует также линейный подход с использованием set
(место для скорости):
def remove_linear(self):
seen = set()
curr = self.head
prev = None
while curr:
if curr.data not in seen:
seen.add(curr.data)
prev = curr
else:
prev.next_node = curr.next_node
curr = curr.next_node
Попробуйте!
Последнее замечание: Python обычно не использует методы получения и установки;они добавляют многословие и не предлагают никакой подлинной защиты, поэтому я пропустил их в своем коде выше.Доверяйте своему клиенту и используйте префиксы подчеркивания для «приватных» переменных.