AlgoVerse

مرتب‌سازی ادغامی

آرایه را از وسط دو نیم می‌کند، هر نیمه را به‌صورت بازگشتی مرتب می‌کند و دو نیمه‌ی مرتب را در هم ادغام می‌کند.

مرتب‌سازی ادغامی نمونه‌ی کلاسیک «تقسیم و حل» است:

ادامه‌ی توضیح ↓
ورودی:
n=8خروجی PDF

هشت عدد درهم: سه سطح تقسیم و هفت ادغام.

  1. def merge_sort(a):
  2. sort(a, 0, len(a) - 1)
  3. return a
  4. def sort(a, lo, hi):
  5. if lo >= hi:
  6. return
  7. mid = (lo + hi) // 2
  8. sort(a, lo, mid)
  9. sort(a, mid + 1, hi)
  10. merge(a, lo, mid, hi)
  11. def merge(a, lo, mid, hi):
  12. left = a[lo:mid + 1]
  13. right = a[mid + 1:hi + 1]
  14. i = 0
  15. j = 0
  16. k = lo
  17. while i < len(left) and j < len(right):
  18. if left[i] <= right[j]:
  19. a[k] = left[i]
  20. i = i + 1
  21. else:
  22. a[k] = right[j]
  23. j = j + 1
  24. k = k + 1
  25. while i < len(left):
  26. a[k] = left[i]
  27. i = i + 1
  28. k = k + 1
  29. while j < len(right):
  30. a[k] = right[j]
  31. j = j + 1
  32. k = k + 1

ناوردا: در حلقه‌ی merge، خانه‌های a[lo..k−1] کوچک‌ترین عضوهای left و right را به ترتیب دارند.

شروع اجرا

5021427314352667

درخت فراخوانی‌های بازگشتی

نارنجی پر = فراخوانی در حال اجرا · حاشیه‌ی نارنجی = هنوز روی پشته · خاکستری = تمام شده

متغیرهای محلی

نارنجی = در همین گام عوض شد

a list

52471326

Call stack

  1. merge_sort()خط 1
گام ۱ از ۲۴۵
خط سیاه = split · خط نارنجی = گام کلیدیcompare: 0/17 · split: 0/7 · copy: 0/7 · write: 0/24

    رشد تعداد عملیات با اندازه‌ی ورودی

    میانگین ۱۲ گراف تصادفی برای هر n (با seed ثابت). نشانگر توخالی = ورودی فعلی.

    • comparisons
    • write
    • ورودی فعلی (n=8)
    02040608046810121416n = تعداد عضوهای آرایهwritecomparisons
    نمایش به شکل جدول
    ncomparisonswrite
    44.88
    69.716
    815.324
    1022.234
    1230.144
    1437.754
    1645.364
    توضیح

    ایده

    مرتب‌سازی ادغامی نمونه‌ی کلاسیک «تقسیم و حل» است:

    1. تقسیم: بازه‌ی a[lo..hi] را از وسط (mid) دو نیم کن.
    2. حل: هر نیمه را با همین الگوریتم، به‌صورت بازگشتی مرتب کن. بازه‌ی یک‌عضوی خودبه‌خود مرتب است.
    3. ترکیب: دو نیمه‌ی مرتب را در هم ادغام کن.

    ادغام

    دو نیمه در left و right کپی می‌شوند. در هر گام، کوچک‌ترین عضو باقی‌مانده‌ی دو طرف با یک مقایسه پیدا و در a[k] نوشته می‌شود. وقتی یکی از دو طرف تمام شد، بقیه‌ی طرف دیگر بدون مقایسه کپی می‌شود.

    هزینه

    • عمق بازگشت log n است و در هر سطح، کل آرایه یک بار ادغام می‌شود، پس زمان در همه‌ی حالت‌ها O(n log n) است.
    • ادغام به آرایه‌ی کمکی نیاز دارد، پس حافظه‌ی اضافه O(n) است.
    • تعداد مقایسه‌ها به ورودی بستگی دارد: برای ۸ عضو بین ۱۲ (آرایه‌ی مرتب) و ۱۷ (ورودی درهم‌تنیده).

    پایداری

    با شرط left[i] ≤ right[j]، از دو عضو برابر همیشه آنکه از نیمه‌ی چپ آمده اول نوشته می‌شود، پس ترتیب عضوهای برابر حفظ می‌شود و مرتب‌سازی پایدار است.

    در trace به چه چیزی نگاه کنی

    • نوار آبی پشت میله‌ها بازه‌ی lo..hi فراخوانی جاری است.
    • «درخت فراخوانی‌های بازگشتی» زیر تصویر نشان می‌دهد کدام زیرمسئله در حال اجراست و کدام‌ها تمام شده‌اند.
    • با سطح جزئیات «هر دور حلقه» فقط گام‌های تقسیم را ببین؛ با «هر عملیات» ادغام را مقایسه‌به‌مقایسه دنبال کن.