Ответ 1
Он назвал развернутый связанный список. Кажется, есть несколько преимуществ: одна в скорости и одна в пространстве. Во-первых, если количество элементов в каждом node соответствует размеру (например, не больше размера одной строки кэша), вы получаете значительно лучшую производительность кеша из улучшенной локальности памяти. Во-вторых, поскольку у вас есть O (n/ m) ссылки, где n - количество элементов в развернутом связанном списке, а m - количество элементов, которые вы можете сохранить в любой node, вы также можете сохранить заметный объем пространства, что особенно заметно, если каждый элемент мал. При построении развернутых связанных списков, по-видимому, реализация будет пытаться вообще оставить пространство в узлах; когда вы пытаетесь вставить полный node, вы перемещаете половину элементов. Таким образом, максимум node будет меньше половины. И в соответствии с тем, что я могу найти (я сам не делал никакого анализа), если вы произвольно вставляете вещи, узлы, как правило, составляют примерно три четверти, или даже более полные, если операции, как правило, находятся в конце списка.
И как говорят все остальные (включая Википедию), вы можете проверить списки пропуска. Пропущенные списки - это отличная вероятностная структура данных, используемая для хранения упорядоченных данных с ожидаемым временем выполнения O (log n) для вставки, удаления и поиска. Он реализован "башней" связанных списков, причем каждый уровень имеет меньшее количество элементов, чем выше. Внизу есть обычный связанный список, имеющий все элементы. На каждом последующем слое меньше элементов, в p (обычно 1/2 или 1/4). То, как оно построено, выглядит следующим образом. Каждый раз, когда элемент добавляется в список, он вставлен в соответствующее место в нижней строке (это использует операцию "Найти", которая также может быть выполнена быстро). Затем, с вероятностью p, он вставлен в соответствующее место в связанном списке "выше", создав этот список, если это необходимо; если он был помещен в более высокий список, то он снова появится выше с вероятностью p. Чтобы запросить что-то в этой структуре данных, вы всегда проверяете верхнюю полосу и видите, можете ли вы ее найти. Если элемент, который вы видите слишком большим, вы переходите на следующую нижнюю полосу и начинаете искать снова. Это похоже на двоичный поиск. Википедия объясняет это очень хорошо, и с хорошими диаграммами. Разумеется, использование памяти будет хуже, и вы не будете иметь улучшенную производительность кеша, но обычно это будет быстрее.
Ссылки
- "Unrolled Linked List", http://en.wikipedia.org/wiki/Unrolled_linked_list
- "Unrolled Linked Lists", http://blogs.msdn.com/b/devdev/archive/2005/08/22/454887.aspx
- "Список пропусков", http://en.wikipedia.org/wiki/Skip_list
- Лекция пропущенных списков из моего класса алгоритмов.