कमाल पद्धत वापरून क्रमवारी लावणे. नवशिक्यांसाठी अल्गोरिदम आणि डेटा स्ट्रक्चर्स: क्रमवारी

मालिकेतील धडा: "पास्कलमधील प्रोग्रामिंग"

अनेक समस्या सोडवताना माहिती शोधण्याची प्रक्रिया जलद आणि अधिक कार्यक्षमतेने डेटाची विशिष्ट क्रमाने मांडणी केली जाते. उदाहरणार्थ, विद्यार्थी, विद्यार्थी, कर्मचारी यांच्या विविध याद्या - इन अक्षर क्रमानुसार, सर्वात मोठ्या मूल्यापासून सर्वात लहान (किंवा उलट) पर्यंत संख्यात्मक डेटा इ.

अगदी काही वेगळ्या पद्धती आहेत ॲरे वर्गीकरण, कार्यक्षमतेच्या प्रमाणात एकमेकांपासून भिन्न, ज्याला क्रमवारी प्रक्रियेत तुलनांची संख्या आणि एक्सचेंजची संख्या म्हणून समजले जाते. चला त्यापैकी काहींवर जवळून नजर टाकूया.

सोप्या निवड पद्धतीचा वापर करून ॲरे क्रमवारी लावा

येथे ॲरेची क्रमवारी लावत आहेकमाल (किमान) घटक आणि त्याची संख्या शोधण्यासाठी निवड पद्धत मूलभूत अल्गोरिदम वापरते.

निवड पद्धत वापरून ॲरे क्रमवारी लावण्यासाठी अल्गोरिदम:

  1. मूळ ॲरेसाठी, कमाल घटक निवडा.
  2. शेवटच्या घटकासह स्वॅप करा (त्यानंतर सर्वात मोठा घटक त्याच्या जागी राहील).
  3. पुनरावृत्ती करा pp. उरलेल्या n-1 घटकांसह 1-2, म्हणजे, ॲरेचा काही भाग विचारात घ्या, पहिल्या घटकापासून उपांत्य घटकापर्यंत प्रारंभ करा, त्यातील कमाल घटक शोधा आणि ते उपांत्य (n-1)व्या घटकासह स्वॅप करा. ॲरे, नंतर उर्वरित (n-2) -दोन घटकांसह आणि असेच एक घटक जोपर्यंत त्याच्या जागी आधीपासूनच राहत नाही.

ॲरे ऑर्डर करण्यासाठी ॲरेचे (n-1) स्कॅन आवश्यक असतील. वर्गीकरण प्रक्रियेदरम्यान, ॲरेचा क्रमवारी लावलेला भाग वाढेल आणि क्रमवारी न केलेला भाग, त्यानुसार, कमी होईल.

डेटाची क्रमवारी लावताना, व्हेरिएबल्समधील सामग्रीची देवाणघेवाण केली जाते. देवाणघेवाण करण्यासाठी, तुम्हाला एक तात्पुरता व्हेरिएबल तयार करणे आवश्यक आहे जे व्हेरिएबलपैकी एकाची सामग्री संग्रहित करेल. अन्यथा, त्यातील सामग्री गमावली जाईल.

कार्य 1. साध्या ब्रूट फोर्सचा वापर करून 10 घटकांची चढत्या क्रमाने क्रमवारी लावा.

चला एक कार्यपद्धती लिहू. त्यासाठी इनपुट पॅरामीटर ॲरे असेल. हे आउटपुट पॅरामीटर देखील असेल. म्हणून, आम्ही त्याचे वर्णन व्हेरिएबल पॅरामीटर म्हणून करतो (सह कीवर्ड var).

प्रक्रियेमध्ये, i वरील बाह्य लूप ॲरेच्या विचारात घेतलेल्या भागाची लांबी निर्धारित करते. ते n ते 2 पर्यंत बदलेल.

कमाल घटक आणि त्याची संख्या शोधण्यासाठी j वरील आतील लूप वापरला जातो. ॲरेच्या मानल्या गेलेल्या भागाच्या शेवटच्या घटकाचे मूल्य कमालचे प्रारंभिक मूल्य म्हणून घेणे वाजवी आहे.

कार्यक्रम कोडप्रक्रीया:

मुख्य प्रोग्रामचा प्रोग्राम कोड:

प्रोग्राम प्राइमर_1; const n = 10; myarray = पूर्णांकाचा ॲरे टाइप करा; var a:myarray; प्रक्रिया वर्गीकरण1(var a:myarray); (रेखीय क्रमवारी (निवड क्रमवारी)) ... आरंभ (मुख्य) लेखन ("स्रोत ॲरे प्रविष्ट करा:"); i साठी:=1 ते n वाचणे(a[i]); वर्गीकरण1(a); writeln("सॉर्ट केलेला ॲरे:"); i साठी:=1 ते 10 लिहा(a[i]," "); लिहिणे; शेवट

निवड पद्धतीचा वापर करून चढत्या क्रमाने ॲरेमध्ये घटकांची क्रमवारी करण्याची प्रक्रिया:

आयटम नंबर 1 2 3 4 5
स्रोत ॲरे 8 7 5 4 2
प्रथम दर्शन 2 7 5 4 8
दुसरे पाहणे 2 4 5 7 8
तिसरे दर्शन 2 4 5 7 8
चौथा पाहणे 2 4 5 7 8

उतरत्या क्रमाने ॲरेची क्रमवारी लावताना, तुम्हाला किमान घटक हलवावा लागेल. कमाल घटक शोधण्यासाठी अल्गोरिदममध्ये “>” चिन्ह बदलून “” चिन्हावर का पुरेसे आहे<«.

साधी एक्सचेंज पद्धत (बबल पद्धत) वापरून ॲरे क्रमवारी लावा

सर्वात प्रसिद्ध क्रमवारी पद्धत म्हणजे बबल सॉर्टिंग. त्याची लोकप्रियता त्याच्या आकर्षक नावाने आणि साध्या अल्गोरिदमद्वारे स्पष्ट केली जाते.

पद्धत या वस्तुस्थितीवर आधारित आहे की अल्गोरिदमच्या अंमलबजावणीदरम्यान, ॲरेचे "फिकट" घटक हळूहळू "फ्लोट अप" होतात.

या पद्धतीचे वैशिष्ठ्य म्हणजे प्रत्येक घटकाची सर्वांशी तुलना करणे नव्हे तर शेजारच्या घटकांच्या जोडीतील तुलना. ॲरेचे अनेक अनुक्रमिक स्कॅन सुरुवातीपासून शेवटपर्यंत केले जातात. समीप घटक "चुकीने" स्थित असल्यास, ते स्वॅप केले जातात.

साध्या एक्सचेंज पद्धतीचा वापर करून चढत्या क्रमाने ॲरेची क्रमवारी लावण्यासाठी अल्गोरिदम:

  1. घटकांच्या पहिल्या जोडीने (a आणि a) ब्राउझिंग सुरू करूया. जर या जोडीचा पहिला घटक दुसऱ्यापेक्षा मोठा असेल, तर आम्ही त्यांना बदलतो, अन्यथा आम्ही त्यांना अपरिवर्तित सोडतो. मग आपण घटकांची दुसरी जोडी (a आणि a) घेतो, जर दुसरा तिसऱ्यापेक्षा मोठा असेल तर आपण त्यांना देखील बदलतो, नंतर आपण तिसऱ्या आणि चौथ्या ची तुलना करतो आणि जर तिसरा चौथ्यापेक्षा मोठा असेल तर आपण त्यांचे बदल करतो. ठिकाणे इ. आपण शेवटची तुलना करतो ती म्हणजे (n-1)व्या आणि nव्या घटकांची ॲरेच्या पहिल्या ट्रॅव्हर्सल दरम्यान, 1 ते (n-1) पर्यंत ॲरे घटकांच्या सर्व जोड्या पाहिल्या जातील. . परिणामी, ॲरेचा कमाल घटक ॲरेच्या शेवटी हलवला जाईल.
  2. सर्वात मोठा घटक त्याच्या जागी असल्याने, त्याशिवाय ॲरेचा भाग विचारात घ्या, म्हणजे, पहिल्यापासून (n-1)व्या घटकापर्यंत, आम्ही ॲरेच्या या भागासाठी मागील चरणांची पुनरावृत्ती करतो जो ॲरेचा दुसरा सर्वात मोठा घटक ॲरेच्या विचारात घेतलेल्या एका भागाच्या शेवटच्या ठिकाणी, म्हणजेच संपूर्ण ॲरेमधील (n-1) ठिकाणी जाईल.
  3. ॲरेच्या वर्तमान भागातील घटकांची संख्या दोनपर्यंत कमी होईपर्यंत या क्रिया सुरू राहतात. या प्रकरणात, आपल्याला अंतिम तुलना करणे आणि शेवटचे दोन घटक ऑर्डर करणे आवश्यक आहे.

