<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=178.71.133.19&amp;*</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=178.71.133.19&amp;*"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/178.71.133.19"/>
		<updated>2026-06-28T14:43:11Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%94%D0%B5%D0%BA&amp;diff=51009</id>
		<title>Дек</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%94%D0%B5%D0%BA&amp;diff=51009"/>
				<updated>2016-01-11T00:10:20Z</updated>
		
		<summary type="html">&lt;p&gt;178.71.133.19: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Определение ==&lt;br /&gt;
[[Файл:deque1.png|thumb|right|200px|Дек]]&lt;br /&gt;
'''Дек''' (от англ. ''deque'' {{---}} double ended queue) {{---}} структура данных, представляющая из себя список элементов, в которой добавление новых элементов и удаление существующих производится с обоих концов. Эта структура поддерживает как FIFO, так и LIFO, поэтому на ней можно реализовать как [[Стек | стек]], так и [[Очередь | очередь]]. В первом случае нужно использовать только методы головы или хвоста, во втором {{---}} методы push и pop двух разных концов. Дек можно воспринимать как двустороннюю очередь. Он имеет следующие операции:&lt;br /&gt;
* &amp;lt;tex&amp;gt; \mathtt{empty} &amp;lt;/tex&amp;gt; {{---}} проверка на наличие элементов,&lt;br /&gt;
* &amp;lt;tex&amp;gt; \mathtt{pushBack} &amp;lt;/tex&amp;gt; (запись в конец) {{---}} операция вставки нового элемента в конец,&lt;br /&gt;
* &amp;lt;tex&amp;gt; \mathtt{popBack} &amp;lt;/tex&amp;gt; (снятие с конца) {{---}} операция удаления конечного элемента,&lt;br /&gt;
* &amp;lt;tex&amp;gt; \mathtt{pushFront} &amp;lt;/tex&amp;gt; (запись в начало) {{---}} операция вставки нового элемента в начало,&lt;br /&gt;
* &amp;lt;tex&amp;gt; \mathtt{popFront} &amp;lt;/tex&amp;gt; (снятие с начала) {{---}} операция удаления начального элемента.&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
Дек расходует только &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; памяти, на хранение самих элементов. &lt;br /&gt;
=== Простая реализация ===&lt;br /&gt;
В данной реализации изначально &amp;lt;tex&amp;gt; \mathtt{head = n - 1} &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; \mathtt{tail = n - 1} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
Ключевые поля:&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathtt{d[0\dots 2 \times n - 1]}&amp;lt;/tex&amp;gt; {{---}} массив, с помощью которого реализуется дек, способный вместить не более &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов,&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathtt{head}&amp;lt;/tex&amp;gt; {{---}} индекс головы дека,&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathtt{tail}&amp;lt;/tex&amp;gt; {{---}} индекс хвоста.&lt;br /&gt;
&lt;br /&gt;
Дек состоит из элементов &amp;lt;tex&amp;gt;\mathtt {d[head\dots tail - 1]}&amp;lt;/tex&amp;gt;. Если происходит максимум &amp;lt;tex&amp;gt;\mathtt {n}&amp;lt;/tex&amp;gt; добавлений, то массив длины &amp;lt;tex&amp;gt;\mathtt {2 \times n}&amp;lt;/tex&amp;gt; может вместить в себя все добавленные элементы.&lt;br /&gt;
 &lt;br /&gt;
 '''boolean''' empty():&lt;br /&gt;
   '''return''' head == tail&lt;br /&gt;
&lt;br /&gt;
 '''function''' pushBack(x : '''T'''):&lt;br /&gt;
   d[tail++] = x&lt;br /&gt;
&lt;br /&gt;
 '''T''' popBack():&lt;br /&gt;
   '''if''' (empty()) &lt;br /&gt;
     '''return''' &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;error&amp;lt;/span&amp;gt; &amp;quot;underflow&amp;quot; &lt;br /&gt;
   '''return''' d[--tail]&lt;br /&gt;
&lt;br /&gt;
 '''function''' pushFront(x : '''T'''):&lt;br /&gt;
   d[--head] = x&lt;br /&gt;
&lt;br /&gt;
 '''T''' popFront():&lt;br /&gt;
   '''if''' (empty()) &lt;br /&gt;
     '''return''' &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;error&amp;lt;/span&amp;gt; &amp;quot;underflow&amp;quot; &lt;br /&gt;
   '''return''' d[head++]&lt;br /&gt;
