Processing math: 100%

Частичные сортировки

Требуется узнать первые k элементов в отсортированном массиве.

Варианты: 1. Отсортировать весь массив полностью O(nlogn) 2. Неполная HeapSort: T(k,n)=T(makeheap)+kT(extractmin)=O(n)+kO(logn). Если k=o(nlogn)T(k,n)=O(n). Быстрее (ассимптотически) сделать нельзя. 3. Запустить QuickSort только на тех левых половинах, длина которых меньше k. Время работы O(n+klogk) в среднем (доказательство ниже).

Порядковые статистики

kпорядковая статистика для массива -- это элемент, который будет стоять на k-ом месте в отсортированном массиве. Медиана -- это n2 порядковая статистика

Randomized selection

def randomized_selection(a, r, l, k):
    px = rand(l, r)
    m_l, m_r = partition3(a, l, r, px)  # берем partition, который учитывает одинаковые элементы
    if m_l - l > k:
        return randomized_selection(a, l, m_l, k)
    elif m_r - i > k:
        return a[m_l]
    else:
        return randomized_selection(a, m_r, r, k - m_r)

Оценка: 1. Худший случай: T(n)T(n1)+O(n)=O(n2) 2. Средний случай: E(#partition: получим "хорошее разбиение")=2 E(T(n))E(T(3/4n))+E(#...)O(n)=E(T(3/4n))+O(n)=O(n)

Сравнение с частичной сортировкой: T(PartialQuickSort(n, k))T(RandomizedSelection(n, k))+T(QuickSort(k))=O(n)+O(klogk)

"Медиана медиан" (Блюм-Флойд-Пратт-Равест-Таржан)

  1. Разбиваем массив на группы по пять элементов
  2. Сортируем группы
  3. Строим массив b, состоящий из медиан этих групп
  4. Вызываемся рекурсивно на b и получаем медиану m
  5. Используем m в partition и вызываемся рекурсивно
def mm(a, l, r, k):
    if l - r == 1:
        return a[l]
    sort_by_5(a, l, r)
    b = medians_by_5(a, l, r)
    m = mm(b, 0, len(b), len(b) / 2)
    px = a[m]
    i = partition(a, l, r, px)
    if i == k:
        return a[i]
    if i > k:
        return mm(a, l, i, k)
    else:
        return mm(a, i, r, k - d)

Оценка:

T(n)T(n5)+T(n710)+O(n) Хотим доказать T(n)=O(n)Cn+d Cn+dCn5+d+C7n10+d+αn+β

Следствие: QuickSort можно реализовать за O(nlogn) в худшем случае.