हे पाहणे सोपे आहे की n घटकांचा समावेश असलेल्या ॲरेचे रूपांतर करण्यासाठी, ते n–1 वेळा स्कॅन करणे आवश्यक आहे, प्रत्येक वेळी पाहण्याची श्रेणी एका घटकाने कमी करते.

खाली बबल पद्धत वापरून चढत्या क्रमाने ॲरे वर्गीकरण करण्याच्या प्रक्रियेचा मजकूर आहे.

ॲरे घटकांना त्यांच्या मूल्यांच्या उतरत्या क्रमाने ऑर्डर करण्यासाठी, ॲरे घटकांची तुलना करताना, “>” चिन्ह बदलून “<«.

एक्सचेंज पद्धतीचा वापर करून चढत्या क्रमाने ॲरेमध्ये घटकांची मांडणी करण्याची प्रक्रिया:

आयटम नंबर 1 2 3 4 5
स्रोत ॲरे 8 7 5 4 2
प्रथम दर्शन 7 5 4 2 8
दुसरे पाहणे 5 4 2 7 8
तिसरे दर्शन 4 2 5 7 8
चौथा पाहणे 2 4 5 7 8

ॲरे क्रमवारी लावाएका विशिष्ट क्रमाने सर्व घटकांचे वितरण करण्याची प्रक्रिया आहे. बर्याचदा हे उपयुक्त आहे. उदाहरणार्थ, तुमच्या इनबॉक्समध्ये, ईमेल प्राप्त झालेल्या वेळेनुसार प्रदर्शित केले जातात; तुम्हाला अर्धा तास, एक तास, दोन किंवा एक दिवसापूर्वी मिळालेल्या ईमेलपेक्षा नवीन ईमेल अधिक संबंधित मानले जातात; जेव्हा तुम्ही तुमच्या संपर्क सूचीवर जाता, तेव्हा नावे सहसा वर्णक्रमानुसार असतात कारण काहीतरी शोधणे सोपे असते. या सर्व प्रकरणांमध्ये डेटा प्रत्यक्षात आउटपुट करण्यापूर्वी क्रमवारी लावणे समाविष्ट आहे.

वर्गीकरण कसे कार्य करते?

डेटा क्रमवारी लावल्याने ॲरेमधील शोध केवळ लोकांसाठीच नाही तर संगणकांसाठीही अधिक कार्यक्षम बनू शकतो. उदाहरणार्थ, नावांच्या सूचीमध्ये एखादे विशिष्ट नाव दिसते की नाही हे शोधणे आवश्यक असलेल्या प्रकरणाचा विचार करा. हे शोधण्यासाठी, आम्हाला ॲरेचा प्रत्येक घटक आमच्या मूल्याविरुद्ध तपासावा लागेल. अनेक घटकांसह ॲरे शोधणे खूप अकार्यक्षम (महाग) असू शकते.

तथापि, आपण असे गृहीत धरू की आपल्या नावांची ॲरे वर्णमालानुसार क्रमवारी लावली आहे. मग आपला शोध आपल्या मूल्याच्या पहिल्या अक्षराने सुरू होतो आणि नंतर वर्णमाला असलेल्या अक्षराने संपतो. या प्रकरणात, जर आम्हाला हे पत्र मिळाले आणि नाव सापडले नाही, तर आम्हाला निश्चितपणे माहित आहे की ते उर्वरित ॲरेमध्ये नाही, कारण आम्ही आमचे पत्र आधीच वर्णक्रमानुसार पास केले आहे!

हे रहस्य नाही की सॉर्ट केलेल्या ॲरेमध्ये शोधण्यासाठी चांगले अल्गोरिदम आहेत. साध्या अल्गोरिदमचा वापर करून, आम्ही फक्त 20 तुलना वापरून 1,000,000 घटक असलेल्या क्रमवारी केलेल्या ॲरेमध्ये विशिष्ट घटक शोधू शकतो! नकारात्मक बाजू, अर्थातच, एवढ्या मोठ्या संख्येने घटकांसह ॲरेची क्रमवारी लावणे तुलनेने महाग आहे आणि हे निश्चितपणे एका शोध क्वेरीच्या फायद्यासाठी केले जात नाही.

काही प्रकरणांमध्ये, ॲरेची क्रमवारी लावल्याने शोध अनावश्यक होतो. उदाहरणार्थ, आम्ही परीक्षेत विद्यार्थ्याचे सर्वोत्तम गुण शोधत आहोत. जर ॲरेची क्रमवारी लावली नसेल, तर सर्वोच्च स्कोअर शोधण्यासाठी ॲरेच्या प्रत्येक घटकाचा शोध घ्यावा लागेल. जर ॲरे क्रमवारी लावली असेल, तर सर्वोच्च स्कोअर एकतर पहिल्या स्थानावर असेल किंवा शेवटचा असेल (ॲरेची क्रमवारी कशी लावली जाते यावर अवलंबून आहे: चढत्या किंवा उतरत्या क्रमाने), त्यामुळे आम्हाला अजिबात शोधण्याची गरज नाही!

क्रमवारी लावणे सामान्यत: ॲरे घटकांच्या जोड्यांची वारंवार तुलना करून आणि विशिष्ट निकष पूर्ण करत असल्यास मूल्ये बदलून केले जाते. या घटकांची तुलना कोणत्या क्रमाने केली जाते हे कोणत्या क्रमवारीत अल्गोरिदम वापरले जाते यावर अवलंबून असते. निकषांमध्ये ॲरेची क्रमवारी कशी लावली जाईल (उदाहरणार्थ, चढत्या क्रमाने किंवा उतरत्या क्रमाने) असते.

दोन घटक स्वॅप करण्यासाठी आपण फंक्शन वापरू शकतो std::swap() C++ मानक लायब्ररी मधून, जे अल्गोरिदममध्ये परिभाषित केले आहे. C++ 11 मध्ये, std::swap() युटिलिटी हेडर फाइलमध्ये हलवण्यात आले:

#समाविष्ट करा #समाविष्ट करा int main() ( int a = 3; int b = 5; std::cout<< "Before swap: a = " << a << ", b = " << b << "\n"; std::swap(a, b); // меняем местами значения переменных a и b std::cout << "After swap: a = " << a << ", b = " << b << "\n"; }

#समाविष्ट करा

#समाविष्ट करा // std::swap साठी. C++11 मध्ये हेडर वापरा

इंट मुख्य()

int a = 3 ;

int b = 5 ;

std::cout<< "Before swap: a = " << a << ", b = " << b << "\n" ;

std::swap(a, b); // a आणि b व्हेरिएबल्सची व्हॅल्यू स्वॅप करा

std::cout<< "After swap: a = " << a << ", b = " << b << "\n" ;

वरील प्रोग्राम चालवण्याचे परिणाम:

स्वॅप करण्यापूर्वी: a = 3, b = 5
स्वॅप नंतर: a = 5, b = 3

रिप्लेसमेंट ऑपरेशन केल्यानंतर, a आणि b व्हेरिएबल्सची व्हॅल्यू स्वॅप केली जातात.

निवड पद्धत वापरून ॲरे क्रमवारी लावणे

ॲरे क्रमवारी लावण्याचे अनेक मार्ग आहेत. निवडीनुसार ॲरे क्रमवारी समजणे कदाचित सर्वात सोपे आहे, जरी ते सर्वात हळू आहे.

च्या साठी सर्वात लहान ते सर्वात मोठे घटक निवडून ॲरेची क्रमवारी लावणेखालील चरण केले जातात:

इंडेक्स 0 वरील घटकापासून सुरुवात करून, आम्ही ॲरेमधील सर्वात लहान मूल्य शोधतो.

सापडलेले मूल्य शून्य घटकासह स्वॅप केले जाते.

ॲरेमधील पुढील निर्देशांकासाठी आम्ही चरण क्रमांक 1 आणि क्रमांक 2 पुन्हा करतो.

