На этом шаге мы рассмотрим особенности такого вычисления.
Согласно представленной в таблице 1 на 20 шаге методике первый шаг состоит из определения размера задачи, который зависит от входных параметров. В этой задаче для определения числа операций в алгоритме вычисления степени важен лишь показатель степени. Ясно, что время выполнения растёт с ростом n, поскольку результат требует большего количества умножений. Таким образом, размер задачи - это показатель степени n. Начальное условие соответствует тривиальным экземплярам задачи минимального размера. Так как n - неотрицательное целое число, наименьший экземпляр класса - это b0, равный 1.
На этапе декомпозиции нужно рассмотреть наименьшую и простейшую из подзадач, подобных исходной, которая получается путём уменьшения размера исходной задачи. На этом шаге мы будем уменьшать её размер на 1, что приведёт к следующей схеме:
где f(b, n) = bn - функция от двух параметров b и n. Очевидно, если нам известно решение f(b, n - 1) = bn-1, то в рекурсивном условии остаётся сделать лишь одно - умножить её на b, чтобы получить bn. Функцию вместе с её начальным условием можно реализовать, как показано в примере 4.1.1 2 3 4 5 |
def power_linear(b, n): if n == 0: return 1 else: return b * power_linear(b, n - 1) |
Это пример линейной рекурсии, так как в рекурсивном условии есть только один вызов функции, не являющийся последней выполняемой алгоритмом операцией. Несмотря на то что вызов функции является последним элементом выражения (в строке 5), метод сначала вычисляет её и только потом умножает результат на b. Таким образом, функция не относится к хвостовой рекурсии. Также важно отметить, что функция не нуждается в начальном условии для n = 1, так как оно было бы избыточным. Наконец, вычислительная сложность этого алгоритма линейно зависит от n. В частности, время выполнения может быть определено так:
1, если n = 0 T(n) = (4.1) T(n - 1), если n > 0
Если условием задачи допускались бы ещё и отрицательные целочисленные показатели степени, то размер задачи был бы абсолютной величиной n. В этом случае начальное условие также задаётся для n = 0, а рекурсивное условие идентично случаю n > 0. Когда n - отрицательное, декомпозиция должна уменьшать размер задачи таким образом, чтобы соответствующая подзадача стремилась к начальному условию. Таким образом, для этого рекурсивного условия необходимо увеличивать n. Схема процесса рассуждений была бы такой:
Таким образом, для получения отрицательной степени bn результат подзадачи должен делиться на b. Поэтому рекурсивное условие должно быть f(b, n) = f(b, n + 1)/b, как показано в примере 4.2.
1 2 3 4 5 6 7 |
def power_gtntral_linear(b, n): if n == 0: return 1 elif n > 0: return b * power_gtntral_linear(b, n - 1) else: return power_gtntral_linear(b, n + 1) / b |
На следующем шаге мы рассмотрим вычисление степени за логарифмическое время.