الگوریتم انتخاب
در علوم کامپیوتر، یک الگوریتم انتخاب، یک الگوریتم برای پیدا کردن kامین کوچکترین عدد در یک لیست است (به چنین عددی kامین مرتبه آماری گفته میشود). این الگوریتمها شامل پیدا کردن کمینه، بیشینه و میانهی عناصر است. الگوریتمهای انتخاب از
انتخاب با مرتبسازی
انتخاب ممکن است با مرتب کردن لیست و سپس استخراج عنصر دلخواه، به مرتبسازی تبدیل شود. این روش زمانی کارآمد است که به تعداد زیادی انتخاب از یک لیست نیاز باشد، در موردی که تنها یک بار مقداردهی میشود، یک مرتبسازی پرهزینه، همراه با چندین عمل استخراج کمهزینه انجام میشود. در حالت کلی، این روش نیازمند زمان
الگوریتمهای کمینه/بیشینه خطی
الگوریتمهای خطی، از لحاظ زمانی، برای پیدا کردن کمینهها یا بیشینهها این گونه کار میکنند که روی لیست تکرار میکنند و رد کمینه یا بیشینه تا هر بار نگه میدارند.
الگوریتم کلی انتخاب غیر خطی
با کمک ایدههای مورد استفاده در الگوریتمهای کمینه/بیشینه، ما میتوانیم یک الگوریتم کلی ساده، ولی ناکارامد برای پیدا کردن کوچکترین kامین یا بزرگترین k عنصر در یک لیست بدهیم، که نیاز به زمان
function select(list[1..n], k) for i from 1 to k minIndex = i minValue = list[i] for j from i+1 to n if list[j] <minValue minIndex = j minValue = list[j] swap list[i] and list[minIndex] return list[k]
دیگر مزیتهای این روش عبارتند از:
- بعد از پیدا کردن کوچکترین jامین عنصر، برای پیدا کردن کوچکترین kامین عنصر، تنها زمان (O(j + (k-j) یا برای k ≤ j تنها زمان مورد نیاز است.
- در رویهای که بر پایهٔ افراز است و به دسترسی تصادفی نیاز دارد، میتوان از دادهساختار لیست پیوندی برای پیادهسازی استفاده کرد.
الگوریتم کلی انتخاب بر پایهٔ افراز
یک الگوریتم فراگیر انتخاب که در عمل کارآمد است، اما در بدترین حالت کارایی ضعیفی دارد، توسط ابداعکنندهٔ مرتبسازی سریع، سی. اِی. آر هوار، ارائه شدهاست. این الگوریتم به نام الگوریتم انتخاب هوار یا انتخاب سریع شناخته میشود.
در مرتبسازی سریع، یک زیررَویه به نام افراز وجود دارد که میتواند در زمان خطی، یک لیست را به دو بخش left
و right
تقسیمبندی میکند که یک گروه کوچکتر از یک عنصر خاص و گروه دیگر بزرگتر یا مساوی آن عنصر خاص هستند. اینجا سودوکدی را میبینیم که یک افراز را برای عنصر list[pivotIndex]
اجرا میکند:
function partition(list, left, right, pivotIndex) pivotValue := list[pivotIndex] swap list[pivotIndex] and list[right] // Move pivot to end storeIndex := left for i from left to right if list[i] <pivotValue swap list[storeIndex] and list[i] increment storeIndex swap list[right] and list[storeIndex] // Move pivot to its final place return storeIndex
در مرتبسازی سریع، ما به صورت بازگشتی هر دو شاخه را در بهترین حالت در زمان
function select(list, left, right, k) if left = right // If the list contains only one element return list[left] // Return that element select pivotIndex between left and right pivotNewIndex := partition(list, left, right, pivotIndex) pivotDist := pivotNewIndex - left + 1 // The pivot is in its final sorted position, // so pivotDist reflects its 1-based position if list were sorted if pivotDist = k return list[pivotNewIndex] else if k <pivotDist return select(list, left, pivotNewIndex - 1, k) else return select(list, pivotNewIndex + 1, right, k - pivotDist)
مانند مرتبسازی سریع، کارایی الگوریتم به محوری که انتخاب میشود بستگی دارد. اگر محورهای نامناسب بهطور متوالی انتخاب شوند، این رویه به انتخاب بر پایهٔ کمینه، که قبلاً گفته شد، تنزل پیدا میکند و در نتیجه به زمان (O(n نیاز پیدا خواهد کرد.
الگوریتم کلی انتخاب به صورت خطی - الگوریتم میانهٔ میانهها
یک الگوریتم با بدترین زمان اجرای خطی برای حالت کلی انتخاب kامین بزرگترین عنصر توسط بلوم، فلوید، پرت، ریوست و ترجان در مقاله سال ۱۹۳۷ با نام «حدود زمانی برای انتخاب» منتشر شد. گاهی از این الگوریتم با نام BFPRT، که حروف اول نام خانوادگی نویسندگان آن است، یاد میشود. این الگوریتم بر اساس الگوریتم انتخاب سریع کار میکند و همچنین به نام الگوریتم میانه میانهها شناخته میشود.
هرچند انتخاب سریع بهطور میانگین دارای زمان خطی است، زمانی که محورهای ضعیفی استفاده شوند میتواند به زمان از درجه دوم نیاز پیدا کند (حالتی را در نظر بگیرید که در هر گام، محور در نزدیکی کوچکترین عنصر انتخاب شود). راه چاره برای اینکه آن را به
الگوریتم انتخاب لیست را به گروههایی شامل پنج عنصر تقسیم میکند. (فعلاً با عناصر باقیمانده کاری نداریم). سپس، برای هر گروه پنجتایی، میانه محاسبه میشود (اگر آن پنج مقدار داخل ثبّاتها بارگذاری شوند و مقایسه شوند، عملیات بهطور بالقوه بسیار سریع انجام میشود). (اگر مرتبسازی به صورت درجا صورت گیرد، این میانهها به یک بلوک پیوسته در لیست منتقل میشوند) انتخاب به صورت بازگشتی در این زیرلیستهای n/5 عنصری فراخوانده میشود تا مقدار واقعی میانه یافت شود. سرانجام، میانهٔ میانهها به عنوان محور انتخاب میشود.
ویژگیهای محور
محور انتخاب شده، از نیمی از عناصر لیست میانهها بزرگتر و از نیمهٔ دیگر کوچکتر است، بهطوریکه در هر نیمه
12 | 15 | 11 | 2 | 9 | 5 | 0 | 7 | 3 | 21 | 44 | 40 | 1 | 18 | 20 | 32 | 19 | 35 | 37 | ۳۹ | ||||||||||||||||||||
13 | 16 | 14 | 8 | 10 | 26 | 6 | 33 | 4 | 27 | 49 | 46 | 52 | 25 | 51 | 34 | 43 | 56 | 72 | ۷۹ | ||||||||||||||||||||
میانهها | 17 | 23 | 24 | 28 | 29 | 30 | 31 | 36 | 42 | 47 | 50 | 55 | 58 | 60 | 63 | 65 | 66 | 67 | 81 | ۸۳ | |||||||||||||||||||
22 | 45 | 38 | 53 | 61 | 41 | 62 | 82 | 54 | 48 | 59 | 57 | 71 | 78 | 64 | 80 | 70 | 76 | 85 | ۸۷ | ||||||||||||||||||||
96 | 95 | 94 | 86 | 89 | 69 | 68 | 97 | 73 | 92 | 74 | 88 | 99 | 84 | 75 | 90 | 77 | 93 | 98 | ۹۱ |
(راهنمای رنگهای جدول: قرمز = «(یکی از دو حالت ممکن) میانهٔ میانهها»، خاکستری = «شماره <قرمز»، سفید = «شماره> قرمز»)
در جدول بالا، برای وضوح بیشتر ۵-تاییها بر اساس میانه مرتب شدهاند. مرتبسازی چندتاییها لزومی ندارد، زیرا ما تنها به میانه برای استفاده به عنوان عنصر محور نیاز داریم.
توجه داشته باشید که تمام عناصر بالا/چپ خانهٔ قرمز (۳۰٪ از ۱۰۰ عنصر) کوچکتر از قرمز، و تمام عناصر پایین/راست خانهٔ قرمز (۳۰٪ دیگر از ۱۰۰ عنصر) بزرگتر از قرمز هستند.
اثبات زمان اجرای (O(n
محاسبهٔ میانه بهطور بازگشتی، در بدترین حالت از درجه خطی بیشتر نخواهد شد، زیرا لیست میانهها ۲۰٪ از اندازهٔ لیست است، در حالی که فراخوانی بازگشتی دیگر حداکثر روی ۷۰٪ لیست لیست اجرا میشود. بنا بر این زمان اجرا به صورت زیر میشود:
T(n) ≤ T(n/5) + T(7n/10) + O(n)
زمان (O(n ناشی از عمل افراز کردن است (ما هر عنصر را به تعداد دفعات ثابتی ملاقات میکنیم، تا آنها را به گروههای (O(n دستهبندی کنیم و هر میانه را در زمان (O(n به دست آوریم. به این ترتیب میتوان نشان داد که
منابع
- M. Blum, R.W. Floyd, V. Pratt, R. Rivest and R. Tarjan, "Time bounds for selection," J. Comput. System Sci. 7 (1973) 448-461.
- K. C. Kiwiel. On Floyd and Rivest’s SELECT Algorithm, Theoretical Computer Sci. 347 (2005) 214-238.
- دانلد کنوت. هنر برنامهنویسی رایانه, Volume 3: Sorting and Searching, Third Edition. Addison-Wesley, 1997. ISBN 0-201-89685-0. Section 5.3.3: Minimum-Comparison Selection, pp.207–219.
- توماس اچ کورمن، Charles E. Leiserson, رونالد ریوست، and کلیفورد استین. مقدمهای بر الگوریتمها, Second Edition. MIT Press and McGraw-Hill, 2001. ISBN 0-262-03293-7. Chapter 9: Medians and Order Statistics, pp.183–196. Section 14.1: Dynamic order statistics, pp.302–308.