दुसऱ्या शब्दांत, आम्ही ॲरेमधील सर्वात लहान घटक शोधतो आणि त्यास प्रथम स्थानावर हलवतो. मग आपण दुसरा सर्वात लहान घटक शोधतो आणि त्यास पहिल्या सर्वात लहान घटकानंतर दुसऱ्या स्थानावर हलवू. क्रमवारी न केलेले घटक संपेपर्यंत ही प्रक्रिया सुरू राहते.

हे अल्गोरिदम 5 घटकांसह ॲरेमध्ये कसे कार्य करते याचे एक उदाहरण येथे आहे:

{ 30, 50, 20, 10, 40 }

प्रथम आपण अनुक्रमणिका 0 पासून सुरू होणारा सर्वात लहान घटक शोधतो:

{ 30, 50, 20, 10 , 40 }

मग आपण अनुक्रमणिका 0 वरील घटकासह सर्वात लहान घटक स्वॅप करतो:

{ 10 , 50, 20, 30 , 40 }

आता ॲरेचा पहिला घटक क्रमवारी लावला आहे, आम्ही त्याकडे दुर्लक्ष करतो. आम्ही पुढील सर्वात लहान घटक शोधत आहोत, परंतु अनुक्रमणिका 1 पासून प्रारंभ करत आहोत:

{ 10 , 50, 20 , 30, 40 }

आणि अनुक्रमणिका 1 वरील घटकासह स्वॅप करा:

{ 10 , 20 , 50 , 30, 40 }

आता आपण पहिल्या दोन घटकांकडे दुर्लक्ष करू शकतो. आम्ही अनुक्रमणिका 2 पासून सुरू होणारा पुढील सर्वात लहान घटक शोधतो:

{ 10 , 20 , 50, 30 , 40 }

आणि अनुक्रमणिका 2 वरील घटकासह स्वॅप करा:

{ 10 , 20 , 30 , 50 , 40 }

आम्ही अनुक्रमणिका 3 पासून सुरू होणारा पुढील सर्वात लहान घटक शोधतो:

{ 10 , 20 , 30 , 50, 40 }

आणि अनुक्रमणिका 3 वरील घटकासह स्वॅप करा:

{ 10 , 20 , 30 , 40 , 50 }

आम्ही अनुक्रमणिका 4 पासून सुरू होणारा पुढील सर्वात लहान घटक शोधतो:

{ 10 , 20 , 30 , 40 , 50 }

आणि आम्ही ते अनुक्रमणिका 4 वरील घटकासह स्वॅप करतो (स्व-प्रतिस्थापन केले जाते, म्हणजे आम्ही काहीही करत नाही):

{ 10 , 20 , 30 , 40 50 }

{ 10, 20, 30, 40, 50 }

लक्षात घ्या की शेवटची तुलना नेहमीच एकल तुलना असेल (म्हणजे स्वत: ची बदली), जी एक अनावश्यक ऑपरेशन आहे, त्यामुळे खरं तर आम्ही ॲरेच्या शेवटच्या घटकापूर्वी क्रमवारी थांबवू शकतो.

C++ मध्ये निवड पद्धत वापरून ॲरे क्रमवारी लावणे

हे अल्गोरिदम C++ मध्ये कसे लागू केले जाते ते येथे आहे:

#समाविष्ट करा #समाविष्ट करा // std::swap साठी. C++11 मध्ये हेडर वापरा int main() ( const int length = 5; int array = ( 30, 50, 20, 10, 40); // ॲरेच्या प्रत्येक घटकामधून लूप करा // (शेवटचा घटक वगळता, ते आधीपासून क्रमवारी लावले जाईल. (int startIndex = 0; startIndex) साठी आपण पोहोचू या< length - 1; ++startIndex) { // В переменной smallestIndex хранится индекс наименьшего значения, которое мы нашли в этой итерации // Начинаем с того, что наименьший элемент в этой итерации - это первый элемент (индекс 0) int smallestIndex = startIndex; // Затем ищем элемент поменьше в остальной части массива for (int currentIndex = startIndex + 1; currentIndex < length; ++currentIndex) { // Если мы нашли элемент, который меньше нашего наименьшего элемента, if (array < array) // то запоминаем его smallestIndex = currentIndex; } // smallestIndex теперь наименьший элемент // Меняем местами наше начальное наименьшее число с тем, которое мы обнаружили std::swap(array, array); } // Теперь, когда весь массив отсортирован - выводим его на экран for (int index = 0; index < length; ++index) std::cout << array << " "; return 0; }

#समाविष्ट करा

#समाविष्ट करा // std::swap साठी. C++11 मध्ये हेडर वापरा

इंट मुख्य()

const int length = 5 ;

// ॲरेच्या प्रत्येक घटकाद्वारे लूप करा

// (शेवटचा एक वगळता, आम्ही पोहोचू तेव्हा ते आधीच क्रमवारी लावले जाईल)

< length - 1 ; ++ startIndex )

// smallestIndex व्हेरिएबल आपल्याला या पुनरावृत्तीमध्ये आढळलेल्या सर्वात लहान मूल्याचा निर्देशांक संग्रहित करतो

// या पुनरावृत्तीमधील सर्वात लहान घटकासह प्रारंभ करा हा पहिला घटक (इंडेक्स 0)

int smallestIndex = startIndex;

// नंतर उर्वरित ॲरेमध्ये एक लहान घटक शोधा

< length ; ++ currentIndex )

// जर आम्हाला एखादा घटक आढळला जो आमच्या सर्वात लहान घटकापेक्षा लहान आहे,

जर (अरे [ वर्तमान निर्देशांक ]< array [ smallestIndex ] )

// मग ते लक्षात ठेवा

सर्वात लहान निर्देशांक = वर्तमान निर्देशांक;

// smallestIndex आता सर्वात लहान घटक आहे

// आम्हाला मिळालेल्या आम्हाला मिळालेल्या आम्हाला सर्वात लहान संख्याची अदलाबदल करा

std::swap(array[startIndex], array[smallestIndex]);

// आता संपूर्ण ॲरेची क्रमवारी लावली आहे, ती स्क्रीनवर प्रदर्शित करा

साठी (इंट इंडेक्स = 0; इंडेक्स< length ; ++ index )

std::cout<< array [ index ] << " " ;

परतावा 0;

या अल्गोरिदमचा सर्वात गोंधळात टाकणारा भाग दुसर्या लूपमध्ये आहे (ज्याला नेस्टेड लूप म्हणतात). बाह्य लूप (startIndex) घटकांद्वारे एक एक (एकावेळी एक) पुनरावृत्ती होते. बाह्य लूपच्या प्रत्येक पुनरावृत्तीमध्ये, आतील लूप (करंटइंडेक्स) ॲरेमध्ये राहणाऱ्या घटकांमधील सर्वात लहान घटक शोधण्यासाठी वापरला जातो (स्टार्टइंडेक्स + 1 पासून सुरू होणारा). smallestIndex आतील लूपद्वारे सापडलेल्या सर्वात लहान घटकाच्या निर्देशांकाचा मागोवा ठेवतो. मग सर्वात लहान इंडेक्स startIndex वरून मूल्य बदलते. शेवटी, बाह्य लूप (startIndex) हा घटक पास करतो आणि प्रक्रिया पुनरावृत्ती होते.

सुगावा:वरील प्रोग्राम कसा कार्य करतो हे समजण्यात तुम्हाला अडचण येत असल्यास, कागदाच्या तुकड्यावर लिहून पहा. वर्कशीटच्या शीर्षस्थानी असलेल्या एका ओळीवर ॲरेचे प्रारंभिक (क्रमबद्ध न केलेले) घटक क्षैतिजरित्या लिहा. या क्षणी startIndex , currentIndex , आणि सर्वात लहान इंडेक्स कोणते घटक आहेत हे दर्शवणारे बाण काढा. प्रोग्राममधून मॅन्युअली लूप करा आणि निर्देशांक बदलल्यावर बाण पुन्हा काढा. बाह्य लूपच्या प्रत्येक पुनरावृत्तीनंतर, ॲरेची वर्तमान स्थिती (त्याच्या घटकांचे स्थान) दर्शविणारी एक नवीन रेषा काढा.

मजकूर वर्गीकरण समान अल्गोरिदम वापरून केले जाते. फक्त ॲरे प्रकार -a वरून बदला आणि योग्य मूल्यांसह प्रारंभ करा.

std::sort()

