Возврат на любом языке программирования

Мне было дано задание написать программу для перестановки строк. Я понимаю логику, но не точное значение Backtrack в этой программе. Пожалуйста, объясните функциональность цикла for, когда swap будет называться, когда permutate() будет называться и точное значение возврата.

# include <stdio.h>void swap (char *x, char *y)
{
char temp;
temp = *x;
*x = *y;
*y = temp;
}void permute(char *a, int i, int n)
{
int j;
if (i == n)
printf("%s\n", a);
else
{
for (j = i; j <= n; j++)
{
swap((a+i), (a+j));
permute(a, i+1, n);
swap((a+i), (a+j)); //backtrack
}
}
}int main()
{
char a[] = "ABC";
permute(a, 0, 2);
getchar();
return 0;
}

-4

Решение

Создание эскиза стека вызовов может помочь вам понять, как работает алгоритм. Пример строки «ABC» является хорошей отправной точкой. По сути, это то, что произойдет с ABC:

permute(ABC, 0, 2)
i = 0
j = 0
permute(ABC, 1, 2)
i = 1
j = 1
permute(ABC, 2, 2)
print "ABC"j = 2
string = ACB
permute(ACB, 2, 2)
print "ACB"string = ABC
j = 1
string = BAC
permute(BAC, 1, 2)
.... (everything starts over)

Как обычно, в приведенном выше примере отступ определяет, что происходит внутри каждого из рекурсивных вызовов.

В основе цикла for лежит то, что каждая перестановка строки ABC задается ABC, BAC и CBA, а также каждая перестановка подстрок BC, AC и BA (удаляйте первую букву из каждой из предыдущих). Для любой строки S возможные перестановки получаются путем замены каждой позиции первой, плюс все перестановки каждой из этих строк. Думайте об этом так: любая переставленная строка должна начинаться с одной из букв в исходной строке, поэтому вы помещаете каждую возможную букву в первую позицию и рекурсивно применяете тот же метод к остальной части строки (без первой буквы) ,

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

Лично мне не нравится этот комментарий, говорящий «возвращение». Лучшим термином будет «свернуть назад», потому что в этот момент рекурсия сворачивается назад, и вы готовите свою строку для следующего рекурсивного вызова. Возврат обычно используется в ситуации, когда вы исследовали поддерево и не нашли решения, поэтому вы возвращаетесь назад (обратно) и пробуете другую ветку. Взято из википедии:

Backtracking — это общий алгоритм поиска всех (или некоторых)
решения некоторой вычислительной задачи, которая постепенно создает
кандидатов на решения, и отказывается от каждого частичного кандидата c
(«возвращается»), как только он определяет, что с не может быть
завершено к действительному решению.

Обратите внимание, что этот алгоритм не генерирует набор перестановок, поскольку он может печатать одну и ту же строку более одного раза при наличии повторяющихся букв. Крайний случай — когда вы применяете его к строке «aaaaa» или любой другой строке с одной уникальной буквой.

0

Другие решения

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

Вы можете найти исчерпывающее объяснение подобного алгоритма здесь: Использование рекурсии и возврата для генерации всех возможных комбинаций

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector