مرتبسازی جدولی
بهجای جابهجا کردن رکوردهای بزرگ، جدولی از اندیسها را مرتب میکند و بعد هر رکورد را فقط یک بار، با دنبال کردن دورهای جایگشت، سر جایش میبرد.
اگر هر رکورد بزرگ باشد (مثلاً پروندهی یک دانشجو)، جابهجا کردنش گران است. مرتبسازی جدولی دو گام دارد:
ادامهی توضیح ↓- زمان:
O(n²) comparisons, O(n) record moves - حافظه:
O(n) - هوروویتز–ساهنی، فصل ۷
شش رکورد؛ جدول اندیسها مرتب میشود و بعد یک دور چهارتایی دنبال میشود (۱۴ و ۵۰ از قبل سر جایشاناند).
def table_sort(a):n = len(a)# 1. Sort a table of indices instead of the (large) records themselves.t = list(range(n))for i in range(1, n):j = iwhile j > 0 and a[t[j - 1]] > a[t[j]]:t[j - 1], t[j] = t[j], t[j - 1]j = j - 1# 2. Move each record once, following the cycles of the permutation t.for i in range(n):if t[i] == i:continuetemp = a[i]j = iwhile t[j] != i:k = t[j]a[j] = a[k]t[j] = jj = ka[j] = tempt[j] = jreturn a
شروع اجرا
متغیرهای محلی
نارنجی = در همین گام عوض شد
a list
351412422650
Call stack
- table_sort()خط 1
گام ۱ از ۷۳
رشد تعداد عملیات با اندازهی ورودی
میانگین ۱۲ گراف تصادفی برای هر n (با seed ثابت). نشانگر توخالی = ورودی فعلی.
- swap_index
- move
- ورودی فعلی (n=6)
نمایش به شکل جدول
| n | swap_index | move |
|---|---|---|
| 4 | 3.3 | 2.2 |
| 6 | 7.6 | 4.1 |
| 8 | 12 | 5 |
| 10 | 21.3 | 6.3 |
| 12 | 29.4 | 9.3 |
توضیح
ایده
اگر هر رکورد بزرگ باشد (مثلاً پروندهی یک دانشجو)، جابهجا کردنش گران است. مرتبسازی جدولی دو گام دارد:
- مرتب کردن جدول اندیسها: آرایهی
tاز اندیسها را طوری مرتب میکنیم کهa[t[0]] ≤ a[t[1]] ≤ …. رکوردها اصلاً تکان نمیخورند؛ فقط عددهای کوچکtجابهجا میشوند. (گاهی همین کافی است: رکوردها را به ترتیبtبخوان.) - جابهجایی فیزیکی:
tیک جایگشت است و هر جایگشت از چند دور ساخته شده. در هر دور، یک رکورد را کنار میگذاریم، بقیه را هر کدام یک بار سر جای نهاییشان میبریم و رکورد کنارگذاشته را در آخرین جای خالی میگذاریم.
هزینه
گام ۲ هر رکورد را حداکثر یک بار جابهجا میکند: O(n) جابهجایی رکورد، در برابر O(n²) در مرتبسازی درجی معمولی.
در trace به چه چیزی نگاه کنی
- در گام ۱ میلهها ثابتاند و فقط
tدر پنل حافظه عوض میشود؛ در گام ۲ میلهها دور به دور سر جایشان میروند.