Java - чому рекурсія така погана stack overflow російською

Ні один із засобів мови не може бути поганим чи хорошим за визначенням.

Рекурсія дає можливість програмісту ясніше висловлювати свої думки всім (і в першу чергу компілятору), але ціна цього - розуміння того, що відбувається. Потрібно розуміти що таке стек як він влаштований, що кладеться в стек при виклику. Потрібно мати трохи більше розвинена уява щоб розуміти коли рекурсія зупиниться і що буде з нею при викликах. Потрібно розуміти чому глобальні змінні потрібно міняти обережно і, одночасно, чому в функції повинно бути якомога менше змінних (аж до перевикористання).

Однак будь-який рекурсивний алгоритм може бути записаний без рекурсії. (Зазвичай використовуючи динамічно розширюваний масив)

Так само з класики рекурсії - невміння правильно ставити стек за допомогою ключів компіляції (як часто ви в Java наприклад збирали з командного рядка або може ви пам'ятаєте як запустити потік з великим стеком).

Тому резюме (вибачте за грубість), якщо ви задаєте це питання, тоді не використовуйте рекурсию, якщо ви усвідомлюєте що робите - тоді це дуже зручний інструмент підвищує читабельність коду в ряді завдань і дає попрацювати компілятору а не вам в сенсі оптимізацій.

відповідь дан 29 Січня о 16:57

Рекурсія не погана. Просто вона вимагає уважного ставлення до стека. Так як він з кожним кроком приростає, що часто призводить до переповнення.

І в принципі її можна замінити на ітерацію (цикл). Що зазвичай і радять робити в мовах, де немає Хвостовий рекурсії.

Наприклад, в scala можна явно вказати, що повинна бути використана Хвостова рекурсія за допомогою анотації @tailrec. тоді виклик (call) буде замінений на перехід (go to).

Неправильне використання рекурсії може привести до переповнення стека і до величезних обчислювальних витрат. Однак, рекурсивний підхід має істотний плюс в природності алгоритму: при використанні апарату математичної індукції, можна легко протестувати правильність результату (пам'ятаючи про особливості подання даних в пам'яті). Рекомендую позначати рекурсивні процедури анотацією @tailrec для перевірки оптимізації функції.

Для оптимізації рекурсивного методу зазвичай вдаються до хвостової рекурсії: передають в функцію додатковий параметр, який зберігає результати попереднього обчислення. Однак, в деяких випадках цього недостатньо: наприклад, в тому ж прикладі з числами Фібоначчі: тут потрібно зберігати список результатів. Для цього можна використовувати ледачі колекції, всередині або поза методу. Іноді виникають і більш складні завдання, коли, наприклад, необхідно знайти оптимальний список результатів. В цьому випадку можна використовувати рекурсію з відсіканням елементів.

відповідь дан 26 Лютого о 11:49

Схожі статті