Рассмотрим следующую настройку:
- нам дан стек который содержит элементов.
- мы можем использовать постоянное количество дополнительных стеков .
- мы можем применить следующие операции к этим стекам:
- проверить, пуст ли стек,
- сравнить верхние позиции двух стеков,
- удалить верхний элемент в стеке,
- распечатать верхний элемент в стопке,
- скопировать верхний элемент стека в другой стек,
- скопировать содержимое одного стека в другой стек.
Обратите внимание, что это единственные разрешенные операции. Мы не можем поменять элементы, и нам не разрешается помещать какой-либо элемент в любой из стеков, за исключением копирования верхнего элемента в стек (после чего предыдущее содержимое целевого стека удаляется, и оно будет содержать только скопированный элемент). ,
Вот алгоритм сортировки стеков с сравнениями:
last := empty
for i from 1 to n
min := empty
w := s
while w is not empty
if w.top > last and w.top < min
min := w.top
delete w.top
print min
last := min
Можем ли мы сделать лучше?
Существует ли программа, которая печатает отсортированный список элементов в стопках, используя только сравнений?
ds.algorithms
sorting
Сиддхарт
источник
источник
Ответы:
Я думаю, что теперь я могу продемонстрировать нетривиальную нижнюю границу. Идея состоит в том, чтобы реализовать любую такую программу с помощью семейства сравнительных ветвящихся программ. Предположение «только для чтения» означает, что наше семейство ветвящихся программ использует мало, то есть , место. Затем мы применяем нижнюю оценку S T = Ω ( n 2 ), доказанную Бородиным и соавт. в «Пространственно-временном обмене для сортировки на не забывающих машинах». Это дает нам нижнюю границу n 2 / log n для времени.O(logn) ST=Ω(n2) n2/logn
Более подробно: мы можем обойтись без операции 5 выше. Грубо говоря, если мы уже можем сравнить заголовки двух списков и напечатать заголовок списка, тогда нам не нужно выделять заголовок списка в конкретном регистре. Предполагая это, мы видим, что каждый регистр в машине только когда-либо хранит конечную подстроку ввода.
Предположим, что наша программа регистров имеет строк кода и k регистров, X 1 , … , X k .ℓ k X1,…,Xk
Исправить . Построим программу ветвления сравнения для строк длины n следующим образом. Создайте узел для каждого кортежа ( i , d 1 , … , d k ), где 1 ≤ i ≤ ℓ и 0 ≤ d 1 , … , d k ≤ n . Идея в том, что вычисления в машине регистра соответствуют путям в программе ветвления, и мы находимся на узле ( i , d 1 , … , dn n (i,d1,…,dk) 1≤i≤ℓ 0≤d1,…,dk≤n если мы находимся в строке i в машине регистрации, и длина строки, хранящейся в X i, равна d i . Теперь мы должны определить направленные ребра ветвящейся программы.(i,d1,…,dk) i Xi di
Если строка имеет формуi
если тогда перейдите к i 1, еще перейдите к i 2Xu<Xv i1 i2
затем для всех , узел ( i , d 1 , … , d k ) помечается путем сравнения d u -го и d v -го элемента ввода, и «истинное» ребро переходит к ( i 1 , d 1 , … , d k ) и «ложное» ребро к ( i 2 , d 1 , … , d kd1,…,dk (i,d1,…,dk) du dv (i1,d1,…,dk) .(i2,d1,…,dk)
Если строка имеет формуi
, перейти к строке i ′X1←tail(X2) i′
затем есть стрелка из любого узла в ( i ′ , d 2 - 1 , … , d k ) .(i,d1,…,dk) (i′,d2−1,…,dk)
Если строка имеет формуi
, переход к строке i ′print(head(Xu)) i′
затем есть стрелка из любого узла в ( i ′ , d 1 , … , d k ), которая помечена d u -ым узлом входа.(i,d1,…,dk) (i′,d1,…,dk) du
Надеемся, что эти примеры проясняют, как я собираюсь построить свою программу ветвления. Когда все сказано и сделано, это разветвление программа имеет не более узлов, поэтому он имеет пространство O ( журнал N )ℓ⋅nk O(logn)
источник
Вы умеете считать элементы? Тогда, я думаю, есть довольно простая реализация Mergesort. Если бы вы могли поместить дополнительные символы в стек, вы могли бы решить это с помощью 3 стеков, как это:
Если у нас есть только один элемент, список уже отсортирован. Теперь предположим, что мы уже отсортировали верхнюю половину стека. Мы можем скопировать верхнюю половину (в обратном порядке) во второй стек и поместить поверх него символ разделения. Теперь у нас снова есть 3 стека (поскольку мы можем игнорировать уже отсортированные символы под символом разделения) и можем отсортировать нижнюю половину. Наконец, мы можем скопировать отсортированную нижнюю половину в третий стек в обратном порядке и объединить обе половины обратно в исходный стек.
Все операции стоят линейного времени, поэтому мы отсортировали список вO(nlogn)
(Обратите внимание, что нам нужны стеки размером из-за символов разделения, но это можно легко исправить с помощью другого стека)nlogn
Поскольку вы не можете поместить новые элементы в стек, у вас могут возникнуть проблемы в точках разделения. Чтобы решить эту проблему, вы можете сделать следующее с некоторыми дополнительными стеками:
источник