CPython deque
реализуется как дважды связанный список блоков размером в 64 элемента (массивы). Все блоки заполнены, за исключением тех, которые находятся на обоих концах связанного списка. IIUC, блоки освобождаются, когда a pop
/popleft
удаляет последний элемент в блоке; они выделяются, когда append
/appendleft
пытается добавить новый элемент и соответствующий блок заполнен.
Я понимаю перечисленные преимущества использования связанного списка блоков, а не связанного списка элементов:
- уменьшить стоимость памяти указателей на предыдущий и следующий в каждом элементе
- сократить время выполнения
malloc
/free
для каждого добавленного/удаляемого элемента - улучшить локальность кэша путем размещения последовательных указателей рядом друг с другом.
Но почему вместо двусвязного списка в первую очередь не был выбран один круглый массив с динамическим размером?
AFAICT, круговая матрица сохранит все вышеперечисленные преимущества и сохранит (амортизированную) стоимость pop*
/append*
в O(1)
(путем комбинирования, как и в list
). Кроме того, это улучшит стоимость поиска по индексу от текущего O(n)
до O(1)
. Круговой массив также будет проще реализовать, поскольку он может повторно использовать большую часть реализации list
.
Я могу видеть аргумент в пользу связанного списка на таких языках, как С++, где удаление элемента из середины может быть сделано в O(1)
с помощью указателя или итератора; однако python deque
не имеет API для этого.