Намагаючись зрозуміти це доказ коректності Quicksort


10

Цей доказ є доведенням за допомогою індукції і йде так:

P (n) - твердження, що "Quicksort правильно сортує кожен вхідний масив довжиною n".

Базовий регістр: кожен вхідний масив довжиною 1 вже відсортований (утримується P (1))

Індуктивний крок: fix n => 2. Зафіксуйте вхідний масив довжиною n.

Необхідно показати: якщо P (k) справедливо для всіх k <n, то P (n) також має місце

Потім він малює масив A, розділений навколо деякого зведеного p. Отже, він малює p і називає частину масиву, яка є <p, як 1-ю частину, а частина, яка> p, - другу частину. Довжина частини 1 = k1, а довжина частини 2 - k2. За підтвердженням правильності підпрограми Partition (доведено раніше), шарнір p повертається у правильне положення.

введіть тут опис зображення

Індуктивна гіпотеза: 1-я, 2-я частини правильно сортуються рекурсивними дзвінками. (Використовуючи P (K1), P (k2))

Отже: після рекурсивних дзвінків весь масив правильно сортується.

QED

Моя плутанина : у мене багато проблем, коли я точно бачу, як це доводить її правильність. Отже, ми припускаємо, що P (k) дійсно виконується для всіх натуральних чисел k <n.

Більшість доказів індукції, які я бачив до цього часу, мають щось на кшталт: Доведіть базовий випадок і покажіть, що P (n) => P (n + 1). Зазвичай вони також включали якусь алгебраїчну маніпуляцію. Цей доказ здається зовсім іншим, і я не розумію, як застосувати до нього концепцію Індукції. Я можу дещо пояснити, що ключовим є правильність підпрограми Partition. Отож є міркування щодо його правильності наступним чином: Ми знаємо, що кожен рекурсивний виклик розділить масив навколо стрижня. Потім цей шарнір буде знаходитись у належному положенні. Тоді кожний підмасив буде додатково розподілений навколо шарніра, і цей шарнір буде потім у своєму правильному положенні. Це продовжується і продовжується до тих пір, поки ви не отримаєте підмножину довжиною 1, яка тривіально сортується.

Але тоді ми не припускаємо, що P (k) виконується для всіх k <n .... ми насправді ВИКАЗУЄМО це (оскільки підпрограма Partition завжди розміщує один елемент у правильному положенні.) Чи не вважаємо ми, що P (k) має значення для всіх k


Що таке "QUE"? Ви мали на увазі "QED"? (латинська демонстрація Quod Erat, яка не містить жодного слова, що починається з U )
Бакуріу

1
Я дійсно мав на увазі QED. Я думаю, що моя розгубленість призвела до того, що я написав "ЩО?" іспанською мовою
FrostyStraw

Відповіді:


13

Ми дійсно припускаємо, що виконується для всіх k < n . Це узагальнення стилю доказування "З P ( n - 1 )" , який ми доводимо, що ви знайомі з P ( n ) ".P(k)k<nP(n1)P(n)

Доказ, який ви описуєте, відомий як принцип сильної математичної індукції і має форму

Припустимо, що - предикат, визначений на n { 1 , 2 , } . Якщо ми можемо це показатиP(n)n{1,2,}

  1. вірно, іP(1)

  2. (k<n[P(k)])P(n)

Тоді справедливо для всіх цілих чисел n 1 .P(n)n1

У доказі, на який ви посилаєтесь, саме так і відбувається. Щоб скористатись quicksort для сортування масиву розміром , ми розділимо його на три частини: перший k підмасив, шарнір (який буде знаходитись у правильному місці) та решту підрядної маси розміром n - k - 1 . У тому випадку, як працює розділ, кожен елемент у першому підмасиві буде меншим або рівним поворотному, і кожен елемент в другому підмасиві буде більшим або рівним поворотному, тому коли ми рекурсивно сортуємо першу та останню підмагістралі, ми завершиться, відсортувавши весь масив.нкн-к-1

