هنگامی که کار مرتب سازی شما شامل آرایه های بزرگ از اعداد کوچک است - مانند نمرات، سنین یا کدهای کاتالیک - الگوریتم های کلاسیک مقایسه مانند QuickSort یا MergeSort می توانند مانند بیش از حد قدرت را احساس کنند، این الگوریتم ها به جای ارسال ورودی های ساده در OLT (n log n) زمان اجرا می شوند، اما اگر دامنه مقادیر احتمالی محدود باشد، شما می توانید عناصر خطی (b) را با استفاده از DLT) به طور منظم تنظیم کنید: این اعداد و یا غیر مستقیم (F).

چگونه شمارش انواع کارها

شمارش مرتب از دانش استفاده می کند که ارزش های ورودی از یک محدوده کوچک (FLT:0) به جای مقایسه های جفت، آن را ایجاد یک هیستوگرام فرکانس از ارزش ها و سپس استفاده از آن هیستوگرام به جای هر عنصر در موقعیت مرتب شده آن.

رویکرد پایه: بازسازی مستقیم

ساده ترین نسخه ی شمارشگر در دو پاس کار می کند:

  1. فرکانس های کشور - از طریق آرایه ورودی و افزایش یک شمارنده برای هر مقدار که می بینید.
  2. اضافه کردن ورودی – از طریق آرایه ی مخالف از کوچک ترین به بزرگترین و برای هر مقدار، آن را به آرایه ورودی به عنوان چندین بار به عنوان شمارش آن را بنویسید.

این امر به نوعی خروجی می دهد اما در صورتی که شما یک کلید را در نظر بگیرید، آن را به صورت جداگانه ذخیره می کند.

تنوع پایدار: شمارش های محاسباتی

برای تثبیت تعداد، یک پاس سوم اضافه می کنیم:

  1. فرکانس ها را مثل قبل بشمارید.
  2. پس از این مرحله، حجم فرکانس را به یک آرایه شمارش جمعی تبدیل کنید. [۱۰] [۱۰]
  3. آرایه ورودی را به سمت معکوس (از عنصر آخر تا اول) تنظیم کنید، برای هر عنصر، از شمارش تجمعی خود برای پیدا کردن موقعیت آن در آرایه خروجی، قرار دادن آن و تخریب شمارش استفاده کنید.

از آنجا که ما به سمت معکوس حرکت می کنیم، نظم نسبی عناصر برابر حفظ می شود. آرایه خروجی از ورودی جدا است، بنابراین این نسخه از فضای اضافی O(n) برای خروجی استفاده می کند، در حالی که نسخه اولیه می تواند با نوشتن ورودی، به صورت مکان باشد.

پیاده سازی دسته بندی در C#

در زیر دو پیاده سازی C# وجود دارد: نسخه اصلی در محل (برای سناریوهایی که ثبات غیر ضروری است) و نسخه پایدار که از آرایه کمکی استفاده می کند، هر دو نیاز به دانستن حداکثر ارزش در پیشبرد دارند.

دسته بندی (غیرقابل بحث) شمارش

این نوع آرایه ورودی را به طور مستقیم بدون یک بافر خروجی اضافی، آن را کارآمد حافظه اما نه پایدار است.

public static void CountingSortBasic(int[] array, int maxValue)
{
 int[] counts = new int[maxValue + 1];

 // Count each element's frequency
 for (int i = 0; i < array.Length; i++)
 {
 counts[array[i]]++;
 }

 // Overwrite the original array in sorted order
 int index = 0;
 for (int value = 0; value <= maxValue; value++)
 {
 while (counts[value]-- > 0)
 {
 array[index++] = value;
 }
 }
}

دسته بندی پایدار شمارش

نسخه پایدار نیاز به یک آرایه خروجی از همان اندازه ورودی دارد، همچنین از شمارش تجمعی برای قرار دادن عناصر به درستی استفاده می کند.

public static int[] CountingSortStable(int[] array, int maxValue)
{
 int[] counts = new int[maxValue + 1];
 int[] output = new int[array.Length];

 // Step 1: Count occurrences
 foreach (int num in array)
 {
 counts[num]++;
 }

 // Step 2: Transform counts to cumulative counts
 for (int i = 1; i <= maxValue; i++)
 {
 counts[i] += counts[i - 1];
 }

 // Step 3: Build the output array (iterate input in reverse for stability)
 for (int i = array.Length - 1; i >= 0; i--)
 {
 int value = array[i];
 output[counts[value] - 1] = value;
 counts[value]--;
 }

 return output;
}

