2011-01-04 17 views
8

एक अनुकूलन समस्या में मैं एक कतार में कई उम्मीदवार समाधान रखता हूं जो मैं उनके प्राथमिकता के अनुसार जांचता हूं।सबसे प्रासंगिक वस्तुओं के साथ बड़ी प्राथमिकता कतार कैसे रखें?

प्रत्येक बार जब मैं एक उम्मीदवार को संभालता हूं, तो इसे कतार के रूप में हटा दिया जाता है लेकिन यह कई नए उम्मीदवारों को उत्पन्न करता है जिससे कैडिडेट्स की संख्या तेजी से बढ़ती है। इसे संभालने के लिए मैं प्रत्येक उम्मीदवार को प्रासंगिकता असाइन करता हूं, जब कोई उम्मीदवार कतार में जोड़ा जाता है, यदि कोई और स्थान उपलब्ध नहीं है, तो मैं कम से कम प्रासंगिक वर्तमान में कतार में उम्मीदवार को प्रतिस्थापित करता हूं (यदि एप्रोपीएट) ।

यह कुशलतापूर्वक करने के लिए मैं उम्मीदवारों और दो जुड़े अप्रत्यक्ष बाइनरी ढेर के साथ एक बड़ा (निश्चित आकार) सरणी रखता हूं: कोई उम्मीदवारों को प्राथमिकता आदेश कम करने में और दूसरे को आरोही प्रासंगिकता में संभालता है।

यह मेरे उद्देश्यों के लिए पर्याप्त कुशल है और आवश्यक पूरक स्थान लगभग 4 इंच/उम्मीदवार है जो उचित भी है। हालांकि यह कोड के लिए जटिल है, और यह इष्टतम प्रतीत नहीं होता है।

मेरा प्रश्न यह है कि यदि आप दक्षता खोए बिना इस कार्य को निष्पादित करने के लिए अधिक पर्याप्त डेटा संरचना या अधिक प्राकृतिक तरीके से जानते हैं।

+0

एक्स कम से कम प्रासंगिक/पूर्व उम्मीदवारों को सम्मिलित करने के बारे में क्या नहीं है? एक घातीय वृद्धि के साथ, वैसे भी उन तक पहुंचा नहीं जाएगा। कतार के प्रारंभिक डेटा प्राप्त करने के लिए आप कतार के आकार के आधार पर एक्स को अलग करना चाहते हैं। लेकिन फिर भी, आपकी कतार भर जाएगी, क्या स्टॉप हालत है? –

+0

@TomWij आप नहीं जानते कि वे कम से कम प्रासंगिक हैं जब तक कि आप कुछ उम्मीदवारों को बदतर न करें। समस्याओं में मुझे दिलचस्पी है कि हमें कोई स्टॉप कंडीशन नहीं है –

+1

जब मैं एक नया उम्मीदवार उत्पन्न करता हूं तो मैं एक साधारण आसानी से गणना करने योग्य संपत्ति के आधार पर एक मूल्य की गणना करता हूं जो मुझे लगता है कि शायद अधिक अच्छा समाधान उत्पन्न होगा। तो प्रासंगिकता एक ह्युरिस्टिक है जिसे कुछ अन्य उम्मीदवारों (और उनके वंश) को दूसरों के ऊपर _a priory_ पसंद करते हैं, मुझे यकीन नहीं है कि इसे कैसे कॉल किया जाए। –

उत्तर

6

यहाँ एक कुशल समाधान है कि एक सामान्य ढेर से अधिक समय और स्थान जटिलता परिवर्तन नहीं करता है:

एक मिनट-ढेर में, हर नोड अपने दोनों बच्चों से कम है। अधिकतम-ढेर में, प्रत्येक नोड अपने बच्चों से बड़ा होता है। आइए इसे प्रत्येक स्तर के लिए एक न्यूनतम और अधिकतम संपत्ति के बीच वैकल्पिक करें: प्रत्येक विषम पंक्ति अपने बच्चों और उसके पोते से भी कम है, और यहां तक ​​कि पंक्तियों के विपरीत भी है। फिर सबसे छोटा नोड ढूंढना सामान्य जैसा ही होता है, और सबसे बड़ा नोड खोजने के लिए जरूरी है कि हम रूट के बच्चों को देखें और सबसे बड़ा लें। बुलबुले नोड्स (सम्मिलन के लिए) थोड़ा सा चालक बन जाता है, लेकिन यह अभी भी वही ओ (लॉगएन) जटिलता है।

क्षमता का ट्रैक रखना और सबसे छोटा (कम से कम प्रासंगिक) नोड पॉपिंग करना आसान हिस्सा है।