&lt;br /&gt;
=== Циклический дек на массиве константной длины ===&lt;br /&gt;
Во всех циклических реализациях изначально присвоены следующие значения &amp;lt;tex&amp;gt; \mathtt{head = 0} &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; \mathtt{tail = 0} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
Ключевые поля:&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathtt{d[0\dots n-1]}&amp;lt;/tex&amp;gt; {{---}} массив, с помощью которого реализуется дек, способный вместить не более &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов,&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathtt{head}&amp;lt;/tex&amp;gt; {{---}} индекс головы дека,&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathtt{tail}&amp;lt;/tex&amp;gt; {{---}} индекс хвоста.&lt;br /&gt;
&lt;br /&gt;
Дек состоит из элементов &amp;lt;tex&amp;gt;\mathtt {d[head\dots tail-1]}&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;\mathtt {d[0\dots tail-1]}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathtt {d[head\dots n-1]}&amp;lt;/tex&amp;gt;. Всего он способен вместить не более &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов. В данной реализации учитывается переполнение и правильно обрабатывается изъятие из пустого дека. Недостатком является константная длина массива, хранящего элементы. Все операции выполняются за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 '''function''' pushBack(x : '''T'''):&lt;br /&gt;
   '''if''' (head == (tail + 1) % n)&lt;br /&gt;
     '''return''' &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;error&amp;lt;/span&amp;gt; &amp;quot;overflow&amp;quot;&lt;br /&gt;
   d[tail] = x&lt;br /&gt;
   tail = (tail + 1) % n&lt;br /&gt;
&lt;br /&gt;
 '''T''' popBack():&lt;br /&gt;
   '''if''' (empty()) &lt;br /&gt;
     '''return''' &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;error&amp;lt;/span&amp;gt; &amp;quot;underflow&amp;quot; &lt;br /&gt;
   tail = (tail - 1 + n) % n&lt;br /&gt;
   '''return''' d[tail]&lt;br /&gt;
&lt;br /&gt;
 '''function''' pushFront(x : '''T'''):&lt;br /&gt;
   '''if''' (head == (tail + 1) % n)&lt;br /&gt;
     '''return''' &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;error&amp;lt;/span&amp;gt; &amp;quot;overflow&amp;quot;&lt;br /&gt;
   head = (head - 1 + n) % n&lt;br /&gt;
   d[head] = x&lt;br /&gt;
&lt;br /&gt;
 '''T''' popFront():&lt;br /&gt;
   '''if''' (empty()) &lt;br /&gt;
     '''return''' &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;error&amp;lt;/span&amp;gt; &amp;quot;underflow&amp;quot; &lt;br /&gt;
   '''T''' ret = d[head]&lt;br /&gt;
   head = (head + 1) % n&lt;br /&gt;
   '''return''' ret&lt;br /&gt;
&lt;br /&gt;
=== Циклический дек на динамическом массиве ===&lt;br /&gt;
Ключевые поля:&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathtt{n}&amp;lt;/tex&amp;gt; {{---}} размер массива,&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathtt{d[0\dots n-1]}&amp;lt;/tex&amp;gt; {{---}} массив, в котором хранится дек,&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathtt{newDeque[0\dots newSize]}&amp;lt;/tex&amp;gt; {{---}} временный массив, где хранятся элементы после перекопирования,&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathtt{head}&amp;lt;/tex&amp;gt; {{---}} индекс головы дека,&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathtt{tail}&amp;lt;/tex&amp;gt; {{---}} индекс хвоста.&lt;br /&gt;
&lt;br /&gt;
Дек состоит из элементов &amp;lt;tex&amp;gt;\mathtt {d[head\dots tail-1]}&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;\mathtt {d[0\dots tail-1]}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathtt {d[head\dots n-1]}&amp;lt;/tex&amp;gt;. Если реализовывать дек на [[Динамический_массив | динамическом массиве]], то мы можем избежать ошибки переполнения. При выполнении операций &amp;lt;tex&amp;gt;\mathtt{pushBack}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathtt{pushFront}&amp;lt;/tex&amp;gt; происходит проверка на переполнение и, если нужно, выделяется большее количество памяти под массив. Также происходит проверка на избыточность памяти, выделенной под дек при выполнении операций &amp;lt;tex&amp;gt;\mathtt{popBack}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathtt{popFront}&amp;lt;/tex&amp;gt;. Если памяти под дек выделено в четыре раза больше размера дека, то массив сокращается в два раза. Для удобства выделим в отдельную функцию &amp;lt;tex&amp;gt;\mathtt{size}&amp;lt;/tex&amp;gt; получение текущего размера дека.&lt;br /&gt;
 &lt;br /&gt;
 '''int''' size()&lt;br /&gt;
   '''if''' tail &amp;gt; head&lt;br /&gt;
     '''return''' n - head + tail&lt;br /&gt;
   '''else'''&lt;br /&gt;
     '''return''' tail - head&lt;br /&gt;
