Дек — различия между версиями
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)— конструктор, - — ссылка на хвост,
 - — ссылка на голову.
 
Дек очень просто реализуется на списке. Элементы всегда добавляются либо в , либо в .