آموزش رایگان جاوا اسکریپت (JavaScript)

آموزش جامع توابع بازگشتی (Recursion) و کاربردهای آن در جاوا اسکریپت: مثال‌ها و مفاهیم

29م مهر 1403 محراب حسن زاده
آموزش جامع توابع بازگشتی (Recursion) و کاربردهای آن در جاوا اسکریپت: مثال‌ها و مفاهیم

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

 

مفهوم توابع بازگشتی

تابع بازگشتی (Recursive Function) تابعی است که خود را درون بدنه خود فراخوانی می‌کند. این تکنیک به شما این امکان را می‌دهد که یک مسئله بزرگ را به مسائل کوچکتر مشابه تقسیم کنید و هر کدام را به صورت مستقل حل کنید.

 

ساختار تابع بازگشتی

یک تابع بازگشتی معمولاً شامل دو بخش اصلی است:

  • پایه (Base Case): شرایطی که باعث پایان یافتن فراخوانی‌های بازگشتی می‌شود.

  • گام بازگشتی (Recursive Case): شرایطی که تابع را به صورت بازگشتی فراخوانی می‌کند.

 

مثال ساده: محاسبه فاکتوریل

محاسبه فاکتوریل یک عدد مثال کلاسیکی از استفاده از توابع بازگشتی است:


function factorial(n) {
  // پایه: فاکتوریل 0 و 1 برابر با 1 است
  if (n === 0 || n === 1) {
    return 1;
  }
  // گام بازگشتی: n * فاکتوریل (n-1)
  return n * factorial(n - 1);
}

console.log(factorial(5)); // Output: 120

 

در این مثال:

  • پایه: اگر n برابر با 0 یا 1 باشد، فاکتوریل آن برابر با 1 است.

  • گام بازگشتی: برای محاسبه فاکتوریل n, تابع factorial(n-1) به صورت بازگشتی فراخوانی می‌شود.

 

کاربردهای توابع بازگشتی

توابع بازگشتی در حل مسائل پیچیده و مسائل ساختاریافته بسیار مفید هستند. در زیر به برخی از کاربردهای متداول آن‌ها اشاره خواهیم کرد:

 

جستجوی عمق‌اول (Depth-First Search)

در ساختارهای داده‌ای مانند درخت‌ها و گراف‌ها، الگوریتم‌های جستجوی عمق‌اول معمولاً با استفاده از توابع بازگشتی پیاده‌سازی می‌شوند.

مثال: جستجو در درخت باینری


class Node {
  constructor(value, left = null, right = null) {
    this.value = value;
    this.left = left;
    this.right = right;
  }
}

function depthFirstSearch(node, target) {
  if (node === null) return false;
  if (node.value === target) return true;
  return depthFirstSearch(node.left, target) || depthFirstSearch(node.right, target);
}

// ساخت درخت نمونه
const tree = new Node(1,
                new Node(2,
                  new Node(4),
                  new Node(5)),
                new Node(3));

console.log(depthFirstSearch(tree, 5)); // Output: true
console.log(depthFirstSearch(tree, 6)); // Output: false

 

در این مثال:

  • پایه: اگر node برابر با null باشد، جستجو به پایان می‌رسد.

  • گام بازگشتی: برای جستجوی در زیر درخت چپ و راست به صورت بازگشتی ادامه می‌دهیم.

 

مرتب‌سازی با استفاده از الگوریتم‌های بازگشتی

الگوریتم‌های مرتب‌سازی مانند Quick Sort و Merge Sort از تکنیک‌های بازگشتی برای تقسیم و حل استفاده می‌کنند.

مثال: Merge Sort


function mergeSort(arr) {
  if (arr.length <= 1) return arr;

  const mid = Math.floor(arr.length / 2);
  const left = mergeSort(arr.slice(0, mid));
  const right = mergeSort(arr.slice(mid));

  return merge(left, right);
}

