«Почти сортировка» целых чисел за линейное время

16

Меня интересует сортировка массива положительных целочисленных значений за линейное время (в модели оперативной памяти с одинаковой мерой стоимости, т. Е. Целые числа могут иметь размер до логарифмического, но предполагается, что арифметические операции над ними будут выполняться единица времени). Конечно, это невозможно с помощью алгоритмов сортировки, основанных на сравнении, поэтому мне интересно вычислить «приблизительную» сортировку, то есть вычислить некоторую перестановку из , который на самом деле не сортируется в целом , а «хорошее приближение» из отсортированной версии . Я буду предполагать, что мы сортируем целые числа в порядке убывания, потому что это делает продолжение более приятным, но, конечно, можно сформулировать проблему наоборот.L=v1,,vnvσ(1),,vσ(n)LL

Одним из возможных критериев приближенной сортировки является следующее (*): если будет , то для каждого мы требуем, чтобы (т.е. «квази-отсортированный» список сверху ограничен убывающей функцией ). Легко видеть, что фактическая сортировка удовлетворяет этому: должно быть больше, чем поэтому оно не больше есть , и в общем случае должно превышать который являетсяNivi1invσ(i)N/iiN/ivσ(2)vσ(1)(vσ(1)+vσ(2))/2N/2vσ(я)(ΣJяvσ(я))/яN/i,

Например, требование (*) может быть достигнуто с помощью алгоритма ниже (предложено @Louis). Мой вопрос: существует ли работа по этой задаче «почти сортировки» целых чисел в линейном времени, навязывая какое-то требование типа (*), которое бы удовлетворяла реальная сортировка? Имеет ли приведенный ниже алгоритм или какой-либо его вариант установленное имя?

Редактировать: исправлен алгоритм и добавлено больше объяснений


Алгоритм:

INPUT: V an array of size n containing positive integers
OUTPUT: T

N = Σ_{i<n} V[i]
Create n buckets indexed by 1..n
For i in 1..n
| Add V[i] into the bucket min(floor(N/V[i]),n)
+

For bucket 1 to bucket n
| For each element in the bucket
| | Append element to T
| +
+

Этот алгоритм работает как задумано по следующим причинам:

  1. Если элемент v находится в сегменте j то vN/j .

    vj=min(N/v,n)jN/vN/v

  2. Если элемент находится в сегменте то либо либо . vjN/(j+1)<vj=n

    v помещается в ведроj=min(N/v,n) , таким образомj=N/v илиj=n . В первом случаеj=N/v что означаетjN/v<j+1 и, следовательно,N/(j+1)<v .

  3. Для j<n в сегментах от 1 до j имеется не более j элементов .j

    Пусть j<n и k - общее количество элементов в одном из сегментов 1..j. В силу 2. имеем, что каждый элемент v в сегменте iij ) таков, что N/(j+1)N/(i+1)<v . Следовательно, сумма K всех элементов в сегментах от 1 до j больше, чем k×N/(J+1) . Но эта суммаK также меньшеN поэтомуk×N/(j+1)<KN и, следовательно, k/(j+1)<1 что дает намk<j+1 илиkj .

  4. T удовлетворяет (*), т.Е.j элементT таков, чтоT[j]N/j

    Согласно 3. мы имеем, что T[j] , j элемент T , происходит из сегмента i с ij поэтому T[j]N/iN/j .

  5. Этот алгоритм занимает линейное время.

    Вычисление N занимает линейное время. Контейнеры могут быть реализованы с помощью связанного списка, который содержит вставку и итерацию O(1) . Вложенный цикл выполняется столько раз, сколько существует элементов (т.е. n раз).

a3nm
источник
1
Не отклонить вопрос (+1, это хороший вопрос), но разве радикальная сортировка не сделает больше, чем вам нужно?
user541686
@ Mehrdad: Спасибо за ваш комментарий! Radix sort сортирует целые числа, но это займет время . O(nlog(maxivi))
a3nm
Не могли бы вы прокомментировать, что именно нежелательно в этой временной сложности? У вас есть одно очень большое целое число, а все остальное мало, например?
user541686
1
@ a3nm radix sort - это не O (n log n), а O (n), следовательно, линейный, если размер целых чисел фиксирован, например, 32-разрядные числа или 64-разрядные числа. Имеют ли числа, которые вы сортируете, переменный размер?
Ксавье Комбель
1
@XavierCombelle: Да, я работаю в модели RAM и не могу предположить, что входные целые числа ограничены константой.
17

Ответы:

8

Это очень похоже на алгоритм ASort. Смотрите эту статью Giesen et. и др .:

https://www.inf.ethz.ch/personal/smilos/asort3.pdf

nn2/ν(n) has a lower bound of nlog(ν(n)) (assuming ν(n)<n).


EDIT, in response to the clarifications in the question:

What you're doing is simply a bucket sort. However, the algorithm for bucket sort isn't linear in this case. The problem: you have to sum the natural numbers and then perform division on each one of them. Since the numbers are unbounded in size, N/V[i] is no longer a constant-time operation. It will take longer to perform the more numbers you need to sum.

How much longer? Division depends on the number of digits, so it's lg(n), times n division operations. That probably sounds familiar. :)

Trixie Wolf
источник
1
Thanks for pointing us to this article! Indeed it is a bit related to the question. However, my algorithm (neither the original version nor the slightly different revised version) is not so similar to ASort;. First, I believe my algorithm runs in O(n), not in superlinear time like ASort. Second, criterion (*) is pretty different from approximating Spearman's footrule distance; e.g., criterion (*) is more or less tight depending on the values of the integers, unlike the footrule distance. Third, althout both our algorithm and ASort are bucketing elements, the criteria are pretty different.
a3nm
@a3nm The clarification of what you posted above suggests you're using a bucket sort, which is linear (and not comparison-based, which means testing two items against each other). The problem is that it doesn't work for all mathematical integers. It only works if the integer size is bounded.
Trixie Wolf
When you say "It only works if the integer size is bounded", I think this is only true if I were actually sorting the integers. But in general the algorithm I posted does not actually sort them, it only enforces the weaker criterion (*). So I do think it runs in linear time even when the integer size is not bounded.
a3nm
2
@a3nm It isn't linear. See my expanded response above.
Trixie Wolf
Thanks for the answer, and sorry about the delay. I think there is some confusion about the model. I am working in the RAM model with uniform time measure (as in van Emde Boas, Machine Models and Simulations, in Handbook of Computation): so the numbers that I manipulate can have logarithmic size, but arithmetic operations on these numbers have unit cost. I have edited my question accordingly. I think that, in this model, the algorithm that I propose really runs in linear time (but of course in this model the nlogn lower bound for actual comparison-based sorting still applies).
a3nm
2

As it turns out, my question is quite irrelevant after all. Indeed, I am working on the RAM machine with uniform cost measure (i.e., we have registers whose registers are not necessarily of constant size but can store integers of logarithmic size in the input at most, and operations on these registers take constant time, including at least addition). And in fact, in this model, sorting integers (by essentially performing a radix sort) can be done in linear time. This is explained in the 1996 paper by Grandjean, Sorting, linear time and the satisfiability problem.

(This does not answer my question of whether there are well-studied notions of "almost sorting" a set of integers, but for them to be interesting one would probably need these weaker notions to be easier to enforce, i.e., work on a weaker model or somehow run in sublinear time. However, I'm currently not aware of a sense in which this would be the case.)

a3nm
источник