&lt;br /&gt;
 '''function''' pushBack(x : '''T'''):&lt;br /&gt;
   '''if''' (head == (tail + 1) % n)&lt;br /&gt;
     '''T''' newDeque[n * 2]&lt;br /&gt;
     '''for''' i = 0 '''to''' n - 2&lt;br /&gt;
       newDeque[i] = d[head]&lt;br /&gt;
       head = (head + 1) % n&lt;br /&gt;
     d = newDeque&lt;br /&gt;
     head = 0&lt;br /&gt;
     tail = n - 1&lt;br /&gt;
     n *= 2&lt;br /&gt;
   d[tail] = x&lt;br /&gt;
   tail = (tail + 1) % n&lt;br /&gt;
&lt;br /&gt;
 '''T''' popBack():&lt;br /&gt;
   '''if''' (empty()) &lt;br /&gt;
     '''return''' &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;error&amp;lt;/span&amp;gt; &amp;quot;underflow&amp;quot;&lt;br /&gt;
   '''if''' (size() &amp;lt; n / 4)&lt;br /&gt;
     '''T''' newDeque[n / 2]&lt;br /&gt;
     '''int''' dequeSize = size()&lt;br /&gt;
     '''for''' i = 0 '''to''' dequeSize - 1&lt;br /&gt;
       newDeque[i] = d[head]&lt;br /&gt;
       head = (head + 1) % n&lt;br /&gt;
     d = newDeque&lt;br /&gt;
     head = 0&lt;br /&gt;
     tail = dequeSize&lt;br /&gt;
     n /= 2&lt;br /&gt;
   tail = (tail - 1 + n) % n&lt;br /&gt;
   '''return''' d[tail]&lt;br /&gt;
&lt;br /&gt;
 '''function''' pushFront(x : '''T'''):&lt;br /&gt;
   '''if''' (head == (tail + 1) % n)&lt;br /&gt;
     '''T''' newDeque[n * 2]&lt;br /&gt;
     '''for''' i = 0 '''to''' n - 2&lt;br /&gt;
       newDeque[i] = d[head]&lt;br /&gt;
       head = (head + 1) % n&lt;br /&gt;
     d = newDeque&lt;br /&gt;
     head = 0&lt;br /&gt;
     tail = n - 1&lt;br /&gt;
     n *= 2&lt;br /&gt;
   head = (head - 1 + n) % n&lt;br /&gt;
   d[head] = x&lt;br /&gt;
&lt;br /&gt;
 '''T''' popFront():&lt;br /&gt;
   '''if''' (empty()) &lt;br /&gt;
     '''return''' &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;error&amp;lt;/span&amp;gt; &amp;quot;underflow&amp;quot; &lt;br /&gt;
   '''if''' (size() &amp;lt; n / 4)&lt;br /&gt;
     '''T''' newDeque[n / 2]&lt;br /&gt;
     '''int''' dequeSize = size()&lt;br /&gt;
     '''for''' i = 0 '''to''' dequeSize - 1&lt;br /&gt;
       newDeque[i] = d[head]&lt;br /&gt;
       head = (head + 1) % n&lt;br /&gt;
     d = newDeque&lt;br /&gt;
     head = 0&lt;br /&gt;
     tail = dequeSize&lt;br /&gt;
     n /= 2&lt;br /&gt;
   '''T''' ret = d[head]&lt;br /&gt;
   head = (head + 1) % n&lt;br /&gt;
   '''return''' ret&lt;br /&gt;
&lt;br /&gt;
=== На списке ===&lt;br /&gt;
Ключевые поля:&lt;br /&gt;
* &amp;lt;code&amp;gt;ListItem(data : '''T''', next : '''ListItem''', prev : '''ListItem''')&amp;lt;/code&amp;gt; {{---}} конструктор,&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathtt{tail}&amp;lt;/tex&amp;gt; {{---}} ссылка на хвост,&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathtt{head}&amp;lt;/tex&amp;gt; {{---}} ссылка на голову.&lt;br /&gt;
&lt;br /&gt;
Дек очень просто реализуется на [[Список | двусвязном списке]]. Он состоит из элементов &amp;lt;tex&amp;gt;\mathtt {head\dots tail}&amp;lt;/tex&amp;gt;. Элементы всегда добавляются либо в &amp;lt;tex&amp;gt;\mathtt{tail.prev}&amp;lt;/tex&amp;gt;, либо в &amp;lt;tex&amp;gt;\mathtt{head.next}&amp;lt;/tex&amp;gt;. В данной реализации не учитывается изъятие из пустого дека.&lt;br /&gt;
&lt;br /&gt;
 '''function''' initialize():&lt;br /&gt;
   head = ListItem(''null'', ''null'', ''null'')&lt;br /&gt;
   tail = ListItem(''null'', ''null'', head)&lt;br /&gt;
   head.next = tail&lt;br /&gt;
