मैं the claim पर संदेह कर रहा हूं कि शुद्ध कार्यात्मक आमतौर पर ओ (लॉग एन) होता है। एडवर्ड Kmett के जवाब भी देखें जो दावा करता है।यद्यपि यह सैद्धांतिक अर्थ में यादृच्छिक उत्परिवर्तनीय सरणी पहुंच पर लागू हो सकता है, लेकिन यादृच्छिक उत्परिवर्तनीय सरणी का उपयोग शायद यह नहीं है कि किसी भी एल्गोरिदम की आवश्यकता होती है, जब इसे दोहराने योग्य संरचना के लिए सही ढंग से अध्ययन किया जाता है, यानी यादृच्छिक नहीं है। मुझे लगता है कि जब एडवर्ड Kmett लिखता है, "अद्यतनों के इलाके का फायदा उठाते हैं"।
मुझे लगता है कि ओ (1) एन-क्वींस एल्गोरिदम के शुद्ध कार्यात्मक संस्करण में सैद्धांतिक रूप से संभव है, डिफएरे के लिए एक पूर्ववत विधि जोड़कर, जो डुप्लिकेट को हटाने और उन्हें फिर से चलाने से बचने के लिए मतभेदों में एक नजर डालने का अनुरोध करता है।
यदि बैकट्रैकिंग एन-क्वींस एल्गोरिदम संचालित करने के तरीके की मेरी समझ में सही है, तो डिफएरे के कारण होने वाली मंदी इसलिए है क्योंकि अनावश्यक अंतर बनाए रखा जा रहा है।
अमूर्त में, "डिफएरे" (आवश्यक रूप से हास्केल) के पास एक सेट तत्व विधि नहीं है (या हो सकती है) जो सरणी की एक नई प्रतिलिपि देता है और मूल प्रतिलिपि के साथ एक अंतर रिकॉर्ड स्टोर करता है, जिसमें पॉइंटर शामिल है नई बदली गई प्रति। जब मूल प्रति को किसी तत्व तक पहुंचने की आवश्यकता होती है, तो वर्तमान प्रतिलिपि की प्रतिलिपि में बदलावों को पूर्ववत करने के लिए अंतरों की इस सूची को फिर से चलाया जाना चाहिए। ध्यान दें कि यहां तक कि ओवरहेड भी है कि इसे सिंगल-लिंक्ड सूची को अंत तक चलाना होगा, इसे दोबारा चलाने से पहले।
कल्पना कीजिए कि इन्हें डबल-लिंक्ड सूची के रूप में संग्रहीत किया गया था, और निम्नानुसार एक पूर्ववत ऑपरेशन था।
एक अमूर्त वैचारिक स्तर से, बैकट्रैकिंग एन-क्वींस एल्गोरिदम क्या करता है जो बूलियन के कुछ सरणी पर फिर से चल रहा है, जो कि प्रत्येक रिकर्सिव स्तर पर उन सरणी में रानी की स्थिति को आगे बढ़ाता है। this animation देखें।
केवल मेरे सिर में यह काम करना, मुझे लगता है कि डिफएरे इतनी धीमी है, क्योंकि रानी एक स्थिति से दूसरी स्थिति में स्थानांतरित हो जाती है, तो मूल स्थिति के लिए बूलियन ध्वज झूठ पर सेट होता है और नई स्थिति को सत्य पर सेट किया गया है, और इन मतभेदों को रिकॉर्ड किया गया है, फिर भी वे अनावश्यक हैं क्योंकि जब रिवर्स में फिर से चलाया जाता है, तो सरणी शुरू होने से पहले सरणी उसी मान के साथ समाप्त होती है। इस प्रकार झूठी पर वापस सेट करने के लिए एक सेट ऑपरेशन का उपयोग करने के बजाय, एक पूर्ववत विधि कॉल की आवश्यकता होती है, वैकल्पिक रूप से एक इनपुट पैरामीटर के साथ जो डिफएरे को बताता है कि अंतर की उपरोक्त डबल-लिंक्ड सूची में खोज करने के लिए "पूर्ववत करें" मान क्या है। यदि वह "पूर्ववत करें" मान डबल-लिंक्ड सूची में एक अंतर रिकॉर्ड में पाया जाता है, तो सूची खोज में वापस चलते समय पाए गए उसी सरणी तत्व पर कोई विरोधाभासी मध्यवर्ती परिवर्तन नहीं होता है, और वर्तमान मान "पूर्ववत करें" के बराबर होता है उस अंतर रिकॉर्ड में मूल्य, तो रिकॉर्ड हटाया जा सकता है और उस पुरानी प्रति को डबल-लिंक्ड सूची में अगले रिकॉर्ड पर फिर से इंगित किया जा सकता है।
बैकट्रैकिंग पर पूरे सरणी की अनावश्यक प्रतिलिपि को हटाने के लिए यह क्या होता है। अंतर रिकॉर्ड के जोड़ को जोड़ने और पूर्ववत करने के लिए एल्गोरिदम के अनिवार्य संस्करण की तुलना में कुछ अतिरिक्त ओवरहेड अभी भी है, लेकिन यह निरंतर समय के करीब हो सकता है, यानी ओ (1)।
यदि मैं एन-क्वीन एल्गोरिदम को सही ढंग से समझता हूं, तो पूर्ववत ऑपरेशन के लिए लुकबैक केवल एक है, इसलिए कोई पैदल चलना नहीं है। इस प्रकार रानी की स्थिति को स्थानांतरित करते समय सेट तत्व के अंतर को स्टोर करना भी आवश्यक नहीं है, क्योंकि पुराने प्रतिलिपि तक पहुंचने से पहले इसे पूर्ववत कर दिया जाएगा। हमें इस प्रकार को सुरक्षित रूप से व्यक्त करने का एक तरीका चाहिए, जो करना आसान है, लेकिन मैं इसे पाठक के लिए एक अभ्यास के रूप में छोड़ दूंगा, क्योंकि यह पोस्ट पहले से ही बहुत लंबा है।
अद्यतन: मैं पूरे एल्गोरिथ्म के लिए कोड लिखा गया है, लेकिन मेरे सिर में एन-रानियों के साथ प्रत्येक दोहराया पंक्ति में, एक गुना विकर्णों को निम्नलिखित सरणी, जहां प्रत्येक तत्व पर लागू किया जा सकता ट्रिपल टुपल का है: (जिस पंक्ति पर यह कब्जा कर लिया गया है या कोई नहीं, पंक्ति सूचकांक की सरणी बाएं-दाएं विकर्ण को छेड़छाड़ करती है, पंक्ति सूचकांक की सरणी दाएं-बाएं विकर्ण को छेड़छाड़ करती है)।पंक्तियों को रिकर्सन या पंक्ति सूचकांक की एक सरणी के गुना के साथ पुनरावृत्त किया जा सकता है (गुना रिकर्सन करता है)।
यहां डेटा संरचना के लिए इंटरफेस का पालन करता है I कल्पना। नीचे दिए गए वाक्यविन्यास कोप्यूट है, लेकिन मुझे लगता है कि यह स्कैला के करीब है, कि आप समझ सकते हैं कि क्या इरादा है।
ध्यान दें कि यदि यह बहुप्रचारित है तो डिफएरे के किसी भी कार्यान्वयन को अनुचित रूप से धीमा कर दिया जाएगा, लेकिन एन-क्वींस बैकट्रैकिंग एल्गोरिदम को डिफएरे को बहुप्रचारित करने की आवश्यकता नहीं है। इस जवाब के लिए टिप्पणियों में इंगित करने के लिए एडवर्ड Kmett के लिए धन्यवाद।
interface Array[T]
{
setElement : Int -> T -> Array[T] // Return copy with changed element.
setElement : Int -> Maybe[T] -> Array[T]
array :() -> Maybe[DiffArray[T]]// Return copy with the DiffArray interface, or None if first called setElement() before array().
}
// An immutable array, typically constructed with Array().
//
// If first called setElement() before array(), setElement doesn't store differences,
// array will return None, and thus setElement is as fast as a mutable imperative array.
//
// Else setElement stores differences, thus setElement is O(1) but with a constant extra overhead.
// And if setElement has been called, getElement incurs an up to O(n) sequential time complexity,
// because a copy must be made and the differences must be applied to the copy.
// The algorithm is described here:
// http://stackoverflow.com/questions/1255018/n-queens-in-haskell-without-list-traversal/7194832#7194832
// Similar to Haskell's implementation:
// http://www.haskell.org/haskellwiki/Arrays#DiffArray_.28module_Data.Array.Diff.29
// http://www.haskell.org/pipermail/glasgow-haskell-users/2003-November/005939.html
//
// If a multithreaded implementation is used, it can be extremely slow,
// because there is a race condition on every method, which requires internal critical sections.
interface DiffArray[T] inherits Array[T]
{
unset :() -> Array[T] // Return copy with the previous setElement() undone, and its difference removed.
getElement : Int -> Maybe[T] // Return the the element, or None if element is not set.
}
// An immutable array, typically constructed with Array(...) or Array().array.
अद्यतन: मैं Scala implementation है, जो एक बेहतर interface है क्या मैं ऊपर का सुझाव दिया था की तुलना में पर काम कर रहा हूँ। मैंने यह भी समझाया है कि फ़ोल्ड्स के लिए अनुकूलन एक म्यूटेबल सरणी के समान स्थिर ओवरहेड तक कैसे पहुंचता है।
क्या ट्रेलर सरणी कहीं भी हास्केल के लिए लागू की गई हैं? – is7s