Можете ли вы вспомнить какую-либо конкретную причину, по которой удаление обычно значительно сложнее реализовать, чем вставку для многих (большинства?) Структур данных?
Быстрый пример: связанные списки. Вставка тривиальна, но удаление имеет несколько особых случаев, которые значительно усложняют ее. Самобалансирующиеся бинарные деревья поиска, такие как AVL и Red-black, являются классическими примерами болезненной реализации удаления.
Я хотел бы сказать, что это связано с тем, как думает большинство людей: нам легче определять вещи конструктивно, что приводит к легким вставкам.
algorithms
data-structures
Лео Брито
источник
источник
pop
,extract-min
?Ответы:
Это больше, чем просто состояние души; Существуют физические (то есть цифровые) причины, по которым удаление сложнее.
Когда вы удаляете, вы оставляете дыру там, где раньше было что-то. Технический термин для получающейся энтропии - «фрагментация». В связанном списке это требует, чтобы вы «обошли» удаленный узел и освободили память, которую он использует. В бинарных деревьях это вызывает дисбаланс дерева. В системах памяти это приводит к тому, что память некоторое время не используется, если вновь выделенные блоки больше, чем блоки, оставленные после удаления.
Короче говоря, вставка легче, потому что вы можете выбрать, куда вы собираетесь вставить. Удаление сложнее, потому что вы не можете заранее предсказать, какой элемент будет удален.
источник
Почему его сложнее удалить, чем вставить? Структуры данных разрабатываются больше с учетом вставки, чем удаления, и это справедливо.
Учтите это - чтобы удалить что-то из структуры данных, оно должно быть там в первую очередь. Поэтому вам нужно сначала добавить его, что означает, что вы можете удалить столько же, сколько и вставок. Если вы оптимизируете структуру данных для вставки, вы гарантированно получите по крайней мере такое же преимущество, как если бы она была оптимизирована для удаления.
Кроме того, какой смысл в последовательном удалении каждого элемента? Почему бы просто не вызвать некоторую функцию, которая очищает ее сразу (возможно, просто создав новую)? Кроме того, структуры данных наиболее полезны, когда они действительно содержат что-то. Таким образом, случай, когда количество удалений равно количеству вставок, на практике не очень распространен.
Когда вы оптимизируете что-то, вы хотите оптимизировать то, что оно делает больше всего и занимает больше всего времени. При обычном использовании удаление элементов структуры данных происходит реже, чем вставка.
источник
k
элементов довольно быстро: выполнить обратную сортировку ввода и объединить с существующим вектором -O(k log k + n)
. Тогда у вас есть структура с довольно сложной вставкой, но потребление верхнихu
элементов тривиально и быстро. Просто возьмите последнююu
и переместите конец вектора. Хотя, если кому-нибудь понадобится такая вещь, я буду проклят. Я надеюсь, что это по крайней мере укрепит ваш аргумент.Это не сложнее.
В случае двусвязных списков при вставке вы будете выделять память, а затем будете связываться либо с головкой, либо с предыдущим узлом, а также с хвостом или следующим узлом. Когда вы удалите, вы будете отменять связь с точно таким же, а затем освободить память. Все эти операции симметричны.
Это предполагает, что в обоих случаях у вас есть узел для вставки / удаления. (И в случае вставки, у вас также есть узел для вставки ранее, поэтому, в некотором смысле, вставка может считаться немного более сложной.) Если вы пытаетесь удалить, имея не узел для удаления, а полезную нагрузку узла, то, конечно, сначала нужно будет найти полезную нагрузку в списке, но это не недостаток удаления, не так ли?
С сбалансированными деревьями применяется то же самое: дерево обычно нуждается в балансировке сразу после вставки, а также сразу после удаления. Рекомендуется использовать только одну подпрограмму балансировки и применять ее после каждой операции, независимо от того, была ли она вставкой или удалением. Если вы пытаетесь реализовать вставку, которая всегда оставляет сбалансированное дерево, а также удаление, которое всегда оставляет сбалансированное дерево, без того, чтобы эти два элемента использовали одну и ту же процедуру балансировки, вы излишне усложняете свою жизнь.
Короче говоря, нет причины, по которой один должен быть сильнее другого, и если вы обнаружите, что это так, то на самом деле вполне возможно, что вы стали жертвой (очень человечной) тенденции находить более естественным мышление Конструктивно, а не субтрактивно, это означает, что вы можете реализовывать удаление более сложным способом, чем это необходимо. Но это человеческая проблема. С математической точки зрения это не проблема.
источник
Что касается времени выполнения, то, сравнивая сложность времени операций со структурами данных в Википедии, обратите внимание, что операции вставки и удаления имеют одинаковую сложность. Профилированная операция удаления - это удаление по индексу, где у вас есть ссылка на удаляемый элемент структуры; вставка по пункту. На практике более длительное время удаления связано с тем, что у вас обычно есть элемент для удаления, а не его индекс, поэтому вам также необходима операция поиска. Большинство структур данных в таблице не требуют дополнительного поиска для вставки, потому что позиция размещения не зависит от элемента, или позиция определяется неявно во время вставки.
Что касается когнитивной сложности, в вопросе есть ответ: крайние случаи. Удаление может иметь больше из них, чем вставка (в общем случае это еще предстоит установить). Однако, по крайней мере, некоторых из этих крайних случаев можно избежать в определенных проектах (например, иметь сторожевой узел в связанном списке).
источник
Вдобавок ко всем упомянутым проблемам существует ссылочная целостность данных. Для наиболее правильно построенной структуры данных, такой как базы данных в SQL, ссылочная целостность Oracle очень важна.
Чтобы убедиться, что вы случайно не уничтожите его, придумано много разных вещей.
Например, каскад на удаление, который не только удаляет то, что вы пытаетесь удалить, но также запускает очистку связанных данных.
Это очищает базу данных от ненужных данных, а также сохраняет целостность данных.
Например, у вас есть таблицы с родителями и видами как связанные записи во второй таблице.
Где родитель является главной таблицей. Если у вас нет усиленной ссылочной целостности, вы можете удалить любые записи в любой таблице, и позже вы не будете знать, как получить полную информацию о семействе, потому что у вас есть данные в дочерней таблице и ничего в родительской таблице.
Вот почему проверка ссылочной целостности не позволит вам удалить запись из родительской таблицы, пока записи из дочерней таблицы не будут очищены.
И именно поэтому в большинстве источников данных сложнее удалить данные.
источник