Академический Документы
Профессиональный Документы
Культура Документы
Учебно-информационный сайт.
Курс ЯЗЫК JAVA Курс WEB РАЗРАБОТКА Курс БАЗЫ ДАННЫХ Успеваемость Процесс обучения Тестирование
Контакты
Рекурсия бывает:
- прямая и косвенная
- без ветвления и с ветвлением
Тест
Для прохождения теста по теме recursion (уровень сложности теста: simple) нажмите “Start Quiz”
Факториал – это функция целочисленного положительного аргумента, которая возвращает целое число равное
произведению всех целых чисел от 1 до аргумента.
Пример:
factorial(5) = 1 * 2 * 3 * 4 * 5 = 120
Факториал растет очень быстро, возможно, стоит использовать не примитивные типы, а BigInteger:
1 import java.math.BigInteger; ?
2
3 public class App {
4 public static void main(String[] args) {
5 System.out.println(factorial(40));
6 }
7
8 public static BigInteger factorial(int arg) {
9 BigInteger result = BigInteger.ONE;
10 for (int k = 1; k <= arg; k++) {
11 result = result.multiply(BigInteger.valueOf(k));
12 }
13 return result;
14 }
15 }
16
17 >> 815915283247897734345611269596115894272000000000
Тест
Для прохождения теста по теме Proc.Recursion.Ariphmetic (уровень сложности теста: mid) нажмите “Start Quiz”
Пример #2:
Если toStrObj(Object) обнаруживает, что ее аргумент – массив, то вызывает toStrArr(Object[]).
А toStrArr(Object[]) для каждого аргумента вызывает toStrObj(Object).
Тест
Для прохождения теста по теме Proc.Recursion.Indirect (уровень сложности теста: mid) нажмите “Start Quiz”
1 ------------------------------------------------------- ?
2 | arg | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10|
3 -------------------------------------------------------
4 | fib(arg)| 1 | 1 | 2 | 3 | 5 | 8 | 13| 21| 34| 55| 89|
5 -------------------------------------------------------
Эту функцию можно вычислять итеративно (int[] result – это “память”, в которой хранятся значения вычисленные
на предыдущих шагах):
Можно эти значения не запоминать, а хранить только последние два значения и через них вычислять следующее
(используем идиому обмена значениями через дополнительную переменную)
Можно свести даже до такой формы (используя идиому обмена значениями без дополнительной переменной)
Вы действительно поняли рекурсию, если можете без запуска программы сказать, что выведут следующие
программы
1 5 ?
2 / \
3 / \
4 3 4
5 /\ / \
6 1 2 2 3
7 /\ /\ /\
8 0 1 0 1 1 2
9 /\
10 0 1
Если же мы заменим fib(k) = fib(k-2) + fib(k-1) на fib(k) = fib(k-1) + fib(k-2), то РЕЗУЛЬТАТ вычисления функции не
изменится, однако ПРОЦЕСС будет другой (обход ЗЕРКАЛЬНОГО по отношению к предыдущему дерева в
глубину слева-направо)
1 5 ?
2 / \
3 / \
4 4 3
5 / \ / \
6 3 2 2 1
7 /\ /\ /\
8 2 1 1 0 1 0
9 /\
10 1 0
Тест
Для прохождения теста по теме recursion.fibonacci нажмите “Start Quiz”
Видео
Набор декабрь 2013
Набор октябрь 2013 (РЕКОМЕНДУЕМОЕ)
Набор июль 2013
Набор апрель 2013
Набор февраль 2013
Набор январь 2013
Набор октябрь 2012
Лабораторные
Лабораторная: proc.recursion.hanoi_tower
proc.recursion.hanoi_tower
Проставьте правильные аргументы методов в рекурсивных вызовах exchange вместо вопросительных знаков.
Итоговый код должен корректно решать задачу о Ханойской башне.
Решение должно иметь вид
import java.util.Stack;
}
}
Лабораторная: proc.recursion.permutation
proc.recursion.permutation
Задача о генерации всех возможных перестановок элементов заданного списка.
Из списка длины N можно построить N! возможных перестановок (N! = 1 * 2 * … * (N – 1) * N, 1!=1, 2!=1*2=2,
3!=1*2*3=6, 4!=1*2*3*4=24, …).
Пример:
Из элементов списка [10, 20, 30] можно построить 6 различных перестановок:
[20, 30, 20]
[10, 20, 30]
[30, 20, 10]
[20, 10, 30]
[30, 10, 20]
[10, 30, 20]
Это некорректный код, который должен рекурсивно строить все возможные перестановки.
Исправьте его.
import java.util.Arrays;
>> [2, 3, 1]
>> [2, 3, 1]
>> [1, 2, 3]
>> [1, 2, 3]
>> [2, 1, 3]
>> [2, 1, 3]
Этот код “недоперемешивает” элементы. Количество вариантов верное, но по какой-то причине имеются
дубликаты.
import java.util.ArrayList;
import java.util.List;
Лабораторная: proc.recursion.parser
proc.recursion.parser
Это пример небольшого и ограниченного по функциональности рекурсивного парсера арифметических
выражений.
Он умеет:
1) встретив скобки с двух сторон – свести задачу к анализу содержимого скобок (пример:”(1+1)” -> “1+1″, пример
“(1+(2/3))” -> “1+(2/3)”);
2) встретив число-знак-XXX – свести задачу к анализу XXX
(пример:”1*(10-3)” -> “(10-3)”, пример “3+(2/(9+1))” -> “(2/(9+1)”);
Задание: переписать его, что бы он ВМЕСТО пункта 2 дела пункт 2′
2′) встретив XXX-знак-число – сведил задачу к анализу XXX.
(пример:”(10-3)*1″ -> “(10-3)”, пример “(2/(9+1))+3″ -> “(2/(9+1)”);
Предупреждение #1: это не полноценный парсер арифметических выражений, есть множество корректных
выражений на которых он “падает” или вычисляет некорректно (“(1+1)+(1+1)”, “-1″, …).
Предупреждение #2: в условиях лабораторной ожидается, что старые выражения вида число-знак-XXX
больше на разбираются.
}
}
Литература
Stack/Method invocation в JVM
….- JVM Spec: Java Virtual Machine Stacks
….- JVM Spec: Frames
….- JVM Spec: Local Variables
….- JVM Spec: Receiving Arguments
….- JVM Spec: Invoking Methods
Алгоритмическая сторона вопроса
- Вирт, “Алгоритмы и структуры данных”
….- глава 3, “Рекурсивные алгоритмы”
- Макконелл, “Анализ алгоритмов”
….- Глава 1.5. “Алгоритмы вида «разделяй и властвуй»”
- Кормен, “Алгоритмы. Построение и анализ”
….- Глава 4. Рекуррентные соотношения