&lt;br /&gt;
 '''function''' pushBack(x : '''T'''):&lt;br /&gt;
   head = ListItem(x, head, ''null'')&lt;br /&gt;
   head.next.prev = head&lt;br /&gt;
&lt;br /&gt;
 '''T''' popBack():&lt;br /&gt;
   data = head.data&lt;br /&gt;
   head = head.next&lt;br /&gt;
   '''return''' data&lt;br /&gt;
&lt;br /&gt;
 '''function''' pushFront(x : '''T'''):&lt;br /&gt;
   tail = ListItem(x, ''null'', tail)&lt;br /&gt;
   tail.prev.next = tail&lt;br /&gt;
&lt;br /&gt;
 '''T''' popFront():&lt;br /&gt;
   data = tail.data&lt;br /&gt;
   tail = tail.prev&lt;br /&gt;
   '''return''' data&lt;br /&gt;
&lt;br /&gt;
=== На двух стеках ===&lt;br /&gt;
Ключевые поля:&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathtt{leftStack}&amp;lt;/tex&amp;gt; {{---}} ссылка на хвост,&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathtt{rightStack}&amp;lt;/tex&amp;gt; {{---}} ссылка на голову.&lt;br /&gt;
&lt;br /&gt;
Храним два [[Стек | стека]] — &amp;lt;tex&amp;gt;\mathtt{leftStack}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathtt{rightStack}&amp;lt;/tex&amp;gt;. Левый стек используем для операций &amp;lt;tex&amp;gt;\mathtt{popBack}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathtt{pushBack}&amp;lt;/tex&amp;gt;, правый — для &amp;lt;tex&amp;gt;\mathtt{popFront}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathtt{pushFront}&amp;lt;/tex&amp;gt;. Если мы хотим работать с левым стеком и при этом он оказывается пустым, то достаем нижнюю половину элементов из правого и кладем в левый, воспользовавшись при этом локальным стеком. Аналогично с правым стеком. Худшее время работы — &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 '''function''' pushBack(x : '''T'''):&lt;br /&gt;
   leftStack.push(x)&lt;br /&gt;
&lt;br /&gt;
 '''T''' popBack():&lt;br /&gt;
   '''if''' '''not''' leftStack.empty()&lt;br /&gt;
     '''return''' leftStack.pop() &lt;br /&gt;
   '''else'''&lt;br /&gt;
     '''int''' size = rightStack.size()&lt;br /&gt;
     '''Stack&amp;lt;T&amp;gt;''' local&lt;br /&gt;
     '''for''' i = 0 '''to''' size / 2 &lt;br /&gt;
       local.push(rightStack.pop())&lt;br /&gt;
     '''while''' '''not''' rightStack.empty()&lt;br /&gt;
       leftStack.push(rightStack.pop())&lt;br /&gt;
     '''while''' '''not''' local.empty()&lt;br /&gt;
       rightStack.push(local.pop())&lt;br /&gt;
     '''return''' leftStack.pop()&lt;br /&gt;
&lt;br /&gt;
 '''function''' pushFront(x : '''T'''):&lt;br /&gt;
   rightStack.push(x)&lt;br /&gt;
&lt;br /&gt;
 '''T''' popFront():&lt;br /&gt;
   '''if''' '''not''' rightStack.empty()&lt;br /&gt;
     '''return''' rightStack.pop() &lt;br /&gt;
   '''else'''&lt;br /&gt;
     '''int''' size = leftStack.size()&lt;br /&gt;
     '''Stack&amp;lt;T&amp;gt;''' local&lt;br /&gt;
     '''for''' i = 0 '''to''' size / 2 &lt;br /&gt;
       local.push(leftStack.pop())&lt;br /&gt;
     '''while''' '''not''' leftStack.empty()&lt;br /&gt;
       rightStack.push(leftStack.pop())&lt;br /&gt;
     '''while''' '''not''' local.empty()&lt;br /&gt;
       leftStack.push(local.pop())&lt;br /&gt;
     '''return''' rightStack.pop()&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Стек]]&lt;br /&gt;
* [[Очередь]]&lt;br /&gt;
* [[Персистентный дек]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [[wikipedia:ru:Двусвязная_очередь|Википедия {{---}} Дек]]&lt;br /&gt;
* [[wikipedia:en:Deque|Wikipedia {{---}} Deque]]&lt;br /&gt;
* [http://opendatastructures.org/ods-cpp/2_5_Building_Deque_from_Two.html Open Data Structures {{---}} Building a Deque from Two Stacks]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Амортизационный анализ]]&lt;/div&gt;</summary>
		<author><name>178.71.133.19</name></author>	</entry>

	</feed>