function merge(left, right) {
  let result = [];
  let leftIndex = 0;
  let rightIndex = 0;

  while (leftIndex < left.length && rightIndex < right.length) {
    if (left[leftIndex] < right[rightIndex]) {
      result.push(left[leftIndex]);
      leftIndex++;
    } else {
      result.push(right[rightIndex]);
      rightIndex++;
    }
  }

  return result.concat(left.slice(leftIndex)).concat(right.slice(rightIndex));
}

console.log(mergeSort([5, 3, 8, 4, 2])); // Output: [2, 3, 4, 5, 8]

 

در این مثال:

  • پایه: اگر آرایه تنها یک عنصر یا خالی باشد، آن را باز می‌گردانیم.

  • گام بازگشتی: آرایه را به دو زیرآرایه تقسیم کرده و هر یک را به صورت بازگشتی مرتب می‌کنیم.

 

حل مسائل با ساختارهای تودرتو

مسائل مانند محاسبه توالی فیبوناچی یا یافتن تعداد مسیرهای ممکن در شبکه‌های تودرتو نیز با استفاده از توابع بازگشتی حل می‌شوند.

مثال: توالی فیبوناچی


function fibonacci(n) {
  if (n <= 1) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
}

console.log(fibonacci(6)); // Output: 8

 

در این مثال:

  • پایه: اگر n برابر با 0 یا 1 باشد، مقدار آن را باز می‌گردانیم.

  • گام بازگشتی: برای محاسبه fibonacci(n), مقادیر fibonacci(n-1) و fibonacci(n-2) را به صورت بازگشتی محاسبه می‌کنیم.

 

مزایا و معایب توابع بازگشتی

مزایا

  • ساده‌سازی کد: توابع بازگشتی می‌توانند کد را ساده‌تر و قابل‌فهم‌تر کنند.

  • حل مسائل پیچیده: برای مسائل با ساختار درختی یا تودرتو بسیار مناسب هستند.

 

معایب

  • مصرف حافظه بالا: توابع بازگشتی می‌توانند به دلیل ذخیره وضعیت‌های موقتی در پشته، مصرف حافظه بالایی داشته باشند.

  • مشکل کارایی: در صورتی که بازگشت‌های زیادی وجود داشته باشد، می‌تواند منجر به کاهش کارایی شود. در این موارد، استفاده از تکنیک‌هایی مانند حفظ حالت (Memoization) یا تبدیل به الگوریتم‌های غیر بازگشتی مفید است.

 

تکنیک‌های بهینه‌سازی توابع بازگشتی

حفظ حالت (Memoization)

برای بهینه‌سازی توابع بازگشتی، می‌توانیم از تکنیک حفظ حالت استفاده کنیم که در آن نتایج محاسبه شده به حافظه کش (Cache) اضافه می‌شوند تا در صورت نیاز مجدد، از نتایج ذخیره شده استفاده شود.

مثال: فیبوناچی با حفظ حالت


const memo = {};

function fibonacci(n) {
  if (n in memo) return memo[n];
  if (n <= 1) return n;
  memo[n] = fibonacci(n - 1) + fibonacci(n - 2);
  return memo[n];
}

console.log(fibonacci(6)); // Output: 8

 

تبدیل به الگوریتم‌های غیر بازگشتی

در برخی موارد، می‌توانیم الگوریتم‌های بازگشتی را به الگوریتم‌های غیر بازگشتی تبدیل کنیم تا مصرف حافظه را کاهش دهیم و کارایی را بهبود بخشیم.

مثال: فیبوناچی غیر بازگشتی


function fibonacci(n) {
  let a = 0, b = 1, temp;

  for (let i = 0; i < n; i++) {
    temp = a;
    a = b;
    b = temp + b;
  }

  return a;
}

console.log(fibonacci(6)); // Output: 8

 

نتیجه‌گیری

