دوره‌ها / JAVA / بازگشت/ریکرژن (Java Recursion)

بازگشت/ریکرژن (Java Recursion)

15 دقیقه Article

بازگشت/ریکرژن (Recursion): متدی که خودش را صدا می‌زند! 🌀🪆

ریکرژن تکنیکی است که در آن یک متد برای حل یک مسئله بزرگ، خودش را با نسخه‌های کوچکتری از همان مسئله فراخوانی می‌کند. این مفهوم شبیه به عروسک‌های روسی (ماتروشکا) است!

۱. ساختار یک متد بازگشتی

هر متد بازگشتی باید دو بخش اصلی داشته باشد:

  • شرط پایه (Base Case): شرطی که باعث توقف بازگشت می‌شود (بسیار حیاتی!).
  • گام بازگشتی (Recursive Step): جایی که متد خودش را دوباره صدا می‌زند.

مثال: محاسبه مجموع اعداد ۱ تا ۱۰

{code_block('static int sum(int k) {\n if (k > 0) {\n return k + sum(k - 1);\n } else {\n return 0; // شرط پایه\n }\n}')}

۲. چرا از ریکرژن استفاده کنیم؟

ریکرژن برای مسائلی که ساختار تکراری پیچیده دارند (مثل پیمایش درخت‌ها یا حل پازل‌های ریاضی مثل هانوی) کد را بسیار کوتاه‌تر و زیباتر می‌کند.

خطر StackOverflow: اگر شرط پایه را اشتباه بنویسید یا اصلاً ننویسید، متد بی‌نهایت بار خودش را صدا می‌زند تا زمانی که حافظه Stack پر شود و برنامه با خطای StackOverflowError کرش کند.
مقایسه با حلقه: هر مسئله ریکرژنی را می‌توان با while یا for هم حل کرد. ریکرژن معمولاً تمیزتر است اما حافظه بیشتری مصرف می‌کند.
ردیابی ذهنی: بهترین راه برای درک ریکرژن، کشیدن مراحل آن روی کاغذ است. تصور کنید هر فراخوانی یک "ماموریت" جدید است که منتظر نتیجه ماموریت‌های زیرمجموعه خود می‌ماند.
<hr style="margin: 50px 0; border: 0; border-top: 1px dashed rgba(255,255,255,0.1);">

بخش تخصصی: مهندسی متدها و مدیریت حافظه 🛠️💎

در این بخش، به مفاهیمی می‌پردازیم که برای درک عمیق مدیریت حافظه و کارایی در جاوا حیاتی هستند.

۱. پشته متد (Method Stack) و فریم‌ها

هر بار که متدی فراخوانی می‌شود، جاوا یک Stack Frame جدید در حافظه Stack ایجاد می‌کند. این فریم شامل متغیرهای محلی و پارامترهای متد است. وقتی متد تمام می‌شود، فریم آن از پشته حذف (Pop) می‌شود. درک این فرآیند برای دیباگ کردن خطاهایی مثل StackOverflowError بسیار مهم است.

۲. انتقال پارامتر: Pass-by-Value

یک نکته بسیار مهم در جاوا این است که جاوا همیشه مقادیر را به صورت Pass-by-Value منتقل می‌کند. برای انواع اولیه، خودِ مقدار کپی می‌شود. برای اشیاء (Objects)، "کپیِ ریفرنس" به متد فرستاده می‌شود. این یعنی شما می‌توانید ویژگی‌های یک شیء را داخل متد تغییر دهید، اما نمی‌توانید خودِ ریفرنس اصلی را به شیء دیگری متصل کنید.

۳. کدهای ماژولار و اصل Single Responsibility

در مهندسی نرم‌افزار حرفه‌ای، هر متد باید فقط و فقط "یک کار" انجام دهد. اگر متد شما بیش از ۲۰ خط شده یا نام آن شامل کلمه "And" است، احتمالاً باید آن را به متدهای کوچک‌تر تقسیم کنید. این کار باعث می‌شود کد شما قابل تست (Testable) و قابل نگهداری باشد.

نکته پایانی: متدها بلوک‌های سازنده هر اپلیکیشن بزرگ هستند. هنرِ یک برنامه‌نویس جاوا در این است که چطور منطقِ پیچیده را به متدهای ساده، کوچک و قابل استفاده مجدد تقسیم کند.

تمرین‌های عملی

برای تثبیت یادگیری این درس تمرین‌های زیر را حل کنید

فاکتوریل بازگشتی Medium
سوال تمرین

متد factorial را طوری کامل کنید که فاکتوریل عدد n را به صورت بازگشتی حساب کند. (فرمول: n * factorial(n-1)). شرط پایه (n == 1) از قبل نوشته شده است.

پاسخ تمرین
JAVA
public class Main {
  static int factorial(int n) {
    if (n <= 1) {
      return 1;
    }
    return n * factorial(n - 1);
  }

  public static void main(String[] args) {
    System.out.println(factorial(5));
  }
}

آماده رفتن به درس بعدی هستید؟

این درس را به پایان رساندید و می‌توانید به درس بعدی بروید.