ॲरे क्रमवारी लावणे हे अतिशय सामान्य ऑपरेशन असल्याने, C++ मानक लायब्ररी अंगभूत सॉर्टिंग फंक्शन प्रदान करते − std::sort(). हे अल्गोरिदम शीर्षलेख फाईलमध्ये स्थित आहे आणि त्याला खालीलप्रमाणे म्हणतात:

#समाविष्ट करा #समाविष्ट करा // std::sort int main() ( const int length = 5; int array = ( 30, 50, 20, 10, 40); std::sort(array, array+length); साठी (int i= 0;< length; ++i) std::cout << array[i] << " "; return 0; }

#समाविष्ट करा

#समाविष्ट करा // std::sort साठी

इंट मुख्य()

const int length = 5 ;

int array [length] = (30, 50, 20, 10, 40);

std:: क्रमवारी (ॲरे, ॲरे + लांबी);

साठी (int i = 0; i< length ; ++ i )

std::cout<< array [ i ] << " " ;

परतावा 0;

चाचणी

कार्य क्रमांक १

निवड पद्धतीचा वापर करून खालील ॲरेची क्रमवारी कशी लावायची ते कागदाच्या तुकड्यावर लिहा (जसे आम्ही वर केले आहे):

{30, 60, 20, 50, 40, 10}

उत्तर #1

30 60 20 50 40 10
10 60 20 50 40 30
10 20 60 50 40 30
10 20 30 50 40 60
10 20 30 40 50 60
10 20 30 40 50 ६० (स्व-रिप्लेसमेंट)
10 20 30 40 50 60 (स्व-रिप्लेसमेंट)

कार्य क्रमांक 2

"C++ मध्ये निवडीनुसार ॲरे क्रमवारी लावा" या उपशीर्षकातून प्रोग्राम कोड पुन्हा लिहा जेणेकरून क्रमवारी उतरत्या क्रमाने (सर्वात मोठी ते सर्वात लहान संख्या) होईल. जरी हे पहिल्या दृष्टीक्षेपात क्लिष्ट वाटत असले तरी प्रत्यक्षात ते खूप सोपे आहे.

उत्तर #2

फक्त बदला:

जर (ॲरे< array)

जर (अरे [ वर्तमान निर्देशांक ]< array [ smallestIndex ] )

जर (ॲरे > ॲरे)

जर (ॲरे [ वर्तमान निर्देशांक ] > ॲरे [ सर्वात लहान निर्देशांक ] )

तसेच सर्वात लहान इंडेक्सचे नाव सर्वात मोठे इंडेक्स असे केले पाहिजे:

#समाविष्ट करा #समाविष्ट करा // std::swap साठी. C++11 मध्ये हेडर वापरा int main() ( const int length= 5; int array = ( 30, 50, 20, 10, 40); // (int startIndex = 0; startIndex) साठी शेवटचा घटक वगळता प्रत्येक ॲरे घटकातून लूप करा< length - 1; ++startIndex) { // largestIndex - это индекс наибольшего элемента, который мы обнаружили до сих пор int largestIndex = startIndex; // Перебираем каждый элемент массива начиная со startIndex + 1 for (int currentIndex = startIndex + 1; currentIndex < length; ++currentIndex) { // Если текущий элемент больше нашего наибольшего элемента, if (array >array) // नंतर या पुनरावृत्तीमधील हा नवीन सर्वात मोठा घटक आहे largeIndex = currentIndex; ) // std::swap(ॲरे, ॲरे) सापडलेल्या सर्वात मोठ्या घटकासह आमचा प्रारंभिक क्रमांक स्वॅप करा; ) साठी (इंट इंडेक्स = 0; इंडेक्स< length; ++index) std::cout << array << " "; return 0; }

#समाविष्ट करा

#समाविष्ट करा // std::swap साठी. C++11 मध्ये हेडर वापरा

इंट मुख्य()

const int length = 5 ;

int array [length] = (30, 50, 20, 10, 40);

// शेवटचा घटक वगळता ॲरेच्या प्रत्येक घटकातून लूप करा

साठी (int startIndex = 0; startIndex< length - 1 ; ++ startIndex )

// largeIndex हा आत्तापर्यंत सापडलेल्या सर्वात मोठ्या घटकाचा निर्देशांक आहे

int largeIndex = startIndex;

// startIndex + 1 पासून सुरू होणाऱ्या ॲरेच्या प्रत्येक घटकातून लूप करा

साठी (int currentIndex = startIndex + 1; currentIndex< length ; ++ currentIndex )

// वर्तमान घटक आपल्या सर्वात मोठ्या घटकापेक्षा मोठा असल्यास,

जर (ॲरे [ वर्तमान निर्देशांक ] > ॲरे [ सर्वात मोठा निर्देशांक ] )

// मग या पुनरावृत्तीमधील हा नवीन सर्वात मोठा घटक आहे

सर्वात मोठा निर्देशांक = वर्तमान निर्देशांक;

// सापडलेल्या सर्वात मोठ्या घटकासह आमचा प्रारंभ क्रमांक स्वॅप करा

std::swap (ॲरे [स्टार्टइंडेक्स], ॲरे [सर्वात मोठी इंडेक्स]);

// स्क्रीनवर क्रमबद्ध ॲरे प्रदर्शित करा

साठी (इंट इंडेक्स = 0; इंडेक्स< length ; ++ index )

std::cout<< array [ index ] << " " ;

परतावा 0;

कार्य क्रमांक 3

हे काम थोडे अवघड आहे.

घटकांची क्रमवारी लावण्याची दुसरी सोपी पद्धत आहे "बबल क्रमवारी"(किंवा जास्त "बबल क्रमवारी"). जवळपास असलेल्या मूल्यांच्या जोडीची तुलना करणे ही कल्पना आहे आणि जर निर्दिष्ट निकष पूर्ण केले तर, या जोडीतील मूल्ये बदलली जातात. आणि अशा प्रकारे घटक ॲरेच्या शेवटी "बबल" करतात. बबल सॉर्ट ऑप्टिमाइझ करण्याचे अनेक मार्ग असले तरी, या असाइनमेंटसाठी आम्ही अनऑप्टिमाइज्ड व्हर्जनला चिकटून राहू कारण ते सोपे आहे.

बबल सॉर्टच्या नॉन-ऑप्टिमाइझ केलेल्या आवृत्तीसाठी, पुढील चरणे पूर्ण केली जातात: सर्वात लहान ते सर्वात मोठ्या मूल्यापर्यंत ॲरे क्रमवारी लावा:

अनुक्रमणिका 0 वरील ॲरे घटकाची अनुक्रमणिका 1 वरील ॲरे घटकाशी तुलना केली जाते. जर अनुक्रमणिका 0 वरील घटक अनुक्रमणिका 1 वरील घटकापेक्षा मोठा असेल, तर मूल्ये स्वॅप केली जातात.

त्यानंतर आम्ही मूल्यांच्या पुढील जोडीकडे जाऊ: अनुक्रमणिका 1 वरील घटक आणि अनुक्रमणिका 2 मधील घटक आणि असेच जोपर्यंत आपण ॲरेच्या शेवटी पोहोचत नाही.

संपूर्ण ॲरे क्रमवारी लावेपर्यंत चरण # 1 आणि चरण # 2 ची पुनरावृत्ती करा.

वरील नियमांनुसार बबल सॉर्ट वापरून खालील ॲरे क्रमवारी लावणारा प्रोग्राम लिहा:

const int length(9); इंट ॲरे = ( 7, 5, 6, 4, 9, 8, 2, 1, 3);

const int length(9);

प्रोग्रामच्या शेवटी, ॲरेचे क्रमबद्ध केलेले घटक प्रिंट करा.

सुगावा:जर आपण एका पुनरावृत्तीमध्ये फक्त एक घटक क्रमवारी लावू शकलो, तर याचा अर्थ असा आहे की संपूर्ण ॲरे क्रमवारी लावली आहे याची खात्री करण्यासाठी आपल्याला आपल्या ॲरेमध्ये (त्याची लांबी) संख्या आहेत तितक्या वेळा लूपची पुनरावृत्ती करावी लागेल.

उत्तर #3