توابع بازگشتی ابزار قدرتمندی در برنامه‌نویسی هستند که به شما این امکان را می‌دهند که مسائل پیچیده را با استفاده از حل مسائل مشابه به صورت کوچکتر حل کنید. با درک اصول پایه‌ای توابع بازگشتی و استفاده از تکنیک‌های بهینه‌سازی، می‌توانید کدهای خود را بهبود بخشید و مسائل پیچیده را به صورت مؤثر حل کنید. از توابع بازگشتی برای حل مسائل ساختاریافته، جستجو، مرتب‌سازی و مسائل تودرتو استفاده کنید و با رعایت نکات بهینه‌سازی، کارایی و مصرف حافظه را مدیریت کنید.

پرسش و پاسخ

نظری یافت نشد

مطالب مشابه

آموزش ساخت یک گالری تصویر با استفاده از جاوا اسکریپت: راهنمای گام به گام
3م آبان 1403

آموزش ساخت یک گالری تصویر با استفاده از جاوا اسکریپت: راهنمای گام به گام

مطالعه بیشتر
آموزش مدیریت Box Model و ترکیب اجزای آن با CSS: کنترل دقیق فاصله‌ها و ابعاد عناصر
5م شهریور 1402

آموزش مدیریت Box Model و ترکیب اجزای آن با CSS: کنترل دقیق فاصله‌ها و ابعاد عناصر

مطالعه بیشتر
کار با border و تنظیمات آن در CSS: مدیریت زوایای گرد با border-radius
9م آبان 1403

کار با border و تنظیمات آن در CSS: مدیریت زوایای گرد با border-radius

مطالعه بیشتر
درک و استفاده از Watchers در Vue.js | آموزش Watch با مثال کاربردی
28م آذر 1404

درک و استفاده از Watchers در Vue.js | آموزش Watch با مثال کاربردی

مطالعه بیشتر
آموزش mix-blend-mode و background-blend-mode در CSS: ترکیب رنگ‌ها و ایجاد افکت‌های جذاب
12م آبان 1403

آموزش mix-blend-mode و background-blend-mode در CSS: ترکیب رنگ‌ها و ایجاد افکت‌های جذاب

مطالعه بیشتر
آموزش استفاده از box-shadow و text-shadow در CSS: ایجاد سایه‌های زیبا و جذاب
11م آبان 1403

آموزش استفاده از box-shadow و text-shadow در CSS: ایجاد سایه‌های زیبا و جذاب

مطالعه بیشتر
درک Props و انتقال داده‌ها بین کامپوننت‌ها در Vue.js | آموزش کاربردی
24م آذر 1404

درک Props و انتقال داده‌ها بین کامپوننت‌ها در Vue.js | آموزش کاربردی

مطالعه بیشتر
مدیریت خطاها در Async/Await و Promises در جاوا اسکریپت: راهنمای کامل با مثال‌های عملی
30م مهر 1403

مدیریت خطاها در Async/Await و Promises در جاوا اسکریپت: راهنمای کامل با مثال‌های عملی

مطالعه بیشتر
آشنایی با انواع انتخاب‌گرها و تغییر پس‌زمینه با CSS: راهنمای جامع
4م شهریور 1402

آشنایی با انواع انتخاب‌گرها و تغییر پس‌زمینه با CSS: راهنمای جامع

مطالعه بیشتر
اصول پایه React.js: آشنایی با کامپوننت‌ها، وضعیت و رندرینگ
28م شهریور 1402

اصول پایه React.js: آشنایی با کامپوننت‌ها، وضعیت و رندرینگ

مطالعه بیشتر
جمع‌بندی، مرور مطالب و پروژه نهایی: ایجاد یک اپلیکیشن وب کامل با جاوا اسکریپت - راهنمای گام به گام
5م آبان 1403

جمع‌بندی، مرور مطالب و پروژه نهایی: ایجاد یک اپلیکیشن وب کامل با جاوا اسکریپت - راهنمای گام به گام

مطالعه بیشتر
آموزش Emit در Vue.js | انتقال رویداد از کامپوننت فرزند به والد
28م آذر 1404

آموزش Emit در Vue.js | انتقال رویداد از کامپوننت فرزند به والد

مطالعه بیشتر

تمامی حقوق معتلق به ناشر سایت است و کپی از آن پیگرد قانونی دارد