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 для этого.