#समाविष्ट करा #समाविष्ट करा // std::swap साठी. C++11 मध्ये हेडर वापरा int main() ( const int length(9); int array = ( 7, 5, 6, 4, 9, 8, 2, 1, 3); साठी (int पुनरावृत्ती = 0; पुनरावृत्ती< length-1; ++iteration) { // Перебираем каждый элемент массива до последнего элемента (не включительно) // Последний элемент не имеет пары для сравнения for (int currentIndex = 0; currentIndex < length - 1; ++currentIndex) { // Если текущий элемент больше элемента после него, то меняем их местами if (array >array) std::swap(ॲरे, ॲरे); ) ) // (इंट इंडेक्स = 0; अनुक्रमणिका) साठी स्क्रीनवर क्रमबद्ध ॲरे प्रदर्शित करा< length; ++index) std::cout << array << " "; return 0; }

#समाविष्ट करा

#समाविष्ट करा // std::swap साठी. C++11 मध्ये हेडर वापरा

इंट मुख्य()

const int length(9);

int array [length] = (7, 5, 6, 4, 9, 8, 2, 1, 3);

साठी (इंट पुनरावृत्ती = 0; पुनरावृत्ती< length - 1 ; ++ iteration )

// प्रत्येक ॲरे घटकातून शेवटच्या घटकापर्यंत लूप करा (समावेशक नाही)

// शेवटच्या घटकाची तुलना करण्यासाठी कोणतीही जोडी नाही

साठी (int currentIndex = 0; currentIndex< length - 1 ; ++ चालू निर्देशांक)

{

// जर वर्तमान घटक त्याच्या नंतरच्या घटकापेक्षा मोठा असेल तर त्यांची अदलाबदल करा

तर(रचना[ चालू निर्देशांक] > रचना[ चालू निर्देशांक+ 1 ] )

इयत्ता:: स्वॅप(रचना[ चालू निर्देशांक] , रचना[ चालू निर्देशांक+ 1 ] ) ;

}

}

// स्क्रीनवर क्रमबद्ध ॲरे प्रदर्शित करा

च्या साठी(intनिर्देशांक= 0 ; निर्देशांक< लांबी; ++ निर्देशांक)

इयत्ता:: cout<< रचना[ निर्देशांक] << " " ;

परत0 ;

}

कार्य क्रमांक 4

तुम्ही मागील असाइनमेंटमध्ये लिहिलेल्या बबल सॉर्ट अल्गोरिदमसाठी खालील दोन ऑप्टिमायझेशन उपाय लागू करा:

लक्षात घ्या की प्रत्येक वेळी बबल सॉर्ट केले जाते, ॲरेमधील सर्वात मोठे मूल्य "बबल" शेवटपर्यंत. पहिल्या पुनरावृत्तीनंतर, ॲरेचा शेवटचा घटक आधीच क्रमवारी लावलेला आहे. दुसऱ्या पुनरावृत्तीनंतर, ॲरेचा उपांत्य घटक क्रमवारी लावला जातो आणि असेच. प्रत्येक नवीन पुनरावृत्तीसह, आम्हाला आधीच क्रमवारी लावलेले घटक पुन्हा तपासण्याची आवश्यकता नाही. तुमचा लूप सुधारित करा जेणेकरून तुम्ही आधीच क्रमवारी लावलेल्या घटकांची पुन्हा तपासणी करू नका.

ॲरेमधील मूल्यांच्या चढत्या किंवा उतरत्या क्रमाने क्रमवारी लावण्यासाठी (क्रमवारी) अनेक पद्धती विकसित केल्या गेल्या आहेत [विर्थ, नुथ. t 3] त्यातील तीन गोष्टींचा विचार करू या, निश्चिततेसाठी, प्रथम n, n=6, ॲरे X चे घटक.

प्रत्येक पुढील i-व्या पायरीवर, i=2, 3,…,n-1, ॲरेच्या (i+1)व्या सेलमधील मूल्य मागील क्रमांकाच्या संख्येसह स्थानाची देवाणघेवाण करून सेल इंडेक्स कमी करण्याच्या दिशेने हलविले जाते. सेल पर्यंत असे दिसून येणार नाही की मागील सेलमध्ये लहान संख्या आहे.

वरीलवरून असे दिसून येते की थेट समावेशन पद्धतीची अंमलबजावणी करताना, बाह्य लूप n-1 वेळा कार्यान्वित करणे आवश्यक आहे आणि आतील लूपच्या अंमलबजावणीची जास्तीत जास्त संभाव्य संख्या, ज्याच्या मुख्य भागामध्ये संख्यांची तुलना आणि पुनर्रचना करणे आवश्यक आहे, 1 वरून n-1 पर्यंत वाढेल. तथापि, आतील लूप अशा प्रकारे आयोजित केले पाहिजे की जेव्हा स्थिती येते तेव्हा ती संपेल किंवा अंमलात आणली जाणार नाही: मागील ॲरे सेलमधील मूल्य सध्याच्या सेलपेक्षा कमी आहे.

आमच्या उदाहरणात:

जेव्हा i=2, सेल X 3 मधील 15 क्रमांक क्रमशः सेल X 2 मधील 34 क्रमांकासह आणि नंतर सेल X 1 मधील क्रमांक 21 सह स्थानांची देवाणघेवाण करतो,

जेव्हा i=4, सेल X 5 मधील 25 क्रमांक सेल X 3 मधील 34 क्रमांकासह बदलतो,

थेट समावेशन पद्धतीचा वापर करून ॲरे X चे पहिले n घटक चढत्या क्रमाने ऑर्डर करण्यासाठी प्रोग्रामचा एक तुकडा खाली आहे (ऑर्डरिंग कायम ठेवताना समावेश).

    i:=1 ते n-1 do साठी

  1. तर (एक्स 0) करा

  2. R:=X[j];

    X[j]:=X;

    X:=R;

ॲरेमधील संख्या उतरत्या क्रमाने ऑर्डर करण्यासाठी, प्रत्येक टप्प्यावर ॲरेच्या शेजारच्या सेलमधील संख्यांना विरुद्ध दिशेने बदलणे पुरेसे आहे, म्हणजे, शेजारच्या सेलच्या मूल्यांची देवाणघेवाण जेव्हा मागील एक वर्तमानापेक्षा कमी असेल तेव्हा.

थेट विनिमय पद्धत (बबल पद्धत).

ही पद्धत, मागील पद्धतीप्रमाणे, ॲरेच्या शेजारच्या पेशींच्या मूल्यांच्या देवाणघेवाणीवर आधारित आहे, परंतु अनुक्रमिक विश्लेषणाच्या अगदी पहिल्या टप्प्यापासून, ॲरेच्या एका टोकापासून दुसऱ्या टोकाकडे जाताना, सर्व जोड्या ॲरेच्या शेजारच्या पेशी गुंतलेल्या आहेत.

पहिल्या टप्प्यावर, क्रमशः, j = n, n-1, ..., 2 साठी, ॲरेच्या शेजारच्या सेलच्या मूल्यांची तुलना केली जाते आणि जर X j स्थिती<Х j-1 выполняется их перестановка, в результате чего наименьшее число оказывается в ячейке Х 1 .

आमच्या उदाहरणात, पहिली पायरी पूर्ण केल्यानंतर, ॲरेमधील डेटा याप्रमाणे स्थित असेल:

प्रत्येक पुढील चरणावर, तपासल्या जाणाऱ्या सेल जोड्यांची संख्या 1 ने कमी होईल. सर्वसाधारणपणे, कोणत्याही चरणावर i, i=1, 2, 3, ..., n-1, प्रक्रिया j पासून j साठी केली जाईल. n ते i+1, विशेषतः, i= n-1 साठी – फक्त एकदाच n-th आणि (n-1)-व्या पेशींसाठी.

वरीलवरून असे दिसून येते की थेट विनिमय पद्धत लागू करताना, बाह्य लूप n-1 वेळा कार्यान्वित करणे आवश्यक आहे आणि अंतर्गत लूपच्या अंमलबजावणीची संख्या, ज्याच्या मुख्य भागामध्ये संख्यांची तुलना आणि पुनर्रचना करणे आवश्यक आहे, कमी होईल. n-1 ते 1 पर्यंत.

"बबल पद्धत" या शब्दाची उत्पत्ती खालीलप्रमाणे स्पष्ट केली आहे: जर आपण वरपासून खालपर्यंत वाढत्या निर्देशांकासह ॲरे सेलच्या उभ्या व्यवस्थेची कल्पना केली, तर समजल्या जाणाऱ्या सर्वात लहान संख्या पाण्यातील बुडबुड्याप्रमाणे वर येईल.

आमच्या उदाहरणात

