Дек — различия между версиями
Mutsch (обсуждение | вклад) м |
Mutsch (обсуждение | вклад) |
||
| Строка 20: | Строка 20: | ||
'''boolean''' empty(): | '''boolean''' empty(): | ||
| − | '''return''' d.head%n+1 == d.tail | + | '''return''' d.head % n + 1 == d.tail |
'''function''' pushBack(x : '''T'''): | '''function''' pushBack(x : '''T'''): | ||
'''if''' (d.head == d.tail) | '''if''' (d.head == d.tail) | ||
'''return''' error "overflow" | '''return''' error "overflow" | ||
| − | + | d[d.tail] = x | |
| − | + | d.tail = (d.tail - 2 + n) % n + 1 | |
'''T''' popBack(): | '''T''' popBack(): | ||
| Строка 37: | Строка 37: | ||
'''if''' (d.head == d.tail) | '''if''' (d.head == d.tail) | ||
'''return''' error "overflow" | '''return''' error "overflow" | ||
| − | + | d[d.head] = x | |
| − | + | d.head = d.head % n + 1 | |
'''T''' popFront(): | '''T''' popFront(): | ||
| Строка 48: | Строка 48: | ||
Все операции выполняются за <tex>O(1)</tex>. | Все операции выполняются за <tex>O(1)</tex>. | ||
=== На саморасширяющемся массиве === | === На саморасширяющемся массиве === | ||
| − | --- | + | Ключевые поля: |
| + | * <tex>\mathtt{s[1\dots n]}</tex> {{---}} массив, в котором хранится дек, | ||
| + | * <tex>\mathtt{newDeque[1\dots newSize]}</tex> {{---}} временный массив, где хранятся элементы после перекопирования, | ||
| + | * <tex>\mathtt{d.head}</tex> {{---}} индекс головы дека, | ||
| + | * <tex>\mathtt{d.tail}</tex> {{---}} индекс хвоста дека, | ||
| + | * <tex>\mathtt{capacity}</tex> {{---}} размер массива. | ||
| + | |||
| + | Если реализовывать дек на динамическом массиве, то мы можем избежать ошибки переполнения. При выполнении операций <tex>pushBack</tex> и <tex>pushFront</tex> происходит проверка на переполнение и, если нужно, выделяется большее количество памяти под массив. Также проверяем, не нужно ли нам уменьшить размер массива при выполнении операций <tex>popBack</tex> и <tex>popFront</tex>. Для удобства выделим в отдельную функцию <tex>size</tex> получение размера дека. | ||
| + | |||
| + | '''int''' size() | ||
| + | '''if''' d.tail > d.head | ||
| + | '''return''' n - d.tail + d.head - 1 | ||
| + | '''else''' | ||
| + | '''return''' d.head - d.tail - 1 | ||
| + | |||
| + | '''function''' pushBack(x : '''T'''): | ||
| + | '''if''' (d.head == d.tail) | ||
| + | '''T''' newDeque[capacity * 2] | ||
| + | '''for''' i = 1 '''to''' capacity - 1 | ||
| + | newDeque[i] = d[d.tail + 1] | ||
| + | d.tail = d.tail % n + 1 | ||
| + | d = newDeque | ||
| + | d.tail = capacity * 2 | ||
| + | d.head = capacity - 1 | ||
| + | capacity = capacity * 2 | ||
| + | d[d.tail] = x | ||
| + | d.tail = (d.tail - 2 + n) % n + 1 | ||
| + | |||
| + | '''T''' popBack(): | ||
| + | '''if''' (empty()) | ||
| + | '''return''' error "underflow" | ||
| + | '''if''' (size() < capacity / 4) | ||
| + | '''T''' newDeque[capacity / 2] | ||
| + | '''for''' i = 1 '''to''' size() | ||
| + | newDeque[i] = d[d.tail + 1] | ||
| + | d.tail = d.tail % n + 1 | ||
| + | d = newDeque | ||
| + | d.tail = capacity / 2 | ||
| + | d.head = size() + 1 | ||
| + | d.tail = d.tail % n + 1 | ||
| + | '''return''' d[d.tail] | ||
| + | |||
| + | '''function''' pushFront(x : '''T'''): | ||
| + | '''if''' (d.head == d.tail) | ||
| + | '''T''' newDeque[capacity * 2] | ||
| + | '''for''' i = 1 '''to''' capacity - 1 | ||
| + | newDeque[i] = d[d.tail + 1] | ||
| + | d.tail = d.tail % n + 1 | ||
| + | d = newDeque | ||
| + | d.tail = capacity * 2 | ||
| + | d.head = capacity - 1 | ||
| + | d[d.head] = x | ||
| + | d.head = d.head % n + 1 | ||
| + | |||
| + | '''T''' popFront(): | ||
| + | '''if''' (empty()) | ||
| + | '''return''' error "underflow" | ||
| + | '''if''' (size() < capacity / 4) | ||
| + | '''T''' newDeque[capacity / 2] | ||
| + | '''for''' i = 1 '''to''' size() | ||
| + | newDeque[i] = d[d.tail + 1] | ||
| + | d.tail = d.tail % n + 1 | ||
| + | d = newDeque | ||
| + | d.tail = capacity / 2 | ||
| + | d.head = size() + 1 | ||
| + | d.head = (d.head - 2 + n) % n + 1 | ||
| + | '''return''' d[d.head] | ||
| + | |||
=== На списке === | === На списке === | ||
Ключевые поля: | Ключевые поля: | ||
Версия 00:32, 6 января 2016
Содержание
Определение
Дек (от англ. deque — double ended queue) — структура данных, представляющая из себя список элементов, в которой добавление новых элементов и удаление существующих производится с обоих концов. Дек можно воспринимать как двустороннюю очередь или двусторонний стек. Он имеет следующие операции:
- — проверка на наличие элементов,
- (запись в конец) — операция вставки нового элемента в конец,
- (снятие с конца) — операция удаления конечного элемента,
- (запись в начало) — операция вставки нового элемента в начало,
- (снятие с начала) — операция удаления начального элемента.
Реализации
Дек расходует только памяти, на хранение самих элементов.
На массиве
Ключевые поля:
- — массив, с помощью которого реализуется дек, способный вместить не более элементов,
- — индекс головы дека,
- — индекс хвоста дека.
Дек состоит из элементов . Всего дек способен вместить не более элементов, поэтому при переполнении приходится перевыделять память и копировать все элементы.
boolean empty(): return d.head % n + 1 == d.tail
function pushBack(x : T):
if (d.head == d.tail)
return error "overflow"
d[d.tail] = x
d.tail = (d.tail - 2 + n) % n + 1
T popBack():
if (empty())
return error "underflow"
d.tail = d.tail % n + 1
return d[d.tail]
function pushFront(x : T):
if (d.head == d.tail)
return error "overflow"
d[d.head] = x
d.head = d.head % n + 1
T popFront():
if (empty())
return error "underflow"
d.head = (d.head - 2 + n) % n + 1
return d[d.head]
Все операции выполняются за .
На саморасширяющемся массиве
Ключевые поля:
- — массив, в котором хранится дек,
- — временный массив, где хранятся элементы после перекопирования,
- — индекс головы дека,
- — индекс хвоста дека,
- — размер массива.
Если реализовывать дек на динамическом массиве, то мы можем избежать ошибки переполнения. При выполнении операций и происходит проверка на переполнение и, если нужно, выделяется большее количество памяти под массив. Также проверяем, не нужно ли нам уменьшить размер массива при выполнении операций и . Для удобства выделим в отдельную функцию получение размера дека.
int size()
if d.tail > d.head
return n - d.tail + d.head - 1
else
return d.head - d.tail - 1
function pushBack(x : T):
if (d.head == d.tail)
T newDeque[capacity * 2]
for i = 1 to capacity - 1
newDeque[i] = d[d.tail + 1]
d.tail = d.tail % n + 1
d = newDeque
d.tail = capacity * 2
d.head = capacity - 1
capacity = capacity * 2
d[d.tail] = x
d.tail = (d.tail - 2 + n) % n + 1
T popBack():
if (empty())
return error "underflow"
if (size() < capacity / 4)
T newDeque[capacity / 2]
for i = 1 to size()
newDeque[i] = d[d.tail + 1]
d.tail = d.tail % n + 1
d = newDeque
d.tail = capacity / 2
d.head = size() + 1
d.tail = d.tail % n + 1
return d[d.tail]
function pushFront(x : T):
if (d.head == d.tail)
T newDeque[capacity * 2]
for i = 1 to capacity - 1
newDeque[i] = d[d.tail + 1]
d.tail = d.tail % n + 1
d = newDeque
d.tail = capacity * 2
d.head = capacity - 1
d[d.head] = x
d.head = d.head % n + 1
T popFront():
if (empty())
return error "underflow"
if (size() < capacity / 4)
T newDeque[capacity / 2]
for i = 1 to size()
newDeque[i] = d[d.tail + 1]
d.tail = d.tail % n + 1
d = newDeque
d.tail = capacity / 2
d.head = size() + 1
d.head = (d.head - 2 + n) % n + 1
return d[d.head]
На списке
Ключевые поля:
-
ListItem(data : T, next : ListItem, prev : ListItem)— конструктор, - — ссылка на хвост,
- — ссылка на голову.
Дек очень просто реализуется на списке. Элементы всегда добавляются либо в , либо в .