เมื่องานเก็บของคุณเกี่ยวข้องกับ จํานวนเต็มขนาดเล็ก -- เช่น เกรด อายุ หรือรหัสตัวเลข -- อัลกอริทึมแบบคลาสสิคแบบ Superet หรือ CommortSort สามารถรู้สึกเกินเหตุได้ อัลกอริทึมเหล่านี้จะทํางานใน O(n LOD) ชั่วคราว แต่ถ้าช่วงของค่าต่าง ๆ ที่เป็นไปได้มีจํากัด คุณสามารถเรียงลําดับได้ตามตัวเลขแบบ On+ k) เวลา [FLT: 0] การเรียงลําดับ [FLTT1] เรียงลําดับนี้ไม่สามารถเพิ่มความเสมอภาคระหว่างการเกิดได้
วิธี นับ ว่า ดี อย่าง ไร
การนับ มีประโยชน์ในการรู้ว่าค่านําเข้าเป็นจํานวนเต็มที่ดึงมาจากช่วงเล็ก ๆ [FLT: 0] แทนการเปรียบเทียบแบบคู่ มันจะสร้างกราฟแสดงความถี่ของค่า จากนั้นใช้กราฟแสดงความถี่นั้นในการจัดองค์ประกอบแต่ละตัวให้อยู่ในตําแหน่งที่ถูกต้อง
วิธี การ ขั้น พื้น ฐาน: การ ปรับ ปรุง แก้ไข โดย ตรง
รุ่นที่ง่ายที่สุดของการนับเรียงลําดับการทํางานในสองผ่าน:
- [FLT: 0] ความถี่แบบไม่ต่อเนื่อง - สแกนผ่านอาร์เรย์นําเข้า และเพิ่มตัวนับของแต่ละค่าที่คุณเห็น
- [FLT: 0] เขียนค่าเข้า – เดินผ่านแนววัดจากค่าน้อยที่สุดเป็นค่ามากที่สุด และแต่ละค่า ให้เขียนกลับไปที่อาร์เรย์นําเข้าเป็นจํานวนเท่าของจํานวน
นี้จะให้ผลลัพธ์ที่เรียงลําดับแต่ไม่ [FLT: 0] ไม่ [FLT: 1) รักษาลําดับสัมพัทธ์ของแบบซ้ํา (ไม่เสถียร). ความมั่นคง (ไม่คงที่). องค์ประกอบสําคัญเมื่อคุณเรียงลําดับของกุญแจ ในขณะที่รักษาลําดับเดิมของบันทึกที่เท่ากัน. ความเสถียรที่อธิบายไว้ต่อไปคืออันที่นิยมใช้บ่อยที่สุดในการปฏิบัติ
นก นางแอ่น ที่ สง่า งาม: นก กระสา
เพื่อให้นับเสถียร เราเพิ่มผ่านที่สาม
- นับความถี่เป็นก่อนหน้านี้
- เปลี่ยนจํานวนลําดับความถี่เป็นลําดับสะสม หลังจากขั้นตอนนี้ จะมีจํานวนสมาชิก ⁇ [FLT: 0] [FLT: 0] .
- เพิ่มจํานวนรายการในลําดับการใส่เข้าไปใหม่ (จากธาตุสุดท้ายไปตัวแรก) สําหรับแต่ละธาตุ ให้ใช้จํานวนสะสมของธาตุเพื่อหาตําแหน่งของอาร์เรย์, วางมัน, และลดจํานวนลง
เนื่องจากเราเดินทางกลับด้าน ลําดับสัมพัทธ์ของธาตุที่เท่ากัน จึงถูกเก็บรักษาไว้ ลําดับของผลลัพธ์จะแยกออกจากค่านําเข้า ดังนั้นรุ่นนี้จึงใช้พื้นที่เพิ่มเติมของผลลัพธ์ (in) ในขณะที่รุ่นพื้นฐานสามารถเรียงลําดับได้โดยการเขียนค่าข้อมูลมากกว่า
การนับแบบเติมความจุใน C#
ด้านล่างนี้มีการใช้ C# สองแบบ: รุ่นพื้นฐาน in-place (สําหรับสถานการณ์ที่ความมั่นคงไม่จําเป็น) และรุ่นคงที่ที่ใช้อาร์เรย์เสริม ทั้งสองต้องการค่าสูงสุดก่อน
พื้นฐาน (nongable) การนับเรียงลําดับ
รายการ ที่ ใช้ ใน การ ใส่ ของ คุณ จะ มี ค่า มาก ขึ้น โดย ไม่ ต้อง ใส่บัฟเฟอร์ เข้า ไป โดย ไม่ ต้อง ใส่ ไว้ ใน รายการ ที่ ออก มา.
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;
}
ในการจัดทําทั้งสองแบบ [FLT: 4] เป็นจํานวนเต็มที่มากที่สุดที่ปรากฏในแนวเรียง หากค่าสูงสุดจริงไม่รู้จัก คุณสามารถคํานวณมันด้วยการคํานวณแบบพรีเมชัน (O) รุ่นคงที่จะคืนค่าลําดับใหม่ โดยปล่อยการไม่เปลี่ยนแปลงเดิมไว้
การวิเคราะห์ความซับซ้อน
ให้ [FLT: 0] n เป็นจํานวนสมาชิก และ k = Maxx – Min + 1 (ช่วงของค่าที่เป็นไปได้).
- [FLT: 0] เวลา: การนับแยกดําเนินการใน O(n+k) เวลา. The Counting phat is O(n), นําหน้าการเรียงตามอันดับคือ O(k) และการสร้างใหม่คือ On(n). เมื่อ k เป็น On), อัลกอริทึมนี้จะเป็นเชิงเส้น ( ⁇ ).
- [FLT: 0]. space: รุ่นพื้นฐานที่ใช้ O(k) ช่องว่างพิเศษสําหรับลําดับจํานวน นับ รุ่นที่คงที่จะใช้ O(n+k) เนื่องจากมันช่วยจัดวางอาร์เรย์ผลลัพธ์ด้วย ซึ่งจะทําให้การนับของแต่ละรายการไม่เรียบเมื่อช่วงของข้อมูลมีความยาวมาก
- [FLT: 0] ร่วมกับชนิดอื่น: ประเภท Smithonyd เช่น SpishSort และ Commortsort ต้องการอย่างน้อย O(n Logn) การเปรียบเทียบ (in Logn). สําหรับ k เล็ก (e.g, k < 10,000 และ n & gt), การนับนับแยกสามารถเป็นคําสั่งขนาดใหญ่ได้เร็วขึ้น.
ส่วนขยายและส่วนขยาย
การ จัด การ กับ ตัว แทน ที่ ไม่ ดี
การเรียงลําดับของจํานวนเต็มที่ไม่เป็นลบ โดยจะปรับค่าลบทั้งช่วง ให้ค่าต่ําสุดเป็นศูนย์ ตัวอย่างเช่น หากตัวเลขอยู่ระหว่าง -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;
}
กุญแจ Notpap
การเรียงลําดับที่ต้องการกุญแจจํานวนเต็ม หากข้อมูลของคุณประกอบด้วยตัวอักษร (ค่าโดยมาก), หรือค่ารวมที่สามารถนําไปใช้เป็นจํานวนเต็มได้ คุณยังสามารถปรับใช้มัน สําหรับวัตถุขนาดใหญ่ คุณสามารถแยกเอากุญแจจํานวนเต็มออกมา และเรียงลําดับวัตถุตาม -- นี่เป็นวิธีเดียวกันที่ Radix เรียงลําดับมักใช้แยกประเภทเป็น parumentine ภายใน
Radix เรียงลําดับ Combo
Radix เรียงลําดับโพรเซส (หรือบิต) แต่ละตัว และการเลือกนับเป็นการเรียงลําดับตามธรรมชาติของแต่ละผ่าน (เช่น ฐาน, 10 หรือ 256) เล็ก ดังนั้น อนุญาตให้มีการเรียงลําดับจํานวนเต็มตามใจแบบเชิงเส้นได้ตามเวลา ซึ่งไม่ใช่ แค่จํานวนน้อย
การ พิจารณา ที่ ใช้ ได้ ผล ใน ซี.
ขนาดหน่วยความจําและ k ใหญ่
หลุมที่ใหญ่สุดคือ การรวมลําดับนับที่มีขนาดใหญ่กว่าหน่วยความจําที่มีอยู่ ตัวอย่างเช่น การเรียงลําดับองค์ประกอบ 1,000 ตัวที่มีระยะของที่ทิ้งของเสีย 1,000,000 ชิ้น ตรวจสอบเสมอว่า [FLT: 0] k k (FLT:1) ไม่ใช่ลําดับขนาดใหญ่กว่า[FT:2] en ; อื่น ๆ ใช้การเปรียบเทียบหรือวิธีผสมระหว่างลูกผสม
partsism และ Span< T>
สําหรับอาร์เรย์ขนาดใหญ่มากๆ คุณสามารถปรับระยะการนับได้โดยแยกส่วนข้อมูลเข้าข้ามเธรด แต่ละเธรดนับส่วนของลําดับส่วนของมันเป็นลําดับเอกชน จากนั้นผลลัพธ์บางส่วนจะถูกรวมเข้าด้วยกัน ใช้ [FLT: 7] และ[FLT: 8] สําหรับลําดับลําดับนับสามารถลดการเรียงตัวได้เมื่อช่วงเล็ก
ตัวพิมพ์ใหญ่
- [FLT: 0] ] amphy access – กลับมาอีกทันที
- [FLT: 0] องค์ประกอบ single – การจัดเรียงเป็นเรื่องเล็กน้อย
- [FLT: 0] ค่าที่เหมือนกันทั้งหมด – ลําดับนับมี 1 รายการที่ไม่ใช่ศูนย์; การสร้างใหม่ใน O(n).
- [FLT: 0] ระยะ Large แต่ข้อมูลน้อย – การนับแยกกลายเป็นความไม่มีประสิทธิภาพ เนื่องจากจํานวนส่วนใหญ่เป็นศูนย์ พิจารณาวิธีนับแบบ Hadhfollow or Bucket sort.
ส่วนเสริมสําหรับประมวลผล
ใช้การเรียงลําดับของค่านําเข้า เมื่อคุณรู้ว่าค่าจํานวนเต็มที่ป้อนเข้าไป ตกอยู่ในช่วงขนาดเล็ก (เช่น, เกรด 0-100, เกรด 0-20), หรือรหัสข้อผิดพลาด 0-1-25) สําหรับช่วงขนาดใหญ่ ให้พิจารณาค่า Radix sort หรือลูกผสมที่ไหลกลับไปที่ Sportssort สําหรับพาร์ทิชันแบบ highs
เมื่อใช้การนับเรียงลําดับ (และเมื่อมีการไม่ใช้)
| Situation | Recommendation |
|---|---|
| Small integer range (k ~ n) | Excellent choice – linear time, simple code. |
| Large integer range (k >> n) | Avoid – memory waste and O(k) overhead. |
| Need stability | Use the stable variant (cumulative counts). |
| Strings or objects | Consider Radix Sort or a comparison sort. |
| Extremely large datasets | Counting Sort can be parallelized; but watch memory. |
การย่อส่วนและประสิทธิภาพ
ในมาตรฐานทั่วไปที่มี n = 1,000,000 และ k = 1,000 การนับนับจะสมบูรณ์ในประมาณ 20-30% ของเวลาที่ดําเนินการโดย (ซึ่งใช้ Introsort) ช่องช่องว่างกว้างขึ้นเป็น k ลดลง ด้านล่างเป็นการเปรียบเทียบประมาณ (เวลาดําเนินการกับ CPU ปัจจุบันด้วย UN 08):
n = 1,000,000 | k = 1,000
Array.Sort (QuickSort variant) : 68 ms
CountingSortBasic : 12 ms
CountingSortStable : 18 ms
เมื่อช่วงขยายเป็น 10,000 ระยะนับยังคงชนะ แต่ขอบแคบกว่า. สําหรับ k = 100,000, ค่าใช้จ่ายหน่วยความจํา (400,000 คีทสําหรับลําดับนับ) เริ่มทําร้ายแคชซีพียู และประสิทธิภาพสามารถลดน้อยลงได้
รูปแบบการวน
การนับเรียงลําดับเป็นอัลกอริทึมง่ายๆ ที่จะส่งผลการทํางานแบบเชิงเส้นเมื่อข้อมูลเข้าเงื่อนไข สําหรับ C# ผู้พัฒนาการจัดการลําดับขนาดใหญ่ของจํานวนเต็มน้อยนี้ จะเป็นเครื่องมือที่มีคุณค่ามาก ที่สามารถลดเวลาในการเรียงลําดับได้อย่างมาก โปรดติดตามช่วงของข้อมูลของคุณ หากมันเล็กและเป็นที่รู้จัก การเรียงลําดับนับจะขยายออกไปตามเงื่อนไขอื่น ๆ สําหรับการสร้างเพิ่มเติม ให้ใช้รูปแบบ luffect icial (FLT) แต่พร้อมที่จะวางตัวนับเมื่อบรรทัดขึ้น -- โดยเชิงเปรียบเทียบ
สําหรับการอ่านเพิ่มเติม สืบค้น [FLT: 0] บทความเกี่ยวกับเคานต์สเซก , Microsoft Docs on Array.Sort และคู่มือปฏิบัติจาก [FTT: 4] Geeks for Geeks [FTTITTTHE].