जेव्हा i=3 क्रमपरिवर्तन ॲरेच्या खालील स्थितीकडे नेईल

बबल पद्धत वापरताना, ॲरेमधील संख्यांच्या जोड्यांचे विश्लेषण निर्देशांक वाढवण्याच्या किंवा कमी करण्याच्या दिशेने जात आहे की नाही हे महत्त्वाचे नाही आणि क्रमवारीचा प्रकार (चढत्या किंवा उतरत्या) केवळ संख्यांच्या क्रमपरिवर्तनाच्या स्थितीनुसार निर्धारित केला जातो ( लहान एक मोठ्याच्या मागे किंवा त्याउलट स्थित असावा).

सुधारित थेट विनिमय पद्धत (सुधारित बबल पद्धत).

वरील संख्यात्मक उदाहरणावरून लक्षात येते की, चौथ्या पायरीनंतर ॲरे क्रमबद्ध झाला आहे, म्हणजेच बाह्य लूप n-1 वेळा नाही तर कमी चालवणे शक्य आहे, जेव्हा हे कळते की ॲरे आहे. आधीच ऑर्डर केले आहे. ही तपासणी खालील गोष्टींवर आधारित आहे: जर आतील लूपच्या अंमलबजावणीदरम्यान कोणतेही क्रमपरिवर्तन झाले नसेल, तर ॲरे आधीच ऑर्डर केली गेली आहे आणि तुम्ही बाह्य लूपमधून बाहेर पडू शकता. क्रमपरिवर्तन केले गेले आहे की नाही हे चिन्ह म्हणून बुलियन प्रकार व्हेरिएबल वापरले जाते: अंतर्गत लूप प्रविष्ट करण्यापूर्वी, त्यास एक मूल्य दिले जाते, उदाहरणार्थ, असत्य, आणि जेव्हा क्रमपरिवर्तन केले जाते, तेव्हा त्यास दुसरे मूल्य दिले जाते, उदाहरणार्थ, खरे.

साहजिकच, क्रमवारीच्या प्रक्रियेला गती देण्यासाठी सुधारित न केलेल्या पद्धतीच्या तुलनेत सुधारित बबल पद्धती वापरण्याचा परिणाम लक्षात येईल जर संख्यांचा मूळ क्रम इच्छित दिशेने क्रमबद्ध होण्याच्या जवळ असेल. अत्यंत प्रकरणात, जेव्हा ॲरे आधीच इच्छित पद्धतीने ऑर्डर केली जाते, तेव्हा बाह्य लूपचा मुख्य भाग फक्त एकदाच कार्यान्वित केला जाईल.

निवड प्रकारामागील कल्पना काय आहे?

  1. क्रमबद्ध न केलेल्या सबरेमध्ये, स्थानिक कमाल (किमान) शोधला जातो.
  2. आढळलेली कमाल (किमान) सबअरेमधील शेवटच्या (पहिल्या) घटकासह ठिकाणे बदलते.
  3. ॲरेमध्ये क्रमवारी न केलेले उपॲरे शिल्लक असल्यास, पॉइंट १ पहा.
एक लहान गेय विषयांतर. सुरुवातीला, माझ्या लेखांच्या मालिकेत, वर्गांची क्रमवारी काटेकोरपणे क्रमाने मांडण्याची मी योजना आखली. त्यानंतर, इतर इन्सर्शन अल्गोरिदमवर लेखांचे नियोजन केले गेले: सॉलिटेअर सॉर्ट, यंग टेबल सॉर्ट, इव्हर्जन सॉर्ट इ.

तथापि, आता नॉनलाइनरिटी ट्रेंडमध्ये आहे, म्हणून, इन्सर्शन सॉर्ट्सबद्दल सर्व प्रकाशने न लिहिता, आज मी निवड प्रकारांबद्दल एक समांतर धागा सुरू करेन. मग मी इतर अल्गोरिदमिक वर्गांसाठी असेच करेन: मर्ज सॉर्ट्स, डिस्ट्रिब्युशन सॉर्ट्स इ. सर्वसाधारणपणे, हे आपल्याला एका किंवा दुसर्या विषयावर प्रकाशने लिहिण्यास अनुमती देईल. अशा थीमॅटिक पर्यायाने ते अधिक मजेदार होईल.

निवड क्रमवारी:: निवड क्रमवारी


साधे आणि नम्र - आम्ही जास्तीत जास्त घटकाच्या शोधात ॲरेमधून जातो. सापडलेली कमाल शेवटच्या घटकासह स्वॅप केली जाते. ॲरेचा क्रम न लावलेला भाग एका घटकाने कमी झाला आहे (आम्ही सापडलेला कमाल हलवला तो शेवटचा घटक समाविष्ट करत नाही). आम्ही या क्रमबद्ध न केलेल्या भागावर समान क्रिया लागू करतो - आम्ही कमाल शोधतो आणि ॲरेच्या क्रमबद्ध न केलेल्या भागामध्ये शेवटच्या ठिकाणी ठेवतो. आणि ॲरेचा क्रमबद्ध न केलेला भाग एका घटकापर्यंत कमी होईपर्यंत आम्ही असेच चालू ठेवतो.

Def सिलेक्शन(डेटा): i, e in enumerate(data): mn = min(range(i, len(data)), key=data.__getitem__) डेटा[i], डेटा = डेटा, e डेटा परत करा

साधी निवड क्रमवारी एक क्रूर शक्ती दुहेरी शोध आहे. त्यात सुधारणा करता येईल का? चला काही बदल पाहू.

दुहेरी निवड क्रमवारी: दुहेरी निवड क्रमवारी


मध्ये समान कल्पना वापरली जाते, जी बबल सॉर्टचा एक प्रकार आहे. ॲरेच्या क्रमबद्ध न केलेल्या भागातून चालत असताना, जास्तीत जास्त व्यतिरिक्त, आम्हाला वाटेत किमान देखील सापडतो. आम्ही किमान प्रथम स्थानावर ठेवतो, जास्तीत जास्त शेवटी ठेवतो. अशा प्रकारे, क्रमवारी न केलेला भाग प्रत्येक पुनरावृत्तीवर दोन घटकांनी कमी केला जातो.

पहिल्या दृष्टीक्षेपात, असे दिसते की हे अल्गोरिदम 2 पटीने वाढवते - प्रत्येक पास केल्यानंतर, क्रमबद्ध न केलेला सबरे एका बाजूला नाही तर एकाच वेळी दोन्ही बाजूंनी कमी केला जातो. परंतु त्याच वेळी, तुलनांची संख्या दुप्पट झाली, तर स्वॅपची संख्या अपरिवर्तित राहिली. दुहेरी निवड अल्गोरिदमची गती फक्त किंचित वाढवते आणि काही भाषांमध्ये ते काही कारणास्तव हळू देखील कार्य करते.

निवड क्रमवारी आणि अंतर्भूत क्रमवारीतील फरक

असे दिसते की निवड क्रमवारी आणि क्रमवारी मूलत: समान गोष्ट आहे, अल्गोरिदमचा एक सामान्य वर्ग. विहीर, किंवा अंतर्भूत क्रमवारी - निवड क्रमवारीचा एक प्रकार. किंवा निवड क्रमवारी - इन्सर्टेशन सॉर्टचा एक विशेष केस. दोन्ही प्रकरणांमध्ये, आम्ही ॲरेच्या क्रमबद्ध नसलेल्या भागातून घटक काढतो आणि त्यांना क्रमवारीत पुनर्निर्देशित करतो.

मुख्य फरक: इन्सर्शन सॉर्टमध्ये आपण ॲरेच्या क्रमबद्ध न केलेल्या भागातून काढतो कोणतेहीघटक आणि क्रमवारी केलेल्या भागामध्ये त्याच्या जागी घाला. निवड क्रमवारीत आम्ही हेतुपुरस्सर शोधतो जास्तीत जास्तघटक (किंवा किमान) ज्यासह आम्ही ॲरेच्या क्रमबद्ध भागाला पूरक करतो. इन्सर्शनमध्ये, आम्ही पुढील घटक कोठे घालायचा ते शोधत आहोत आणि निवड करताना, आम्हाला आधीपासूनच माहित आहे की आम्ही ते कोणत्या ठिकाणी ठेवू, परंतु त्याच वेळी आम्हाला या स्थानाशी संबंधित घटक शोधण्याची आवश्यकता आहे.