संपादित करें: यह एक मानक न्यूनतम अधिकतम ढेर प्रतीत होता है! विवरण के लिए here देखें। एक सी कार्यान्वयन है: header, source और example। यहाँ एक उदाहरण ग्राफ है:

http://internet512.chonbuk.ac.kr/datastructure/heap/img/heap8.jpg

+0

@marcog +1 विश्वविद्यालय में, बहुत रोचक नहीं सीखा है। –

+1

@Esteban http://stackoverflow.com/questions/2252793/is-there-ac-minmax-heap-implementation –

+0

@ टॉमविज़ ओह, तो मुझे लगता है कि एक मानक डेटा-संरचना है :)/मुझे लगता है कि यह तुलना कैसे करता है मेरे विचार के लिए। – marcog

1

"इष्टतम" की रूपरेखा के बिना (असंभव के पास) का न्याय करने के लिए कठिन है।

कभी-कभी 'गूंगा' एल्गोरिदम सबसे तेज़ हो सकता है क्योंकि इंटेल सीपीयू स्मृति के संगत ब्लॉक पर गूंगा सरणी स्कैन पर अविश्वसनीय रूप से तेज़ होते हैं, खासकर यदि लूप और डेटा ऑन-चिप फिट हो सकते हैं। इसके विपरीत, मेमोरी के बड़े ब्लॉक में पॉइंटर्स के चारों ओर कूदते हुए जो ऑन-चिप फिट नहीं होता है, वह दस या सैकड़ों या धीमे हो सकते हैं।

जब आप 'चालाक' डेटा संरचना लॉकिंग शुरू करते हैं तो आपके मुद्दों को समानांतर करने का प्रयास करते समय आपको समस्याएं भी हो सकती हैं, इस प्रकार एकाधिक धागे को एक साथ प्रगति से रोकने से रोकती है।

मैं आपके वर्तमान, न्यूनतम-अधिकतम दृष्टिकोण और एक सरल सरणी स्कैन (कोई लिंक्ड सूचियों = कम स्मृति) दोनों को प्रोफाइल करने की अनुशंसा करता हूं ताकि यह देखने के लिए कि कौन सा सर्वश्रेष्ठ प्रदर्शन करता है। ऐसा लगता है कि अजीब लगता है, मैंने अभ्यास में सरल सरणी स्कैन द्वारा पीटा लिंक वाली सूचियों के साथ 'चालाक' एल्गोरिदम देखा है क्योंकि सरल दृष्टिकोण कम स्मृति का उपयोग करता है, इसमें एक कड़ा लूप होता है और सीपीयू अनुकूलन से अधिक लाभ होता है।आप उम्मीदवारों को आयोजित एक निश्चित आकार सरणी के साथ स्मृति आवंटन और कचरा संग्रहण मुद्दों से भी संभावित रूप से बचें।

एक विकल्प जो आप समाधान पर विचार करना चाहते हैं कि समाधान कम बार-बार छिड़कने और हर बार अधिक तत्वों को हटाने के लिए है। उदाहरण के लिए, प्रत्येक प्रुन ऑपरेशन पर 100 तत्वों को हटाने का मतलब है कि आपको केवल 100 वें समय की आवश्यकता है। इससे तत्वों को जोड़ने और हटाने के लिए एक और विषम दृष्टिकोण की अनुमति मिल सकती है।

लेकिन कुल मिलाकर, केवल ध्यान रखें कि ऑप्टिमाइज़ेशन के लिए कंप्यूटर-साइंस दृष्टिकोण हमेशा और कल के हार्डवेयर पर उच्च प्रदर्शन के लिए व्यावहारिक दृष्टिकोण नहीं है।

+0

आपके सुझावों के लिए धन्यवाद, मैं आपके विचारों में आपसे सहमत हूं। इस मामले में हालांकि, मैं एक बहुत बड़ी सरणी को संभालने में कामयाब रहा हूं, जो स्कैन अव्यवहारिक बनाता है। द्विआधारी ढेर सैद्धांतिक रूप से और व्यावहारिक रूप से बहुत ही कुशल डेटा संरचना है और मुझे आशा है कि मेरी समस्या में कुछ भिन्नता का उपयोग किया जा सकता है। –

1

यदि आप ढेर के बजाय skip-lists का उपयोग करते हैं तो आपके पास O (logn) में अभी भी खोज करते समय तत्वों को हटाने के लिए O (1) समय होगा।
दूसरी तरफ एक स्किप सूची को कार्यान्वित करना कठिन होता है और बाइनरी ढेर की तुलना में अधिक जगह का उपयोग करता है।

संबंधित मुद्दे