Почему удаление узла из двусвязного списка происходит быстрее, чем удаление узла из односвязного списка?

Мне было любопытно, почему удаление узла из двойного связанного списка происходит быстрее, чем одно связанное. Согласно моей лекции, для двойного связанного списка требуется O(1) по сравнению с O(n) для одного связанного. Согласно моему мыслительному процессу, я думал, что они оба должны быть O(n), так как вам нужно пересечь, возможно, все элементы, поэтому это зависит от размера.

Я понимаю, что это будет связано с тем, что каждый узел имеет указатель на предыдущий и следующий указатель следующий узел, я просто не могу понять, как это будет постоянная операция в смысле O (1)

2 ответов


Это частично зависит от того, как вы интерпретируете установки. Вот две разные версии.

Версия 1: Предположим, вы хотите удалить узел связанного списка, содержащий определенное значение x из одно - или двусвязного списка, но вы не знаете, где он находится в списке. В этом случае вам придется пройти по списку, начиная с самого начала, пока вы не найдете узел для удаления. Как в одиночном, так и в двойном списке вы можете удалить его в O (1) раз, поэтому общее время выполнения-O (n). Тем не менее, сложнее сделать шаг удаления в одиночно связанном списке, так как вам нужно обновить указатель в предыдущей ячейке (на которую не указывает ячейка для удаления), поэтому вам нужно сохранить два указателя при этом.

Версия 2: Теперь предположим, что вам дали указатель на ячейку для удаления и нужно удалить ее. В списке с двойной связью это можно сделать, используя следующие и предыдущие указатели для идентификации двух ячеек вокруг ячейки удалите, а затем перемонтируйте их, чтобы соединить ячейку из списка. Для этого требуется время O(1). Но как насчет отдельного списка? Чтобы удалить эту ячейку из списка, необходимо изменить следующий указатель ячейки, которая появляется перед ячейкой для удаления, чтобы она больше не указывала на ячейку для удаления. К сожалению, у вас нет указателя на эту ячейку, так как список связан только по отдельности. Поэтому вам нужно начать с начала списка, пройти вниз по узлам и найти узел, который приходит прямо перед тем, чтобы удалить. Это занимает время O(n), поэтому время выполнения для шага удаления-O(n) в худшем случае, а не O (1). (Тем не менее, если вы знаете два указатели-ячейка, которую вы хотите удалить, и ячейка прямо перед ней, затем вы можете удалить ячейку в O (1) раз, так как вам не нужно сканировать список, чтобы найти предыдущую ячейку.)

короче говоря: если вы знаете ячейку для удаления заранее, список с двойной связью позволяет удалить ее вовремя O (1) в то время как для одного связанного списка потребуется время O(n). Если вы не знаете ячейку заранее, то это O(n) в обоих случаях.

надеюсь, что это помогает!


список не должен быть пересечен для подключения предыдущего узла к следующему узлу в двусвязный список. Вы просто указываете

curr.Prev.Next = curr.Next и curr.Next.Prev = curr.Prev.

в списке с одной связью вам нужно пересечь список, чтобы найти предыдущий узел. Обход может быть o(n) в не отсортированном списке.