हे अल्गोरिदमचे दोन्ही वर्ग त्यांच्या सार आणि वापरलेल्या पद्धतींमध्ये एकमेकांपासून पूर्णपणे भिन्न बनवते.

बिंगो क्रमवारी:: बिंगो क्रमवारी

निवड क्रमवारीचे एक मनोरंजक वैशिष्ट्य म्हणजे गती डेटाच्या क्रमवारीच्या स्वरूपावर अवलंबून नाही.

उदाहरणार्थ, जर ॲरे जवळजवळ क्रमवारी लावलेला असेल, तर, जसे ज्ञात आहे, इन्सर्टेशन सॉर्ट त्यावर खूप जलद प्रक्रिया करेल (जरी द्रुत क्रमवारीपेक्षा वेगवान). आणि इन्सर्टेशन सॉर्टसाठी रिव्हर्स-ऑर्डर केलेला ॲरे हा डीजेनरेट केस आहे;

आणि निवड क्रमवारीसाठी, ॲरेचे आंशिक किंवा उलट क्रमाने काही फरक पडत नाही - ते नियमित यादृच्छिक गतीने अंदाजे समान वेगाने प्रक्रिया करेल. तसेच, शास्त्रीय निवडीच्या क्रमवारीसाठी, ॲरेमध्ये अद्वितीय किंवा पुनरावृत्ती घटकांचा समावेश आहे की नाही हे महत्त्वाचे नाही - याचा वेगावर व्यावहारिकपणे कोणताही परिणाम होत नाही.

परंतु तत्त्वतः, आपण सर्जनशील होऊ शकता आणि अल्गोरिदम सुधारित करू शकता जेणेकरून ते काही डेटा सेटसाठी जलद कार्य करेल. उदाहरणार्थ, ॲरेमध्ये डुप्लिकेट घटक असल्यास बिंगो क्रमवारी विचारात घेतली जाते.

येथे युक्ती अशी आहे की अक्रमित भागात, केवळ कमाल घटक लक्षात ठेवला जात नाही तर पुढील पुनरावृत्तीसाठी कमाल देखील निर्धारित केली जाते. हे तुम्हाला, मॅक्सिमाची पुनरावृत्ती करण्याच्या बाबतीत, प्रत्येक वेळी त्यांना पुन्हा शोधण्याची परवानगी देते, परंतु ॲरेमध्ये ही कमाल पुन्हा एकदा समोर येताच त्यांना लगेच त्यांच्या जागी ठेवण्याची परवानगी देते.

अल्गोरिदमिक जटिलता समान राहते. परंतु जर ॲरेमध्ये पुनरावृत्ती होणाऱ्या संख्यांचा समावेश असेल, तर बिंगो क्रमवारी नियमित निवडीच्या क्रमवारीपेक्षा दहापट जलद होईल.

# बिंगो क्रमवारी def बिंगो(डेटा): # प्रथम पास. कमाल = len(डेटा) - 1 नेक्स्टव्हॅल्यू = श्रेणीतील i साठी डेटा(कमाल - 1, -1, -1): जर डेटा[i] > nextValue: nextValue = डेटा[i] तर कमाल आणि डेटा == पुढील मूल्य: कमाल -= 1 # त्यानंतरचे पास. कमाल असताना: मूल्य = nextValue nextValue = श्रेणीतील i साठी डेटा(कमाल - 1, -1, -1): जर डेटा[i] == मूल्य: डेटा[i], डेटा = डेटा, डेटा[i] कमाल -= 1 elif डेटा[i] > nextValue: nextValue = data[i] तर कमाल आणि डेटा == nextValue: कमाल -= 1 रिटर्न डेटा

सायकल क्रमवारी:: सायकल क्रमवारी

चक्रीय वर्गीकरण मनोरंजक आहे (आणि व्यावहारिक दृष्टिकोनातून मौल्यवान) कारण ॲरेच्या घटकांमध्ये बदल घडतात आणि जर घटक त्याच्या अंतिम जागी ठेवला असेल तरच. ॲरे पुन्हा लिहिणे खूप महाग असल्यास हे उपयुक्त ठरू शकते आणि भौतिक मेमरीची काळजी घेण्यासाठी, तुम्हाला ॲरे घटकांमधील बदलांची संख्या कमी करणे आवश्यक आहे.

हे असे कार्य करते. चला ॲरेमधून जाऊ या आणि या बाह्य लूपमधील पुढील सेल X ला कॉल करू. आणि या सेलमधून पुढील घटक घालण्यासाठी ॲरेमध्ये कोणत्या ठिकाणी आपण पाहतो. ज्या ठिकाणी तुम्हाला पेस्ट करण्याची आवश्यकता आहे तेथे आणखी काही घटक आहे, आम्ही ते क्लिपबोर्डवर पाठवतो. बफरमधील या घटकासाठी, आम्ही ॲरेमध्ये त्याचे स्थान देखील शोधतो (आणि ते या ठिकाणी घाला आणि या ठिकाणी संपणारा घटक बफरला पाठवू). आणि बफरमधील नवीन क्रमांकासाठी आम्ही समान क्रिया करतो. ही प्रक्रिया किती काळ चालू ठेवायची? जोपर्यंत क्लिपबोर्डमधील पुढील घटक सेल X मध्ये समाविष्ट करणे आवश्यक असलेला घटक बनत नाही तोपर्यंत (अल्गोरिदमच्या मुख्य लूपमधील ॲरेमधील वर्तमान स्थान). लवकरच किंवा नंतर हा क्षण होईल आणि नंतर बाह्य लूपमध्ये आपण पुढील सेलमध्ये जाऊ शकता आणि त्यासाठी समान प्रक्रिया पुन्हा करू शकता.

इतर निवड प्रकारांमध्ये, आम्ही त्यांना शेवटच्या/प्रथम स्थानावर ठेवण्यासाठी कमाल/किमान शोधतो. सायकल क्रमवारीत, असे दिसून येते की उपॲरेमध्ये किमान प्रथम स्थानावर आहे, जसे की, इतर अनेक घटक ॲरेच्या मध्यभागी कुठेतरी त्यांच्या योग्य ठिकाणी ठेवण्याच्या प्रक्रियेत.

आणि येथे अल्गोरिदमिक जटिलता देखील O( मध्ये राहते. n 2). सराव मध्ये, चक्रीय क्रमवारी नियमित निवडीच्या क्रमवारीपेक्षा कित्येक पटीने हळू असते, कारण तुम्हाला ॲरेमधून अधिक धावावे लागते आणि अधिक वेळा तुलना करावी लागते. पुनर्लेखनाच्या किमान संभाव्य संख्येसाठी ही किंमत आहे.

# cyclic sorting def cycle(data): # आम्ही range(0, len(data) - 1 मधील सायकलस्टार्ट साठी चक्रीय चक्रांच्या शोधात ॲरेमधून जातो: मूल्य = डेटा # आम्ही घटक pos = cycleStart कुठे घालायचा ते शोधतो श्रेणीतील i साठी (सायकलस्टार्ट + 1, लेन(डेटा)): जर डेटा[i]< value: pos += 1 # Если элемент уже стоит на месте, то сразу # переходим к следующей итерации цикла if pos == cycleStart: continue # В противном случае, помещаем элемент на своё # место или сразу после всех его дубликатов while value == data: pos += 1 data, value = value, data # Циклический круговорот продолжается до тех пор, # пока на текущей позиции не окажется её элемент while pos != cycleStart: # Ищем, куда переместить элемент pos = cycleStart for i in range(cycleStart + 1, len(data)): if data[i] < value: pos += 1 # Помещаем элемент на своё место # или сразу после его дубликатов while value == data: pos += 1 data, value = value, data return data

पॅनकेक वर्गीकरण

एक अल्गोरिदम ज्यामध्ये जीवनाच्या सर्व स्तरांवर प्रभुत्व मिळवले आहे - पासून ते.

सर्वात सोप्या आवृत्तीमध्ये, आम्ही ॲरेच्या क्रमबद्ध न केलेल्या भागामध्ये जास्तीत जास्त घटक शोधतो. जेव्हा कमाल आढळते, तेव्हा आम्ही दोन तीक्ष्ण वळण करतो. प्रथम, आम्ही घटकांची साखळी फ्लिप करतो जेणेकरून जास्तीत जास्त विरुद्ध टोकाला असेल. मग आम्ही संपूर्ण क्रमबद्ध न केलेले सबरे फ्लिप करतो, परिणामी जास्तीत जास्त ठिकाणी घसरण होते.

