منتشر شده در

نماد بزرگ O در جاوا اسکریپت

نویسندگان

نماد بزرگ O (O بزرگ)

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

نماد بزرگ O ، توابع را بر اساس نرخ رشد آنها طبقه‌بندی می‌کند: وظایفی که نرخ رشد یکسانی دارند در یک مرتبه در نظر گرفته می‌شوند. این نماد ریاضی، رفتار محدود کننده یک تابع را زمانی که استدلال به سمت یک مقدار خاص یا بی‌نهایت میل می‌کند، توصیف می‌کند. از نماد بزرگ O برای طبقه‌بندی الگوریتم‌ها بر اساس نحوه رشد زمان اجرا یا نیازهای فضایی آن‌ها با افزایش اندازه ورودی استفاده می‌شود. حرف O به این دلیل استفاده می‌شود که نرخ رشد یک تابع، مرتبه آن نیز نامیده می‌شود.

تکرار (Iteration)

حلقه For

for (let i = 0; i < n; i++) {
  console.log(i)
}

کد بالا n بار اجرا خواهد شد. پیچیدگی زمانی این کد O(n) است.

حلقه While

let i = 0
while (i < n) {
  console.log(i)
  i++
}

کد بالا n بار اجرا خواهد شد. پیچیدگی زمانی این کد O(n) است.

حلقه Do While

let i = 0
do {
  console.log(i)
  i++
} while (i < n)

کد بالا n بار اجرا خواهد شد. پیچیدگی زمانی این کد O(n) است.

بازگشتی (Recursion)

فاکتوریل

function factorial(n) {
  if (n === 0) {
    return 1
  }
  return n * factorial(n - 1)
}

کد بالا n بار اجرا خواهد شد. پیچیدگی زمانی این کد O(n) است.

فیبوناچی

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

کد بالا n بار اجرا خواهد شد. پیچیدگی زمانی این کد O(n) است.

جستجو (Searching)

function linearSearch(arr, value) {
  for (let i = 0; i < arr.length; i++) {
    if (arr[i] === value) {
      return i
    }
  }
  return -1
}

کد بالا n بار اجرا خواهد شد. پیچیدگی زمانی این کد O(n) است.

function binarySearch(arr, value) {
  let start = 0
  let end = arr.length - 1
  let middle = Math.floor((start + end) / 2)
  while (arr[middle] !== value && start <= end) {
    if (value < arr[middle]) {
      end = middle - 1
    } else {
      start = middle + 1
    }
    middle = Math.floor((start + end) / 2)
  }
  if (arr[middle] === value) {
    return middle
  }
  return -1
}

کد بالا log(n) بار اجرا خواهد شد. پیچیدگی زمانی این کد O(log(n)) است.

مرتب سازی (Sorting)

مرتب سازی حبابی (Bubble Sort)

function bubbleSort(arr) {
  for (let i = arr.length; i > 0; i--) {
    for (let j = 0; j < i - 1; j++) {
      if (arr[j] > arr[j + 1]) {
        let temp = arr[j]
        arr[j] = arr[j + 1]
        arr[j + 1] = temp
      }
    }
  }
  return arr
}

کد بالا n^2 بار اجرا خواهد شد. پیچیدگی زمانی این کد O(n^2) است.

مرتب سازی انتخابی (Selection Sort)

function selectionSort(arr) {
  for (let i = 0; i < arr.length; i++) {
    let lowest = i
    for (let j = i + 1; j < arr.length; j++) {
      if (arr[j] < arr[lowest]) {
        lowest = j
      }
    }
    if (i !== lowest) {
      let temp = arr[i]
      arr[i] = arr[lowest]
      arr[lowest] = temp
    }
  }
  return arr
}

کد بالا n^2 بار اجرا خواهد شد. پیچیدگی زمانی این کد O(n^2) است.

مرتب سازی درج (Insertion Sort)

function insertionSort(arr) {
  for (let i = 1; i < arr.length; i++) {
    let currentVal = arr[i]
    for (var j = i - 1; j >= 0 && arr[j] > currentVal; j--) {
      arr[j + 1] = arr[j]
    }
    arr[j + 1] = currentVal
  }
  return arr
}

کد بالا n^2 بار اجرا خواهد شد. پیچیدگی زمانی این کد O(n^2) است.

مرتب سازی ادغامی (Merge Sort)

function mergeSort(arr) {
  if (arr.length <= 1) return arr
  let mid = Math.floor(arr.length / 2)
  let left = mergeSort(arr.slice(0, mid))
  let right = mergeSort(arr.slice(mid))
  return merge(left, right)
}

function merge(left, right) {
  let results = []
  let i = 0
  let j = 0
  while (i < left.length && j < right.length) {
    if (left[i] < right[j]) {
      results.push(left[i])
      i++
    } else {
      results.push(right[j])
      j++
    }
  }
  while (i < left.length) {
    results.push(left[i])
    i++
  }
  while (j < right.length) {
    results.push(right[j])
    j++
  }
  return results
}

کد بالا n log(n) بار اجرا خواهد شد. پیچیدگی زمانی این کد O(n log(n)) است.

مرتب سازی سریع (Quick Sort)

function pivot(arr, start = 0, end = arr.length + 1) {
  let pivot = arr[start]
  let swapIdx = start
  function swap(array, i, j) {
    let temp = array[i]
    array[i] = array[j]
    array[j] = temp
  }
  for (let i = start + 1; i < arr.length; i++) {
    if (pivot > arr[i]) {
      swapIdx++
      swap(arr, swapIdx, i)
    }
  }
  swap(arr, start, swapIdx)
  return swapIdx
}

function quickSort(arr, left = 0, right = arr.length - 1) {
  if (left < right) {
    let pivotIndex = pivot(arr, left, right)
    quickSort(arr, left, pivotIndex - 1)
    quickSort(arr, pivotIndex + 1, right)
  }
  return arr
}

کد بالا n log(n) بار اجرا خواهد شد. پیچیدگی زمانی این کد O(n log(n)) است.

نکات برای نماد بزرگ O

  • عملیات‌های حسابی ثابت هستند
  • انتساب متغیر ثابت است
  • دسترسی به عناصر در یک آرایه (با استفاده از اندیس) یا شی (با استفاده از کلید) ثابت است
  • در یک حلقه، پیچیدگی برابر است با طول حلقه ضربدر پیچیدگی آنچه در داخل حلقه اتفاق می‌افتد

منابع