یافتن میانه بدون مرتب‌سازی کامل: الگوریتم‌های انتخاب زمان-خطی

یافتن k-امین کوچک‌ترین عنصر در یک آرایه مرتب‌نشده نیازمند هزینه کامل Θ(n log n) مرتب‌سازی نیست؛ می‌تواند در زمان خطی انجام شود. این راهنمای جامع مورد بدیهی یافتن حداقل یا حداکثر، یک الگوریتم انتخاب تصادفی ظریف با زمان مورد انتظار خطی، و یک الگوریتم قطعی پیچیده‌تر که زمان خطی را حتی در بدترین‌حالت تضمین می‌کند را پوشش می‌دهد.

میانه میانه‌هاآمار ترتیبیالگوریتم انتخاب

~7 min read · Updated Sep 7, 2026

مسئله انتخاب

i-امین آمار ترتیبی یک مجموعه از n عنصر، صرفاً i-امین کوچک‌ترین عنصر در آن مجموعه است. Selection Problem (مسئله انتخاب) می‌پرسد: با داشتن یک آرایه مرتب‌نشده و یک ایندکس i، آمار ترتیبی i-ام را پیدا کن. موارد خاص شامل یافتن حداقل (i = 1)، حداکثر (i = n)، و میانه (i = ⌈n/2⌉) است.

یک رویکرد ساده ابتدا آرایه را مرتب می‌کند، با استفاده از یکی از الگوریتم‌های Θ(n log n) که پیش‌تر در این مجموعه بحث شد، سپس صرفاً به نتیجه مرتب‌شده ایندکس می‌زند. این کار می‌کند اما کار بیشتری از نیاز انجام می‌دهد — مرتب‌سازی مسئله‌ای اساساً سخت‌تر از یافتن یک آمار ترتیبی خاص را حل می‌کند. این مقاله الگوریتم‌هایی که انتخاب را مستقیماً حل می‌کنند، بدون مرتب‌سازی کامل، پوشش می‌دهد.

یافتن حداقل یا حداکثر: یک پیمایش خطی بدیهی

یافتن هرکدام از حداقل یا حداکثر به‌تنهایی فقط نیازمند یک عبور واحد در سراسر آرایه است، که هر عنصر را با کاندید فعلی مقایسه می‌کند.

MINIMUM(A, n):
  min = A[1]
  برای i = 2 تا n:
      اگر A[i] < min:
          min = A[i]
  min را برگردان

این واضحاً در زمان Θ(n) اجرا می‌شود، و اثبات بهینه‌بودن آن آسان است: هر الگوریتمی که حداقل را پیدا می‌کند باید حداقل یک‌بار هر عنصر را بررسی کند، چون یک عنصر بررسی‌نشده همیشه می‌تواند در نهایت حداقل واقعی از آب دربیاید، که کران پایین متناظر Ω(n) را می‌دهد.

یک پرسش جالب‌تر یافتن هم‌زمان حداقل و حداکثر است. یک رویکرد ساده دو عبور جداگانه انجام می‌دهد، و در مجموع از 2n - 2 مقایسه استفاده می‌کند. یک رویکرد ماهرانه‌تر عناصر را به‌صورت جفتی پردازش می‌کند، ابتدا هر جفت را با یکدیگر مقایسه می‌کند، سپس فقط برنده را با حداکثر فعلی و فقط بازنده را با حداقل فعلی مقایسه می‌کند، و کل را به تقریباً 3n/2 مقایسه کاهش می‌دهد — یک بهبود فاکتور-ثابت معنادار.

انتخاب تصادفی: زمان مورد انتظار خطی

یافتن یک آمار ترتیبی دلخواه i جالب‌تر است. RANDOMIZED-SELECT ایده افرازبندی را از quicksort تصادفی، که پیش‌تر در این مجموعه بحث شد، اقتباس می‌کند، اما با یک تفاوت حیاتی: پس از افرازبندی، فقط به یک سمت بازگشت می‌کند نه هر دو.

RANDOMIZED-SELECT(A, p, r, i):
  اگر p == r:
      A[p] را برگردان
  q = RANDOMIZED-PARTITION(A, p, r)
  k = q - p + 1   // تعداد عناصر در سمت پایین، شامل محور
  اگر i == k:
      A[q] را برگردان         // محور دقیقاً پاسخ است
  در غیر این صورت اگر i < k:
      RANDOMIZED-SELECT(A, p, q - 1, i) را برگردان   // فقط چپ بازگشت کن
  در غیر این صورت:
      RANDOMIZED-SELECT(A, q + 1, r, i - k) را برگردان // فقط راست بازگشت کن

از آنجا که الگوریتم فقط به یک سمت افراز بازگشت می‌کند نه هر دو، از کار بازگشتی اضافه‌ای که هزینه کل quicksort را Θ(n log n) کرد اجتناب می‌کند. از نظر شهودی، این اندازه مسئله را در هر گام نصف (یا بیشتر) می‌کند در حالی که فقط کار افرازبندی Θ(n) در گام فعلی انجام می‌دهد، نه کار Θ(n) در هر سطح همان‌طور که quicksort در سراسر هر دو شاخه انجام می‌دهد.