Покажемо, що це правильно за допомогою сильної індукції: оскільки перший підмножина має елементів, ми можемо за допомогою індукції припустити, що він буде правильно сортований. Оскільки у другому підмасиві є n - k - 1 < n елементів, можна припустити, що він буде правильно відсортований. Таким чином, склавши всі шматки разом, ми закінчимо сортування масиву.к<нн-к-1<н


2
Прохолодна частина принципу сильної індукції полягає в тому, що базовий випадок P(1) не потрібен! Якщо ми візьмемо на етапі індукції, то антецедент k < 1 , P ( k ) є вакуумним, тому маємо P ( 1 ) безумовно. n=1k<1,P(k)P(1)
Маріо Карнейро

Гаразд так ... щоб було зрозуміло ... Ми ПРИБУДАЄМО, що P (k) вірно для всіх k <n. І те, як ми покажемо, що P (k) ==> P (n) (для всіх k <n), відбувається через поєднання знання того, що шарнір точно буде в правильному положенні та через припущення (індуктивна гіпотеза ) що лівий і правий підряди також відсортовані. Поєднайте це з базовим випадком (в якому k = 1 <n), і доказ закінчений?
FrostyStraw

ну, мабуть, було б недостатньо знати, що шарнір знаходиться в правильному положенні, але також і те, що правий підрядок є більшим за шар, а лівий - менше, ніж
FrostyStraw,

@FrostyStraw Це китайські шепітки.
Рафаель

1
@FrostyStraw Hehe, я мав на увазі стратегію доказування. :)
Рафаель

7

У цьому доказі використовується принцип повної індукції :

Припустимо, що:

  • Футляр: П(1)
  • Крок: Для кожного н>1П(1),,П(н-1)П(н)

П(н)н1

Q(м)П(1) і П(2) і  і П(м)

Тепер давайте використаємо повну індукцію, щоб довести, що наступна версія Quicksort правильно сортує свої дані:

Quicksort(A, n)
    if n = 1 then:
        return
    else:
        let X[1...x] consist of all elements of A[2],...,A[n] which are at most A[1]
        let Y[1...y] consist of all elements of A[2],...,A[n] which are larger than A[1]
        call Quicksort(X, x)
        call Quicksort(Y, y)
        set A to the concatenation of X, A[1], Y

Ось A[1],...,A[n]вхідний масив і nйого довжина. Ствердження, яке ми хочемо довести, таке:

Ан1АБ

  1. А
  2. Існує перестановка π1,,πн1,,нБ[i]=А[πi]
  3. Б[1]Б[2]Б[н]

П(н)

Якщо - масив довжиною n 1 , а B - його вміст після запускуАн1БQuicksort(A, n)Б[1]Б[2]Б[н]

нн=1н>1Х,х,Y,уQuicksortх,у<н

Х[1]Х[2]Х[х]Y[1]Y[2]Y[у]
ХYХ[х]А[1]<Y[1]
Х[1]Х[х]А[1]<Y[1]Y[у].
Б[1]Б[н]П(н)

4

Відсутня частина аргументу - транзитивність '<' - тобто властивості, що якщо a <b і b <c, то a <c. Доказ того, що кінцевий масив відсортований, виглядає приблизно так:

Нехай A [i], A [j] - елементи масиву після сортування, де i <j. Тоді A [i] <A [j] випливає з одного з наступних випадків розміщення (а інших випадків немає):

(a) i і j знаходяться в першому розділі - A [i] <A [j] слідує за рекурсією / індукцією.

(b) i та j знаходяться у другому розділі - A [i] <A [j] слідує за рекурсією / індукцією.

(c) i знаходиться в першому розділі, а j - індекс повороту - A [i] <A [j] слідує підтвердженням процедури розділення.

(c) i - індекс повороту, а j - у другому розділі - A [i] <A [j] слідує за підтвердженням процедури розділення.

(e) i знаходиться у першому розділі, а j - у другому розділі - потім за процедурою розділення A [i] <pivot та pivot <A [j]. Отже, по транзитивності A [i] <A [j].

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.