Де я зазвичай використовую Deque у виробничому програмному забезпеченні?


21

Я досить добре знайомий з тим, де використовувати стеки, черги та дерева в програмних додатках, але раніше ніколи не використовував Deque (Double Ended Queue). Де я зазвичай стикаюся з ними в дикій природі? Чи буде він там же, як у черзі, але із додатковими гриблями?



здається, в цій темі є деяка плутанина. В Інтернеті "deque" - це двобічна черга (у wikipedia згадується реалізація пов'язаного списку). Однак у C ++ STL "std :: deque" - це структура, схожа на масив, реалізована як масив блоків даних. Він пропонує довільний доступ, схожий на std :: vector, але його можливість зміни розміру ближче до списку std :: list, оскільки в міру додавання даних він додає блоки та не перерозподіляє та не переміщує існуючі дані.
DXM

1
@DXM: deque STL все ще є двобічною чергою, проте забезпечує швидші операції на кінцях (залежно від реалізації). Те, що він пропонує доступ до середини, також не робить його основну операцію менш схожою на чергу.
gbjbaanb

@gbjbaanb: Все, що я говорю, - якщо ви подивитеся на загальнодоступні інтерфейси 3 класу: std :: vector, std :: list (або std :: черга) та std :: deque, ви побачите, що std :: vector і std :: deque мають однаковий публічний інтерфейс та однакові можливості (std :: deque трохи більш гнучким за рахунок збільшення пам’яті пам’яті). std :: list та std :: черга, з іншого боку, поводяться більше, як їх відповідні частини CS, пов'язаний список та черга відповідно. CS deque! = Std :: deque
DXM

Я знаходжу цю відповідь більш практичним по shiv.mymail - stackoverflow.com/questions/3880254 / ...
roottraveller

Відповіді:


21

Один із способів використання деке - це "старіння" предметів. Зазвичай він використовується як функція скасування чи історія історії. У дік вставлена ​​нова дія. Найдавніші предмети знаходяться спереду. Обмеження розміру деке змушує предмети на передній частині видаляти в якийсь момент, коли нові елементи вставляються (старіння найдавніших предметів). Потім це швидкий спосіб отримати доступ до обох кінців структури, оскільки ви миттєво знаєте найдавніші та найновіші елементи, щоб або видалити передню частину, і здійснити найдавнішу дію в О (1) або скасувати в О (1) час.


Я не думаю, що тут декеси використовуються / не потрібні. Досить простого (можливо, обмеженого розміру) стека.
Конрад Рудольф

2
@Konrad Як ви старієте предмети в простому стеку? (тобто як ви видаляєте команди, які "занадто старі"?)
Андрес Ф.

@AndresF. Чи вік не залежить від розміру стека? Якщо так, то я ніколи не чув про цю структуру даних. В іншому випадку це просто стек з фіксованим розміром, який можна реалізувати в термінах deque, або просто постулюючи більш просту структуру даних, що називається стек фіксованого розміру.
Конрад Рудольф

Так двосторонні черги є корисними в кінці кінців;) Ніколи не чула про стек фіксованого розміру (в тому сенсі , ви маєте в виду, видалення старого елемента). Це має сенс, але це не те, що зазвичай означає «стек», а чи справді це простіше, залишається зрозуміти :)
Андрес Ф.

Про це було написано в коментарях до початкового запитання: en.wikipedia.org/wiki/Double-ended_queue Це просто подвійна черга. Я використовував це на практиці так, як я виклав вище (саме тому я і розмістив це). У справжньому стеці єдиними операціями, які ви повинні мати - це push, pop, top та peek (ми могли б сперечатися з іншими, але це, як правило, це). Ви не повинні знати про те, що знаходиться в нижній частині стека, або навіть як отримати доступ до нижньої частини. У "стеці фіксованого розміру" ви просто генеруєте переповнення стека, а не старіння старих елементів, коли ви заповнювали його.
jmq

1

Відмінне запитання. Я не можу пригадати наш курс CS 102, в якому згадувались про одну заявку на подвійну чергу.

На сьогоднішній день єдиним мені відомим додатком є ​​планувальник роботи з викрадення робіт, згаданий у статті Вікіпедії .

Він працює по суті так:

У звичайній однопотоковій процедурній моделі кожен виклик функції висуває запис активації на так званому стеку викликів . Запис активації містить локальні змінні та параметри цього виклику. Після того, як виклик методу завершено ("повертається"), останній запис активації вискакує зі стека викликів.

Це особливо важливо, оскільки саме так реалізується рекурсія: структура рекурсії представлена ​​в поточному стані стека викликів.

Паралелізуючи рекурсивний алгоритм, ми можемо використовувати цю властивість, замінивши стек виклику чергою викликів. Кожен потік у обчисленні отримує власну чергу дзвінків і штовхає та записує записи активації, як у послідовному виконанні.

Але як тільки нитка закінчила свою роботу (= черга виклику порожня), вона вкрадає роботу з іншого потоку, видаляючи запис активації з черги виклику цього потоку, видаляючи з "неправильного" кінця.

По суті, черга дзвінків виконує функції двох стеків викликів, які тепер обслуговують два потоки.


У вас є джерело для цього? Звучить цікаво.
kyjelly90210

1
@ Richard1987 Стаття у Вікіпедії цитує оригінальний документ. Існує кілька реалізацій, наприклад, у GNU c ++ stdlib-паралельній реалізації-крадіжці (але код читається жахливо) або паралельній реалізації узагальненого ділення та підкорення вашим справді (але останній використовує дуже ідіоматичний стиль програмування зокрема до бібліотеки і тому важко читати)
Конрад Рудольф
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.