अशा कॉर्डबॅलेट्स, सामान्यतः, O( च्या अल्गोरिदमिक जटिलतेस कारणीभूत ठरतात. n 3). हे प्रशिक्षित सिलीएट्स आहेत जे एका झटक्यात अडकतात (म्हणून, त्यांच्या कार्यक्षमतेमध्ये O( ची जटिलता असते) n 2)), आणि प्रोग्रामिंग करताना, ॲरेचा भाग उलट करणे ही अतिरिक्त लूप असते.

पॅनकेक क्रमवारी लावणे गणिताच्या दृष्टिकोनातून खूप मनोरंजक आहे (सर्वोत्तम विचारांनी क्रमवारी लावण्यासाठी पुरेशी किमान वळणांची संख्या मोजण्याचा विचार केला आहे) समस्येचे अधिक जटिल सूत्र आहेत (तथाकथित जळलेल्या बाजूसह). पॅनकेक्सचा विषय अत्यंत मनोरंजक आहे, कदाचित मी या मुद्द्यांवर अधिक तपशीलवार मोनोग्राफ लिहीन.

# पॅनकेक सॉर्ट डीफ पॅनकेक(डेटा): इफ len(डेटा) > 1: श्रेणीतील आकारासाठी(len(डेटा), 1, -1): # क्रमवारी न केलेल्या भागामध्ये कमालची स्थिती maxindex = कमाल(श्रेणी(आकार) , key = data.__getitem__) जर maxindex + 1 != आकार: # जर कमाल शब्द नसेल, तर तुम्हाला ते उलट करावे लागेल जर maxindex != 0: # ते फ्लिप करा # जेणेकरून कमाल डाव्या डेटावर असेल[: maxindex+1] = उलट (डेटा[:maxindex +1]) # ॲरेचा क्रम न लावलेला भाग उलटा, # कमाल स्थान डेटामध्ये येते[:size] = उलट (डेटा[:size]) डेटा परत करा

निवड क्रमवारी केवळ ॲरेच्या क्रमबद्ध न केलेल्या भागामध्ये किमान/जास्तीत जास्त घटक शोधण्याइतकीच प्रभावी आहे. आज विश्लेषित केलेल्या सर्व अल्गोरिदममध्ये, शोध दुहेरी शोधाच्या स्वरूपात केला जातो. आणि दुहेरी शोध, तुम्ही ते कसे पहाता हे महत्त्वाचे नाही, नेहमी अल्गोरिदमिक जटिलता O( पेक्षा चांगली नसते n 2). याचा अर्थ असा होतो की सर्व निवड प्रकारांचा अर्थ चौरस जटिलतेसाठी नशिबात आहे? मुळीच नाही, जर शोध प्रक्रिया मूलभूतपणे वेगळ्या पद्धतीने आयोजित केली असेल. उदाहरणार्थ, डेटा सेटचा ढीग म्हणून विचार करा आणि ढीगमध्ये शोधा. तथापि, ढीगांचा विषय हा एक लेख नसून संपूर्ण गाथा आहे, परंतु आपण दुसर्या वेळी नक्कीच बोलू.

निवडीनुसार क्रमवारी लावत आहेअंमलात आणण्यासाठी कदाचित सर्वात सोपा क्रमवारी अल्गोरिदम आहे. इतर समान अल्गोरिदम प्रमाणे, ते तुलना ऑपरेशनवर आधारित आहे. प्रत्येक घटकाची प्रत्येक घटकाशी तुलना करून आणि आवश्यक असल्यास, विनिमय करून, पद्धत आवश्यक क्रमबद्ध फॉर्ममध्ये क्रम आणते.

अल्गोरिदमची कल्पना अगदी सोपी आहे. एक ॲरे असू द्या आकार n, नंतर निवड क्रमवारी खालीलप्रमाणे येते:

1. क्रमाचा पहिला घटक घ्या [i], येथे i- घटक क्रमांक, प्रथम i 1 च्या बरोबरीचे;

2. अनुक्रमाचा किमान (जास्तीत जास्त) घटक शोधा आणि त्याची संख्या व्हेरिएबलमध्ये साठवा की;

3. पहिल्या घटकाची संख्या आणि सापडलेल्या घटकाची संख्या जुळत नसल्यास, म्हणजे जर की≠1, नंतर हे दोन घटक मूल्यांची देवाणघेवाण करतात, अन्यथा कोणतेही फेरफार होत नाही;

4. वाढ i 1 द्वारे आणि उर्वरित ॲरेची क्रमवारी लावणे सुरू ठेवा, म्हणजे घटक क्रमांक 2 पासून n, घटक पासून आधीच त्याचे स्थान घेत आहे.

त्यानंतरच्या प्रत्येक पायरीसह, अल्गोरिदम कार्य करत असलेल्या सबरेचा आकार 1 ने कमी होतो, परंतु याचा क्रमवारी पद्धतीवर परिणाम होत नाही.

पूर्णांकांच्या विशिष्ट अनुक्रमाचे उदाहरण वापरून अल्गोरिदमच्या ऑपरेशनचा विचार करूया. 9, 1, 4, 7, 5 पाच पूर्णांकांचा समावेश असलेला ॲरे (Fig. 6.2) दिलेला आहे. तुम्हाला निवड क्रमवारी वापरून त्याचे घटक चढत्या क्रमाने मांडावे लागतील. चला क्रमाने घटकांची तुलना करूया. दुसरा घटक पहिल्यापेक्षा कमी आहे - हे लक्षात ठेवा ( की=2). पुढे, आम्ही पाहतो की ते इतर सर्वांपेक्षा लहान देखील आहे आणि पासून की≠1, पहिला आणि दुसरा घटक स्वॅप करा. चला उर्वरित भाग ऑर्डर करणे सुरू ठेवूया, 9 मूल्य असलेल्या घटकासाठी बदली शोधण्याचा प्रयत्न करूया. आता मध्ये की 3 प्रविष्ट केले जाईल, कारण घटक क्रमांक 3 चे मूल्य सर्वात कमी आहे. पाहिल्याप्रमाणे, की≠2, म्हणून, आम्ही 2रा आणि 3रा घटक स्वॅप करतो. पुढच्या पायरीवर सबॅरेचा आकार 1 च्या बरोबरीचा होईपर्यंत आम्ही घटकांना जागी ठेवणे सुरू ठेवतो.

आकृती 6.2 – निवड क्रमवारीचे उदाहरण

C++ मध्ये प्रोग्राम कोड:

void SelectionSort(int A, int n) //निवड क्रमवारी

साठी (i=0; i

संख्या=अ[i]; key=i;

साठी (j=i+1; j

जर (A[j]

cout<<"Результирующий массив: ";

साठी (i=0; i

शून्य मुख्य() //मुख्य कार्य

cout<<"Количество элементов >"; cin>>n;

साठी (i=0; i

cout< ";


निवड क्रम (ए, एन);

पास्कल मधील प्रोग्राम कोड:

टाइप करा arr = पूर्णांकाचा ॲरे;

var i, j, n: पूर्णांक;

प्रक्रिया निवड क्रम (A: arr; n: integer); (निवडानुसार क्रमवारी लावा)

var की, गणना: पूर्णांक;

i:=1 ते n करण्यासाठी

संख्या:=A[i]; की:=i;

j:=i+1 ते n डू साठी

जर (A>A[j]) तर key:=j;

जर (की<>मग मी

लिहा("परिणाम ॲरे:");

i साठी:=1 ते n लिहा(A[i], " "); (ॲरे आउटपुट)

प्रारंभ (मुख्य प्रोग्राम ब्लॉक)

लिहा("घटकांची संख्या >");

i साठी:=1 ते n do (ॲरे इनपुट)

लिहा(i," घटक > ");

निवड क्रम (ए, एन);

निवड क्रमवारी लागू करणे सोपे आहे आणि काही परिस्थितींमध्ये ते अधिक जटिल आणि प्रगत पद्धतींपेक्षा श्रेयस्कर असू शकते. परंतु बहुतेक प्रकरणांमध्ये, हे अल्गोरिदम नंतरच्या तुलनेत कार्यक्षमतेमध्ये निकृष्ट आहे, कारण सर्वात वाईट, सर्वोत्तम आणि सरासरी प्रकरणांमध्ये याची आवश्यकता असेल (n२) वेळ.