در هر دو پیاده سازی، بزرگترین عدد صحیحی است که در آرایه ظاهر می شود، اگر حداکثر واقعی ناشناخته باشد، می توانید آن را با یک اسکن مقدماتی (O(n) محاسبه کنید.

تحلیل پیچیدگی

[به جز این که از آن استفاده کنید، از آن بهره مند شوید و از آن بهره مند شوید. ]

  • [[۱] [۱۰] [۱۰] [۱۰] [۱۰] [[۱۰]] [[۱۰]] [[۱۰]]] [[۱۰]]] [۱] [۱]] [۱]] [۱]] [۱]] [۱] [۱]] [۱]] [۱] [۱]] [۱] [۱]] [۱]] [۳۲] [۲] [۱] [۱] [۲] [۲] [۲] [۲]] [۲] [۲]] [۲] [۲]]]] [۲] [۲]]] [۲] [۲]]]]] [۲]]]]]] [۲] [۲] [۲] [۲] [۱] [۲] [۲] [۲] [۲] [۲] [۲] [۲]]]] [۲] [۲] [۲] [۲]]]] [۲] [۲] [۱]] [۱] [۱] [۲] [۲] [۲] [۲] [۲] [۲] [۲] [۲] [۲]] [۲] [۲
  • Space: نسخه پایه از فضای اضافی O(k) برای آرایه شمارش استفاده می کند. نسخه پایدار از O (n + k) استفاده می کند زیرا همچنین آرایه خروجی را اختصاص می دهد.این باعث می شود شمارش مرتب نامناسب زمانی که دامنه بزرگتر از تعداد موارد است.
  • Comparison با انواع دیگر: انواع مقایسه مانند QuickSort و MergeSort نیاز به حداقل O (n log n) مقایسه برای k کوچک (به عنوان مثال، k <؛ 10,000 و n >؛ 100،000)، شمارش مرتب می تواند سفارشات از اندازه سریع تر.

تنوع و گسترش

مدیریت Integers منفی

شمارش مرتب به طور بومی با اعداد غیر منفی کار می کند تا مقادیر منفی را مدیریت کند، کل محدوده را تغییر دهد، به عنوان مثال، اگر اعداد از 1000 تا 1000 باشد، هر عنصر را با +1000 تنظیم کنید، آرایه شمارش سپس اندازه (FLT:5).

public static int[] CountingSortWithNegative(int[] array)
{
 if (array.Length == 0) return array;

 int min = array.Min();
 int max = array.Max();
 int range = max - min + 1;

 int[] counts = new int[range];
 int[] output = new int[array.Length];

 foreach (int num in array)
 counts[num - min]++;

 for (int i = 1; i < range; i++)
 counts[i] += counts[i - 1];

 for (int i = array.Length - 1; i >= 0; i--)
 {
 int value = array[i];
 output[counts[value - min] - 1] = value;
 counts[value - min]--;
 }

 return output;
}

دانلود فیلم برداری Non Integer Keys

شمارش مرتب نیاز به کلید های صحیح دارد.اگر داده های شما شامل کاراکترهای ( بایت) یا تکرارهایی باشد که می توانند به اعداد صحیح برسند، شما هنوز هم می توانید آن را برای اشیاء بزرگتر اعمال کنید، می توانید یک کلید صحیح استخراج کنید و اشیاء را به ترتیب مرتب کنید – این دقیقاً این است که چگونه رای ها اغلب از دسته بندی شمارش به عنوان زیرکان داخلی آن استفاده می کنند.

بازی Radix Collection

راکس مرتب کردن دیجیتال (یا بیت) را به صورت جداگانه پردازش می کند و شمارش مرتب انتخاب طبیعی برای هر پاس زمانی است که پایه (به عنوان مثال، 10 یا 256) کوچک است.این اجازه می دهد تا به صورت خطی به شکل گیری صحیح های خودسرانه، نه فقط کوچک است.

بررسی های عملی در C#

حافظه فوت و k بزرگ

بزرگترین سقوط یک آرایه شمارش بزرگتر از حافظه موجود است.[۱] برای مثال، مرتب کردن ۱۰۰۰ عنصر با طیف وسیعی از ۱٫۰۰۰ زباله فضا همیشه تأیید کنید که k سفارش های بزرگ تر از n است.

Parallelism و Span <؛ T>

برای آرایه های بسیار بزرگ، می توانید فاز شمارش را با تقسیم ورودی در سراسر رشته ها همگام سازی کنید.هر رشته بخش خود را به یک آرایه خصوصی می پردازد و سپس نتایج جزئی جمع آوری می شود.(FLT:7 و برای شمارش آرایه می تواند تخصیص توده را کاهش دهد زمانی که دامنه کوچک است.

دانلود زیرنویس فارسی فیلم Edge Cases

  • [در این باره] [[[۱]]] [۱۰] [۱]] [۱۰]] [۱]] [۱] [۱] [۱۰]] [۱]] [۱] [۱۰] [۱] [۱۰] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۶] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱۰] [۱۰] [۱۰] [۱۰] [۱۰] [۱] [۱۰] [۱۰] [۱] [۱] [۱] [۱] [۱] [۱۰] [۱۰] [۱] [۱] [۱] [۱] [۱] [۱] [۱۰] [۱
  • [در این باره] [[[۱]] [۱۰] [۱]] [۱۰]] [۱۰]] [۱]] [۱۰] [۱]] [۱۰]] [۳] [۱]] [۱۰] [۱]] [۱۰] [۳] [۹] [۱]] [۹] [۹] [۹] [۹] [۱] [۹] [۹] [۹] [۹] [۹] [۹] [۹] [۹] [۹] [۹] [۹] [۱] [۱] [۱] [۹] [۹] [۹] [۹] [۹] [۹] [۱] [۱] [۱] [۱] [۱] [۳] [۹] [۹] [۹] [۹] [۹] [۹] [۹] [۹] [۹] [۹] [۹] [۳] [۳] [۳] [۹] [۹] [۹] [۹] [۳] [۱] [۹] [۹] [۹] [۹] [۹] [۹] [۹] [۹] [۹] [۹] [۹] [۹
  • تمام ارزش های یکسان - آرایه شمارش دارای یک ورودی غیر صفر است؛ بازسازی در O (n) اجرا می شود.
  • داده های پراکنده (FLT 1) - شمارش مرتب ناکارآمد می شود زیرا اکثر ورودی های شمارش صفر است.

توصیه های عملکردی

استفاده از دسته بندی زمانی که شما می دانید که اعداد ورودی به محدوده کوچکی می رسند (به عنوان مثال، نمرات 0 تا 100، سنین 0 تا 120 یا کدهای خطا 0- 255) برای محدوده های بزرگتر، رایکس مرتب یا ترکیبی که به QuickSort برای پارتیشن های بلند برد باز می شود.

وقتی از دسته بندی استفاده می کنیم (و وقتی که نمی خواهید)

SituationRecommendation
Small integer range (k ~ n)Excellent choice – linear time, simple code.
Large integer range (k >> n)Avoid – memory waste and O(k) overhead.
Need stabilityUse the stable variant (cumulative counts).
Strings or objectsConsider Radix Sort or a comparison sort.
Extremely large datasetsCounting Sort can be parallelized; but watch memory.

اندازه گیری و عملکرد

در یک معیار معمولی با n = 000 و k = 1000، شمارش مرتب در حدود 20 تا 30 درصد از زمان گرفته شده توسط (که از درون منافذ استفاده می کند) شکاف به عنوان کاهش می یابد. زیر یک مقایسه تقریبی (زمان های اجرایی در یک CPU مدرن با .NET 8):

n = 1,000,000 | k = 1,000
Array.Sort (QuickSort variant) : 68 ms
CountingSortBasic : 12 ms
CountingSortStable : 18 ms

هنگامی که دامنه به ۱۰۰۰۰ رشد می کند، شمارش مرتب هنوز برنده می شود، اما حاشیه باریک می شود. k = ۱۰۰،۰۰۰، صفحه حافظه ( ۴۰۰ کیلوبایت برای آرایه شمارش) شروع به آسیب رساندن به حافظه CPU می کند و عملکرد می تواند کاهش یابد.

نتیجه گیری

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

در این باره، با |Wikipedia]] در ، ، [[FLT:Microsoft docs on ArraySort]] و یک راهنمای عملی از GeeksforGeeksGeeks forGeeks[FLT5:5] مشورت کنید.