Table of Contents
जब आपका छँटाई का कार्य छोटे पूर्णांकों की बड़ी सरणी शामिल है - जैसे ग्रेड, उम्र, या श्रेणीबद्ध कोड - क्विकसोर्ट या मर्जसोर्ट जैसे क्लासिक तुलना-आधारित एल्गोरिदम ओवरकिलिंग की तरह महसूस कर सकते हैं। ये एल्गोरिदम ओ (n log n) समय में चल रहे हैं, लेकिन यदि संभव मानों की सीमा सीमित है, तो आप रैखिक ओ (n + k) समय में कोंटिंग सॉर्ट ] के साथ क्रमबद्ध कर सकते हैं। यह गैर-समझन सॉर्टिंग एल्गोरिदम इस तथ्य को लाभ देता है कि आप तत्वों की तुलना के बजाय घटनाओं की गणना कर सकते हैं, एक स्थिर प्रकार को वितरित कर सकते हैं जो कि दोनों सरल और सही के लिए तेजी से ब्ला है।
कैसे गिनती सॉर्ट वर्क्स
गिनती छंटनी में यह ज्ञान का शोषण किया गया है कि इनपुट मान एक छोटी सीमा से तैयार किए गए पूर्णांक हैं ]। इसके बजाय जोड़ी की तुलना में, यह मूल्यों का एक आवृत्ति हिस्टोग्राम बनाता है और फिर उस हिस्टोग्राम का उपयोग करता है जो प्रत्येक तत्व को अपनी सही क्रमबद्ध स्थिति में रखने के लिए करता है।
बुनियादी दृष्टिकोण: प्रत्यक्ष पुनर्निर्माण
गिनती का सरल संस्करण क्रमबद्ध दो पासों में काम करता है:
- ]Count frequency - इनपुट सरणी के माध्यम से iterate और प्रत्येक मूल्य आप देखते हैं के लिए एक काउंटर वृद्धि।
- ]Overwrite the Input – सबसे छोटा से बड़ा काउंटर सरणी के माध्यम से चलो और प्रत्येक मूल्य के लिए, इसे वापस इनपुट सरणी में कई बार इसकी गिनती के रूप में लिखें।
यह एक क्रमबद्ध आउटपुट उत्पन्न करता है लेकिन करता है not डुप्लिकेट के सापेक्ष आदेश को संरक्षित (यह स्थिर नहीं है)। स्थिरता मामलों जब आप एक कुंजी पर क्रमबद्ध करते हैं जबकि समान कुंजी के साथ रिकॉर्ड के मूल आदेश को बनाए रखते हैं। स्थिर संस्करण, अगले वर्णित है, एक सबसे अधिक प्रयोग किया जाता है अभ्यास में।
स्थिर वैरिएंट: संचयी गणना
गिनती को स्थिर बनाने के लिए, हम एक तीसरे पास जोड़ते हैं:
- पहले की तरह आवृत्तियों की गणना करें।
- आवृत्ति सरणी को संचयी गिनती सरणी में परिवर्तित करें। इस चरण के बाद, में तत्वों की संख्या होती है i].
- इसके विपरीत इनपुट सरणी को इटरेट करें (पिछले तत्व से पहले)। प्रत्येक तत्व के लिए, आउटपुट सरणी में अपनी स्थिति खोजने के लिए अपनी संचयी गिनती का उपयोग करें, इसे रखें, और गणना को कम करें।
चूंकि हम रिवर्स में पार करते हैं, समान तत्वों का सापेक्ष क्रम संरक्षित है। आउटपुट सरणी इनपुट से अलग है, इसलिए यह संस्करण आउटपुट के लिए 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))) के साथ समझौता कर सकते हैं। स्थिर संस्करण एक नया क्रमबद्ध सरणी लौटाता है, जिससे मूल अपरिवर्तित हो जाता है।
जटिलता विश्लेषण
n] तत्वों की संख्या हो और k] = अधिकतम - मिनट + 1 (उप संभावित मूल्यों की सीमा) = अधिकतम - न्यूनतम + 1 (उप संभावित मूल्यों की सीमा)।
- Time:] O(n + k)] समय में क्रमबद्ध रनों की गिनती. गिनती चरण O(n) है, संचयी उपसर्ग O(k) है, और पुनर्निर्माण O(n) है. जब k O(n) है, तो एल्गोरिदम रैखिक है.
- Space: मूल संस्करण गिनती सरणी के लिए O(k) अतिरिक्त स्थान का उपयोग करता है। स्थिर संस्करण O(n + k) का उपयोग करता है क्योंकि यह आउटपुट सरणी को भी आवंटित करता है। यह गणना करने योग्य बनाता है जब सीमा वस्तुओं की संख्या के सापेक्ष बड़ी होती है।
- अन्य प्रकार के साथ तुलना: QuickSort और MergeSort जैसे तुलना-आधारित प्रकार कम से कम O(n log n) तुलना की आवश्यकता होती है। छोटे k (e.g., k < 10,000 और n & gt; 100,000), गिनती छंटनी तीव्रता के आदेश हो सकते हैं।
विविधता और विस्तार
नकारात्मक पूर्णांकों को संभालने
गिनती छंटनी मूल रूप से गैर-नकारात्मक पूर्णांक के साथ काम करती है। नकारात्मक मूल्यों को संभालने के लिए, पूरी रेंज को स्थानांतरित करें ताकि न्यूनतम शून्य हो जाए। उदाहरण के लिए, यदि संख्या -1000 से 1000 तक हो, तो प्रत्येक तत्व को +1000 तक ऑफसेट करें। गिनती सरणी तब आकार है।
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;
}
मानचित्रण गैर-इंटीगर कुंजी
गणना करने के लिए क्रमबद्ध को पूर्णांक कुंजी की आवश्यकता होती है। यदि आपके डेटा में वर्ण (बाट्स) होते हैं, या enumerations जो पूर्णांकों के लिए डाला जा सकता है, तो आप अभी भी इसे लागू कर सकते हैं। बड़ी वस्तुओं के लिए, आप एक पूर्णांक कुंजी निकाल सकते हैं और तदनुसार वस्तुओं को सॉर्ट कर सकते हैं - यह वास्तव में कैसे रेडिक्स सॉर्ट अक्सर गिनती का उपयोग करता है।
रेडिक्स सॉर्ट कॉम्बो
रेडिक्स सॉर्ट प्रक्रियाएं अंक (या बिट्स) व्यक्तिगत रूप से, और गिनती सॉर्ट प्रत्येक पास के लिए प्राकृतिक विकल्प है जब आधार (जैसे, 10 या 256) छोटा होता है। यह केवल छोटे लोगों के लिए नहीं बल्कि मनमाने ढंग से पूर्णांकों की रैखिक-समय पर छँटाई की अनुमति देता है।
C# में प्रैक्टिकल विचार
मेमोरी पदचिह्न और बड़े कश्मीर
सबसे बड़ा नुकसान उपलब्ध स्मृति से बड़ा एक गिनती सरणी आवंटित किया जाता है। उदाहरण के लिए, 1,000,000 कचरे की जगह की एक श्रृंखला के साथ 1,000 तत्वों को सॉर्ट करना। हमेशा सत्यापित करें कि k n]]] से बड़ा परिमाण के आदेश नहीं है -अन्य रूप में एक तुलना प्रकार या एक हाइब्रिड दृष्टिकोण का उपयोग करें।
समानता और अवधि<टी>
अत्यंत बड़ी सरणी के लिए, आप धागे के पार इनपुट को विभाजित करके गिनती चरण को समानांतर बना सकते हैं। प्रत्येक धागा अपने सेगमेंट को एक निजी सरणी में गिनता है, और फिर आंशिक परिणाम समेकित होते हैं। ] का उपयोग करके और गिनती सरणी के लिए ढेर आवंटन को कम कर सकते हैं जब सीमा छोटी हो।
एज मामले
- ]Empty array - तुरंत वापसी।
- एकल तत्व - छँटाई आदिवासी है।
- ]सभी समान मान - गिनती सरणी में एक गैर-zero प्रविष्टि है; ओ (n) में पुनर्निर्माण रन।
- ]बड़े रेंज लेकिन sparse डेटा - गिनती छंटनी अक्षम हो जाती है क्योंकि अधिकांश गिनती प्रविष्टियां शून्य होती हैं। एक हैश आधारित गिनती दृष्टिकोण या बाल्टी छंटनी पर विचार करें।
प्रदर्शन सिफारिश
जब आप जानते हैं कि इनपुट इंटाइजर्स एक छोटी रेंज (जैसे ग्रेड 0-100, आयु 0-120, या त्रुटि कोड 0-255) में आते हैं, तो गिनती का उपयोग करें। बड़ी रेंज के लिए, रेडिक्स सॉर्ट या हाइब्रिड पर विचार करें जो उच्च-श्रेणी वाले विभाजन के लिए क्विकस्टर्ट में वापस आ जाता है।
जब गिनती छंटनी (और जब तक नहीं) का उपयोग करने के लिए
| 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% में पूरा किया। खाई कश्मीर में कमी के रूप में चौड़ी है। नीचे एक अनुमानित तुलना (NET 8 के साथ एक आधुनिक सीपीयू पर निष्पादन समय):
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 KB) सीपीयू कैश को चोट पहुंचाना शुरू कर देता है, और प्रदर्शन में गिरावट हो सकती है।
निष्कर्ष
गिनती छंटनी एक निर्णायक सरल एल्गोरिथ्म है जो डेटा अपनी बाधाओं को फिट करने पर रैखिक प्रदर्शन प्रदान करता है। C# डेवलपर्स के लिए छोटे पूर्णांकों की बड़ी सरणी से निपटने के लिए, यह एक मूल्यवान उपकरण है जो नाटकीय रूप से छंटनी समय को कम कर सकता है। अपने डेटा की सीमा पर नजर रखें: यदि यह छोटा और ज्ञात है, तो गणना छंटनी किसी भी तुलना-आधारित विकल्प को पीछे छोड़ देगी। अधिक सामान्य प्रयोजन के लिए छंटाई, निर्मित-इन का उपयोग करें, लेकिन हमेशा गिनती में गिरावट के लिए तैयार रहें क्रमबद्ध जब संख्याएं - सामान्य रूप से और आज़ादी तक लाइन करें।
आगे पढ़ने के लिए, ]Wikipedia (Wikipedia)] पर कंटेंट , ]Aray.Sort] पर Microsoft docs, और GeeksforGeeks]]] से एक व्यावहारिक गाइड।