Сортировка с использованием стеков только для чтения

14

Рассмотрим следующую настройку:

  • нам дан стек который содержит элементов.sn
  • мы можем использовать постоянное количество дополнительных стеков .O(1)
  • мы можем применить следующие операции к этим стекам:
    1. проверить, пуст ли стек,
    2. сравнить верхние позиции двух стеков,
    3. удалить верхний элемент в стеке,
    4. распечатать верхний элемент в стопке,
    5. скопировать верхний элемент стека в другой стек,
    6. скопировать содержимое одного стека в другой стек.

Обратите внимание, что это единственные разрешенные операции. Мы не можем поменять элементы, и нам не разрешается помещать какой-либо элемент в любой из стеков, за исключением копирования верхнего элемента в стек (после чего предыдущее содержимое целевого стека удаляется, и оно будет содержать только скопированный элемент). ,

Вот алгоритм сортировки стеков с сравнениями:O(n2)

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

Можем ли мы сделать лучше?

Существует ли программа, которая печатает отсортированный список элементов в стопках, используя только O(nlogn) сравнений?

Сиддхарт
источник
2
Похоже, регистры ведут себя как стеки? Похоже, вы говорите о пуш-и поп-операциях. Это твои вопросы? Как бы вы отсортировали стек, используя несколько стеков и операции со стеком?
AturSams
2
С регистрами вы можете: просто поместить каждое число в один регистр ( O ( n ) ), а затем применить обычный алгоритм сортировки ( O ( n lg n ) ). nO(n)O(nlgn)
Kaveh
1
Вы хотите использовать регистры? В противном случае проблема тривиализируется, как прокомментировал Каве. O(1)
Юваль Фильмус
1
Добро пожаловать. Я думал, что нам дано несколько стеков, а не только один, я это исправлю.
Каве
2
@akappa, ты уверен, что можно использовать в этом видении? Мы не можем сохранить произвольную потерю размера больше 1. Разве вам не нужно хранить отсортированные блоки?
Kaveh

Ответы:

1

Я думаю, что теперь я могу продемонстрировать нетривиальную нижнюю границу. Идея состоит в том, чтобы реализовать любую такую ​​программу с помощью семейства сравнительных ветвящихся программ. Предположение «только для чтения» означает, что наше семейство ветвящихся программ использует мало, то есть , место. Затем мы применяем нижнюю оценку S T = Ω ( n 2 ), доказанную Бородиным и соавт. в «Пространственно-временном обмене для сортировки на не забывающих машинах». Это дает нам нижнюю границу n 2 / log n для времени.O(logn)ST=Ω(n2)n2/logn

Более подробно: мы можем обойтись без операции 5 выше. Грубо говоря, если мы уже можем сравнить заголовки двух списков и напечатать заголовок списка, тогда нам не нужно выделять заголовок списка в конкретном регистре. Предполагая это, мы видим, что каждый регистр в машине только когда-либо хранит конечную подстроку ввода.

Предположим, что наша программа регистров имеет строк кода и k регистров, X 1 , , X k .kX1,,Xk

Исправить . Построим программу ветвления сравнения для строк длины n следующим образом. Создайте узел для каждого кортежа ( i , d 1 , , d k ), где 1 i и 0 d 1 , , d kn . Идея в том, что вычисления в машине регистра соответствуют путям в программе ветвления, и мы находимся на узле ( i , d 1 , , dnn(i,d1,,dk)1i0d1,,dkn если мы находимся в строке i в машине регистрации, и длина строки, хранящейся в X i, равна d i . Теперь мы должны определить направленные ребра ветвящейся программы.(i,d1,,dk)iXidi

Если строка имеет формуi

если тогда перейдите к i 1, еще перейдите к i 2Xu<Xvi1i2

затем для всех , узел ( 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)dudv(i1,d1,,dk) .(i2,d1,,dk)

Если строка имеет формуi

, перейти к строке i X1tail(X2)i

затем есть стрелка из любого узла в ( i , d 2 - 1 , , d k ) .(i,d1,,dk)(i,d21,,dk)

Если строка имеет формуi

, переход к строке i print(head(Xu))i

затем есть стрелка из любого узла в ( i , d 1 , , d k ), которая помечена d u -ым узлом входа.(i,d1,,dk)(i,d1,,dk)du

Надеемся, что эти примеры проясняют, как я собираюсь построить свою программу ветвления. Когда все сказано и сделано, это разветвление программа имеет не более узлов, поэтому он имеет пространство O ( журнал N )nkO(logn)

Сиддхарт
источник
0

Вы умеете считать элементы? Тогда, я думаю, есть довольно простая реализация Mergesort. Если бы вы могли поместить дополнительные символы в стек, вы могли бы решить это с помощью 3 стеков, как это:

Если у нас есть только один элемент, список уже отсортирован. Теперь предположим, что мы уже отсортировали верхнюю половину стека. Мы можем скопировать верхнюю половину (в обратном порядке) во второй стек и поместить поверх него символ разделения. Теперь у нас снова есть 3 стека (поскольку мы можем игнорировать уже отсортированные символы под символом разделения) и можем отсортировать нижнюю половину. Наконец, мы можем скопировать отсортированную нижнюю половину в третий стек в обратном порядке и объединить обе половины обратно в исходный стек.

Все операции стоят линейного времени, поэтому мы отсортировали список в O(nlogn)

(Обратите внимание, что нам нужны стеки размером из-за символов разделения, но это можно легко исправить с помощью другого стека)nlogn


Поскольку вы не можете поместить новые элементы в стек, у вас могут возникнуть проблемы в точках разделения. Чтобы решить эту проблему, вы можете сделать следующее с некоторыми дополнительными стеками:

n2logn

lognccnlogn+cn2logn2+cn4logn4+ ...=O(nlogn)O(nlogn)

Cero
источник
Я не уверен, что понимаю. Как мы можем, например, скопировать верхнюю половину стека в обратном порядке в другой стек, если мы никогда не сможем поместить какой-либо элемент в любой стек?
Сиддхарт
Мы не можем поместить любой новый элемент в стек, но согласно 5 мы можем поместить верхний элемент одного стека в другой. Таким образом, копирование стека в обратном порядке требует максимально линейного времени. Итак, я полагаю, это было не то, что вы просили?
Cero
Вы не можете ничего толкать поверх других предметов, как объяснено в вопросе.
Kaveh