تحلیل زمان اجرای مورد انتظار

با استفاده از همان سبک تحلیل احتمالاتی که پیش‌تر در این مجموعه بحث شد، می‌توان نشان داد زمان اجرای مورد انتظار برآورده می‌کند:

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

E[T(n)] ≤ E[T(n/2)] + O(n)

حل این رابطه بازگشتی، مشابه در شکل با
حالت ۲ روش استاد که پیش‌تر در این مجموعه بحث شد:

E[T(n)] = O(n)

یک استخراج دقیق‌تر، که همه تقسیم‌های افراز ممکن وزن‌دهی‌شده با احتمال‌شان را در نظر می‌گیرد، تأیید می‌کند این کران O(n) مورد انتظار صرف‌نظر از مقدار i درخواست‌شده برقرار است، شامل بدترین حالات یافتن حداقل، حداکثر، یا میانه.

مانند quicksort تصادفی، این الگوریتم همچنان یک بدترین‌حالت Θ(n²) دارد — برای مثال، اگر محور تصادفی انتخاب‌شده اتفاقاً به‌طور مکرر کوچک‌ترین یا بزرگ‌ترین عنصر باقی‌مانده باشد — اما این بدترین‌حالت در سراسر انتخاب‌های تصادفی به‌طور ناچیزی نامحتمل است، که الگوریتم را به‌طور قابل‌اعتماد در عمل سریع می‌کند.

انتخاب قطعی: زمان خطی تضمین‌شده

برای اپلیکیشن‌هایی که به یک کران زمان خطی بدترین‌حالت تضمین‌شده نیاز دارند، بدون هیچ وابستگی به تصادفی‌سازی، یک الگوریتم قطعی جزئی‌تر وجود دارد، که اغلب Median-of-Medians (میانه میانه‌ها) نامیده می‌شود. نوآوری کلیدی آن یک روش ماهرانه برای انتخاب یک محور است که تضمین می‌کند یک افراز نسبتاً متوازن تولید می‌کند، صرف‌نظر از اینکه ورودی چگونه باشد.

SELECT(A, n, i):
  اگر n ≤ یک ثابت کوچک (مثلاً 5):
      A را مستقیماً مرتب کن و عنصر i-ام را برگردان
  
  A را به ⌈n/5⌉ گروه از 5 عنصر هرکدام تقسیم کن
  میانه هر گروه را پیدا کن (با مرتب‌سازی هر گروه کوچک)
  به‌طور بازگشتی میانه این ⌈n/5⌉ میانه را پیدا کن — آن را x بنام
  
  A را حول x افراز کن
  فرض کن k = رتبه x در آرایه افرازشده
  اگر i == k:
      x را برگردان
  در غیر این صورت اگر i < k:
      SELECT را به‌طور بازگشتی روی سمت پایین برای عنصر i-ام فراخوانی کن
  در غیر این صورت:
      SELECT را به‌طور بازگشتی روی سمت بالا برای عنصر (i-k)-ام فراخوانی کن

بینش حیاتی این است که میانه-میانه‌ها x تضمین می‌شود از حداقل تقریباً 3n/10 عنصر بزرگ‌تر و از حداقل تقریباً 3n/10 عنصر کوچک‌تر باشد، که تضمین می‌کند افراز هرگز خیلی نامتوازن نباشد، صرف‌نظر از ورودی خاص.

چرا رابطه بازگشتی به زمان خطی حل می‌شود

الگوریتم دو فراخوانی بازگشتی انجام می‌دهد: یکی روی ⌈n/5⌉ عنصر برای یافتن میانه میانه‌ها، و یکی روی حداکثر تقریباً 7n/10 عنصر برای گام اصلی انتخاب بازگشتی، به‌علاوه کار O(n) برای گروه‌بندی، مرتب‌سازی گروه‌های کوچک، و افرازبندی.

T(n) ≤ T(⌈n/5⌉) + T(7n/10) + O(n)

حل این رابطه بازگشتی با استفاده از روش substitution که پیش‌تر در این مجموعه بحث شد، با حدس T(n) ≤ cn:

T(n) ≤ c⌈n/5⌉ + c(7n/10) + O(n)
     ≤ cn/5 + c + 7cn/10 + O(n)
     = 9cn/10 + c + O(n)

این ≤ cn است به‌شرط انتخاب c به‌اندازه کافی بزرگ
که جمله O(n) و +c
توسط باقی‌مانده cn/10 جذب شوند

بنابراین T(n) = O(n)

این تأیید می‌کند الگوریتم میانه-میانه‌ها به زمان اجرای بدترین‌حالت Θ(n) دست می‌یابد — یک تضمین زمان-خطی واقعاً قطعی، برخلاف تضمین زمان-مورد-انتظار الگوریتم تصادفی.

مقایسه دو الگوریتم انتخاب

