آموزش توابع بازگشتی در پایتون، بازگشت (Recursion) یک تکنیک برنامهنویسی است که در آن یک تابع خود را فراخوانی میکند تا یک مشکل را به صورت تدریجی حل کند. در واقع، یک تابع بازگشتی معمولاً برای حل مسائل بزرگتر از نسخههای کوچکتر همان مسئله استفاده میکند.
در هر تابع بازگشتی، باید دو نکته وجود داشته باشد:
مورد پایه (Base Case): شرایطی که به تابع میگوید که دیگر نیازی به فراخوانی مجدد خود ندارد و باید خروجی را برگرداند.
مورد بازگشتی (Recursive Case): شرایطی که در آن تابع خود را فراخوانی میکند و بخش کوچکتری از مسئله را حل میکن
نحوه نوشتن توابع بازگشتی در پایتون:
برای نوشتن یک تابع بازگشتی، باید تابع خود را طوری طراحی کنید که در هر بار فراخوانی یک ورودی را به شکل کوچکتر به تابع ارسال کند و در نهایت به مورد پایه برسد.
ساختار کلی یک تابع بازگشتی:
def recursive_function(parameters): # شرط پایه (Base Case) if condition: return value else: # فراخوانی بازگشتی (Recursive Call) return recursive_function(smaller_problem)
مثال 1: تابع محاسبه فاکتوریل
یکی از سادهترین مثالها برای درک بازگشت، محاسبه فاکتوریل یک عدد است. فاکتوریل یک عدد n به صورت n! برابر با ضرب تمام اعداد صحیح از 1 تا n است. برای محاسبه فاکتوریل به صورت بازگشتی:
مورد پایه: فاکتوریل ۰ و ۱ برابر با ۱ است.
مورد بازگشتی: فاکتوریل n برابر با n * (n-1)!.
کد پایتون برای محاسبه فاکتوریل:
def factorial(n): # شرط پایه if n == 0 or n == 1: return 1 else: # فراخوانی بازگشتی return n * factorial(n - 1) # استفاده از تابع print(factorial(5)) # خروجی: 120
توضیح کد:
ابتدا چک میکنیم که آیا n برابر با ۰ یا ۱ است. در این صورت، فاکتوریل برابر ۱ است.
اگر n بزرگتر از ۱ باشد، تابع خود را با مقدار n-1 فراخوانی میکند و نتیجه را در n ضرب میکند.
مثال 2: توابع فیبوناچی
سری فیبوناچی به این صورت است که هر عدد برابر با مجموع دو عدد قبلی است:
F(0) = 0 F(1) = 1 F(n) = F(n-1) + F(n-2) برای n > 1
کد پایتون برای محاسبه عدد نهم از سری فیبوناچی به صورت بازگشتی:
def fibonacci(n): # شرط پایه if n == 0: return 0 elif n == 1: return 1 else: # فراخوانی بازگشتی return fibonacci(n - 1) + fibonacci(n - 2) # استفاده از تابع print(fibonacci(9)) # خروجی: 34
توضیح کد:
در ابتدا، دو شرط پایه داریم: اگر n برابر با ۰ باشد، ۰ را برمیگردانیم و اگر n برابر با ۱ باشد، ۱ را برمیگردانیم.
در غیر این صورت، تابع بازگشتی دو بار فراخوانی میشود: یکی برای n-1 و دیگری برای n-2 و نتایج آنها با هم جمع میشود.
مزایای استفاده از بازگشت:
سادگی و خوانایی کد: بسیاری از مشکلات میتوانند به سادگی با استفاده از بازگشت حل شوند، به ویژه مشکلاتی که به صورت طبیعی میتوانند به زیر مسائل کوچکتر تقسیم شوند (مثل مشکلات درختی یا سریهای بازگشتی).
کاهش پیچیدگیهای شرطی: برای برخی از مسائل، استفاده از بازگشت کد را سادهتر از نوشتن کدهای پیچیده با حلقهها میکند.
معایب بازگشت:
هزینه حافظه بالا: در هر فراخوانی بازگشتی، اطلاعات مربوط به وضعیت تابع در پشته ذخیره میشود. این ممکن است باعث پر شدن پشته (Stack Overflow) شود، به خصوص در مسائل با عمق بازگشتی زیاد.
کاهش کارایی: در برخی موارد، فراخوانیهای بازگشتی ممکن است زمان زیادی بگیرند، به خصوص اگر از محاسبات تکراری استفاده کنند.
برای حل این مشکلات، میتوان از روشهایی مثل مموایزیشن (Memoization) استفاده کرد تا محاسبات تکراری را ذخیره کرده و از انجام دوباره آنها جلوگیری کرد.
