2016-10-22 2 views
4

Из книги Седжвик & Кевин Уэйн Алгоритмы 4-е изданиеMerge Сортировать Базовый вариант (рекурсия) Проанализируйте

В рекурсии код базового варианта часть

if(end <= start) 
    { 
     return; 
    } 

Но я проверил end никогда не станет ниже индекс start. только end = start происходят, когда осталось только 1 элемент. Тогда почему <= меньше оператора, где работает только одно условие, равное = работает постоянно?

Предположим, что имеется массив a[8,5,3].

Теперь средняя точка первого индекса так после разрыва

a[8,5] and a[3] 

divide(a,0,1) and divide(a,2,2), merge(a,0,1,2) начало меньше, чем в конце divide(a,0,1) и start=end происходит в вызове функции divide(a,2,2).

Теперь середина - это 0-й индекс.

a[8] and a[5] 

divide(a,0,0) and divide(a,1,1), merge(a,0,0,1) здесь как в вызове функции start=end является единственно верным.

так буквально end никогда не становилась меньше start таким образом end<start никогда не бывает. только end=start.

Может ли кто-нибудь объяснить мне, почему мы используем оператор < (меньше) в базовом случае сортировки слияния?

Полных Рекурсивный Код

int divide(int a[], int start, int end) 
{ 
    int mid; 

    if(end<=start) 
    { 
     return; 
    } 
    else 
    { 
     mid = (start+end)/2; 
     divide(a, start, mid); 
     divide(a, mid+1, end); 
     merge(a, start, mid, end); 
    } 
} 
+0

ли у вас есть условие, как 'если (конец = start) '? не 'if (end == start)'? –

+0

@MuhammadAhmad, спасибо! да, это работает, если я пишу '(end == start)' – michel

ответ

3

Это правильно, что divide функции никогда вызовов себя с аргументами так, что end < start. Таким образом, if-statement может быть также if (end == start).

Может быть, это поймать, если функция деления вызывается от еще фрагмент кода некорректным образом, например.

void foo(int a[]) 
{ 
    divide(a, 5, 3); 
} 

Это может вызвать петлю Бесконечные если чек только был == вместо <=. Поэтому представляется более безопасным использование <=.

Исходный код также может быть переписано как:

int divide(int a[], int start, int end) 
{ 
    int mid; 

    if(end > start) 
    { 
     mid = (start+end)/2; 
     divide(a, start, mid); 
     divide(a, mid+1, end); 
     merge(a, start, mid, end); 
    } 
} 

В любом случае это, вероятно, не имеет значения для выполнения - оптимизирующий компилятор переставить вещи в любом случае.

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

+0

Спасибо, что сообщили мне об ошибке, которую я сделал с void. – michel

+0

не могли бы вы объяснить, как это будет цикл бесконечности в этом коде? 'void foo (int a []) { divide (a, 5, 3); } '}' – michel

+0

@Michel Если вы используете '==' вместо '<=' вызов 'divide (a, 5, 3)' вызовет бесконечный цикл, потому что: первый раз 'mid' становится 4 (т. Е. (5 +3)/2). Затем функция вызывает себя, используя 'divide (a, 5, 4)'. На этот раз 'mid' становится 4 (т. Е. (5 + 4)/2). Затем функция вызывает себя, используя 'divide (a, 5, 4)'. Тот же звонок снова! Так что это будет продолжаться вечно. – 4386427

1

вы могли бы написать рекурсивную часть функции баррикад ниже

void divide(int a[], int start, int end) 
{ 
    int mid; 

    if(start < end) 
    { 
     mid = (start+end)/2; 
     divide(a, start, mid); 
     divide(a, mid+1, end); 
     merge(a, start, mid, end); 
    } 
} 
+0

Я думаю, что это почти тот же код, что и в ответе @ 4386427, за исключением того, что тип возвращаемого типа является 'void' или меняет' end> ​​start' на 'start

+0

Вы должны оставить комментарий к ответу, если считаете, что тип возврата должен быть 'void' вместо того, чтобы публиковать новый ответ с тем же кодом в нем. –

+0

Хм, ты прав! В основном такой же, как я следовал за псевдокодом от введения к алгоритмам Томасом Х. Корменом – Shateel

Смежные вопросы