Randomized Select:
  - زمان مورد انتظار: O(n)
  - زمان بدترین‌حالت: O(n²)، هرچند بسیار نامحتمل
  - پیاده‌سازی ساده، فاکتورهای ثابت کوچک
  - در بیشتر موقعیت‌های عملی ترجیح داده می‌شود

Median-of-Medians (Select قطعی):
  - زمان بدترین‌حالت: O(n)، تضمین‌شده
  - پیاده‌سازی پیچیده‌تر، فاکتورهای ثابت بزرگ‌تر
  - وقتی تضمین‌های بدترین‌حالت ضروری‌اند ترجیح داده می‌شود،
    مانند در سیستم‌های بلادرنگ یا محیط‌های خصمانه

چرا الگوریتم‌های انتخاب فراتر از میانه اهمیت دارند

انتخاب کارآمد کاربردهای عملی در سراسر علوم کامپیوتر دارد: یافتن صدک‌ها در تحلیل آماری، شناسایی k-امین کوتاه‌ترین مسیر در مسیریابی شبکه، و به‌عنوان یک زیرروال درون الگوریتم‌های دیگر، شامل یک نوع استفاده‌شده برای انتخاب محورهای بهتر برای خود quicksort در پیاده‌سازی‌های حساس به کارایی. این واقعیت که این مسئله یک راه‌حل واقعاً زمان-خطی می‌پذیرد، دقیقاً سریع‌تر از کران پایین Ω(n log n) که برای مرتب‌سازی کامل اعمال می‌شود، یک اصل مهم در طراحی الگوریتم را نشان می‌دهد: درک دقیق اینکه یک مسئله واقعاً به چه چیزی نیاز دارد، به‌جای استفاده از آشناترین ابزار، اغلب یک راه‌حل اساساً

Written & researched by Dr. Shahin Siami

Related Articles

الگوریتم‌های نظریه اعداد: GCD، توان‌رسانی پیمانه‌ای، و RSA

رمزنگاری مدرن و بی‌شمار کاربرد الگوریتمی به تعداد کمی الگوریتم ظریف نظریه اعداد متکی است. این راهنمای جامع الگوریتم اقلیدس برای محاسبه بزرگ‌ترین مقسوم‌علیه مشترک، توان‌رسانی پیمانه‌ای سریع برای محاسبه کارآمد توان‌های بزرگ، و پایه ریاضی رمزنگاری RSA، یکی از پراستفاده‌ترین سیستم‌های رمزنگاری در جهان، را پوشش می‌دهد.

Continue

اصول هندسه محاسباتی: جهت، تقاطع پاره‌خط، و پوسته محدب

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

Continue

الگوریتم‌های تطبیق رشته: جستجوی ساده، Rabin-Karp، و فراتر از آن

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

Continue

الگوریتم‌های تقریبی: نزدیک‌شدن اثبات‌پذیر به بهینه برای مسائل سخت

وقتی یک مسئله NP-complete اثبات شود، یک راه‌حل کارآمد دقیق بعید است وجود داشته باشد، اما این به معنای رهاکردن کامل مسئله نیست. این راهنمای جامع الگوریتم‌های تقریبی را توضیح می‌دهد، که تضمین بهینه‌بودن را در ازای تضمین کارایی معامله می‌کنند، و مسائل پوشش رأس و فروشنده دوره‌گرد را به‌عنوان مثال‌های کلاسیک با نسبت‌های تقریبی اثبات‌پذیر پوشش می‌دهد.

Continue

NP-Completeness توضیح داده شده: P، NP، و چرا برخی مسائل در برابر راه‌حل‌های کارآمد مقاومت می‌کنند

برخی مسائل برای دهه‌ها در برابر هر تلاشی برای یک الگوریتم کارآمد مقاومت کرده‌اند، با این حال هیچ‌کس اثبات نکرده یک راه‌حل کارآمد غیرممکن است. این راهنمای جامع کلاس‌های P و NP، مفهوم تقلیل‌های زمان-چندجمله‌ای مورد استفاده برای مقایسه سختی مسئله، و چگونگی اینکه اثبات NP-complete بودن یک مسئله شواهد قوی، هرچند نه اثبات، فراهم می‌کند که هیچ الگوریتم کارآمدی وجود ندارد را توضیح می‌دهد.

Continue

جریان بیشینه: فورد-فالکرسون و قضیه برش-کمینه/جریان-بیشینه

مسائل جریان بیشینه بیشترین توان عملیاتی ممکن از میان یک شبکه با اتصالات محدود-به-ظرفیت را مدل‌سازی می‌کنند، از لوله‌های آب تا شبکه‌های داده. این راهنمای جامع شبکه‌های جریان را معرفی می‌کند، روش فورد-فالکرسون برای یافتن جریان بیشینه با استفاده از مسیرهای تقویتی را مرور می‌کند، و قضیه ظریف برش-کمینه/جریان-بیشینه که دو مسئله به‌ظاهر متفاوت را به یکی متصل می‌کند را توضیح می‌دهد.

Continue