डबल-एंडेड कतार: Difference between revisions

From Vigyanwiki
(Created page with "{{redirect-distinguish2|Deque|dequeueing, a queue operation}} {{Distinguish|Double-ended priority queue}} {{tooshort|date=April 2022}} {{technic...")
 
No edit summary
Line 1: Line 1:
{{redirect-distinguish2|Deque|dequeueing, a [[queue (abstract data type)|queue]] operation}}
"डीक्यू" यहां पुनर्निर्देश करता है। डीक्यूइंग, क्यू संचालन के साथ भ्रमित नहीं होना चाहिए।
{{Distinguish|Double-ended priority queue}}
{{tooshort|date=April 2022}}
{{technical|date=April 2022}}


[[कंप्यूटर विज्ञान]] में, एक डबल-एंडेड कतार (संक्षिप्त रूप से डेक, उच्चारित 'डेक', चेक की तरह<ref>Jesse Liberty; Siddhartha Rao; Bradley Jones. ''C++ in One Hour a Day, Sams Teach Yourself'', Sixth Edition. Sams Publishing, 2009. {{ISBN|0-672-32941-7}}. Lesson 18: STL Dynamic Array Classes, pp. 486.</ref>) एक [[सार डेटा प्रकार]] है जो एक [[कतार (डेटा संरचना)]] को सामान्यीकृत करता है, जिसके लिए तत्वों को सामने (सिर) या पीछे (पूंछ) से जोड़ा या हटाया जा सकता है।<ref>[[Donald Knuth]]. ''[[The Art of Computer Programming]]'', Volume 1: ''Fundamental Algorithms'', Third Edition. Addison-Wesley, 1997. {{ISBN|0-201-89683-4}}. Section 2.2.1: Stacks, Queues, and Deques, pp. 238&ndash;243.</ref> इसे अक्सर हेड-टेल लिंक्ड लिस्ट भी कहा जाता है, हालांकि ठीक से यह एक डेक की एक विशिष्ट [[डेटा संरचना]] ''#कार्यान्वयन'' को संदर्भित करता है (नीचे देखें)।
डबल-एंडेड प्राथमिकता क्यू के साथ भ्रमित नहीं होना चाहिए।


== नामकरण परंपराएं ==
[[कंप्यूटर विज्ञान]] में,  डबल-एंडेड क्यू  (संक्षिप्त रूप से डीक्यू, स्पष्ट 'डेक', जैसे चेक<ref>Jesse Liberty; Siddhartha Rao; Bradley Jones. ''C++ in One Hour a Day, Sams Teach Yourself'', Sixth Edition. Sams Publishing, 2009. {{ISBN|0-672-32941-7}}. Lesson 18: STL Dynamic Array Classes, pp. 486.</ref>) एक [[सार डेटा प्रकार|अमूर्त डेटा प्रकार]] है जो एक [[कतार (डेटा संरचना)|क्यू  (डेटा संरचना)]] को सामान्यीकृत करता है, जिसके लिए तत्वों को फ्रंट (हेड) या बैक (टैल) से जोड़ा या हटाया जा सकता है।<ref>[[Donald Knuth]]. ''[[The Art of Computer Programming]]'', Volume 1: ''Fundamental Algorithms'', Third Edition. Addison-Wesley, 1997. {{ISBN|0-201-89683-4}}. Section 2.2.1: Stacks, Queues, and Deques, pp. 238&ndash;243.</ref> इसे प्रायः हेड-टेल लिंक्ड सूची भी कहा जाता है, हालांकि सही से यह डीक्यू की एक विशिष्ट [[डेटा संरचना]] ''कार्यान्वयन'' को संदर्भित करता है (नीचे देखें)।
Deque को कभी-कभी dequeue लिखा जाता है, लेकिन इस प्रयोग को आम तौर पर तकनीकी साहित्य या तकनीकी लेखन में बहिष्कृत किया जाता है क्योंकि dequeue भी एक क्रिया है जिसका अर्थ कतार से हटाना है। फिर भी, कई [[ पुस्तकालय (कम्प्यूटिंग) ]] और कुछ लेखक, जैसे [[ मैं अल्फ्रेड हूं ]], [[जॉन हॉपक्रॉफ्ट]], और [[जेफरी उल्मैन]] ने अपनी पाठ्यपुस्तक डेटा स्ट्रक्चर्स और एल्गोरिदम में, इसे डेक्यू बताया। कॉन्सेप्ट्स इन प्रोग्रामिंग लैंग्वेजेस के लेखक जॉन सी. मिशेल भी इस शब्दावली का उपयोग करते हैं।


== भेद और उप-प्रकार ==
== नामोल्लेखन कन्वेंशन ==
यह क्यू एब्स्ट्रैक्ट डेटा टाइप या फ़र्स्ट इन फ़र्स्ट आउट लिस्ट (FIFO (कंप्यूटिंग और इलेक्ट्रॉनिक्स)) से भिन्न है, जहाँ तत्वों को केवल एक छोर पर जोड़ा जा सकता है और दूसरे से हटाया जा सकता है। इस सामान्य डेटा वर्ग के कुछ संभावित उप-प्रकार हैं:
डेक को कभी-कभी डीक्यू भी लिखा जाता है, लेकिन इस प्रयोग को सामान्य रूप से तकनीकी साहित्य या तकनीकी लेखन में बहिष्कृत किया जाता है क्योंकि डीक्यू भी एक क्रिया है जिसका अर्थ क्यू  से हटाना है। फिर भी, कई [[ पुस्तकालय (कम्प्यूटिंग) | पुस्तकालय (कम्प्यूटिंग)]] और कुछ लेखक, जैसे अहो, होपक्रॉफ्ट, और उल्मैन ने अपनी पाठ्यपुस्तक डेटा संरचना और एल्गोरिदम में, इसे डीक्यू बताया है। <nowiki>''कॉन्सेप्ट्स इन प्रोग्रामिंग भाषा''</nowiki> के लेखक जॉन सी मिशेल भी इस शब्दावली का उपयोग करते हैं।


*एक इनपुट-प्रतिबंधित डेक वह है जहां दोनों सिरों से विलोपन किया जा सकता है, लेकिन सम्मिलन केवल एक छोर पर किया जा सकता है।
== विभेद और सबटाइप ==
* एक आउटपुट-प्रतिबंधित डेक वह है जहां दोनों सिरों पर सम्मिलन किया जा सकता है, लेकिन विलोपन केवल एक छोर से किया जा सकता है।
यह क्यू अमूर्त डेटा टाइप या <nowiki>''</nowiki>प्रथम प्रवेश प्रथम निर्गम<nowiki>''</nowiki> सूची (फीफो (कंप्यूटिंग और इलेक्ट्रॉनिक्स)) से भिन्न है, जहाँ तत्वों को केवल एक एंड (सिरे) पर जोड़ा जा सकता है और दूसरे से हटाया जा सकता है। इस सामान्य डेटा क्लास के कुछ संभावित सबटाइप हैं:


कंप्यूटिंग, कतार (डेटा संरचना) और स्टैक (डेटा संरचना) में बुनियादी और सबसे आम सूची प्रकार दोनों को डेक की विशेषज्ञता माना जा सकता है, और डेक का उपयोग करके कार्यान्वित किया जा सकता है।
*एक इनपुट-प्रतिबंधित डेक वह है जहां दोनों सिरों से विलोपन किया जा सकता है, लेकिन प्रविष्टि केवल एक एंड पर किया जा सकता है।
* एक आउटपुट-प्रतिबंधित डेक वह है जहां दोनों सिरों पर प्रविष्टि किया जा सकता है, लेकिन विलोपन केवल एक एंड से किया जा सकता है।
 
कंप्यूटिंग, क्यू  (डेटा संरचना) और स्टैक (डेटा संरचना) में आधारभूत और सबसे सामान्य सूची प्रकार दोनों को डेक की विशेषज्ञता माना जा सकता है, और डेक का उपयोग करके कार्यान्वित किया जा सकता है।


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


भाषाओं के बीच नाम भिन्न होते हैं; प्रमुख कार्यान्वयन में शामिल हैं:
भाषाओं के बीच नाम भिन्न होते हैं; प्रमुख कार्यान्वयन में सम्मिलित हैं:
{| class="wikitable"
{| class="wikitable"
! operation !! common name(s) !! [[Ada (programming language)|Ada]] !! [[C++]]!![[Java (programming language)|Java]] !! [[Perl]] !! [[PHP]] !! [[Python (programming language)|Python]] !! [[Ruby (programming language)|Ruby]]  
! संचालन !! सामान्य नाम !! [[Ada (programming language)|एडीए]] !! [[C++]]!![[Java (programming language)|जावा]] !! [[Perl|व्यावहारिक निष्कर्षण]]  
![[Rust (programming language)|Rust]]
[[Perl|और रिपोर्ट भाषा]]
![[JavaScript]]
! [[PHP|हाइपरटेक्स्ट प्रीप्रोसेसर]] !! [[Python (programming language)|पायथन]] !! [[Ruby (programming language)|रूबी]]
![[Rust (programming language)|आरयूएसटी]]
![[JavaScript|जावास्क्रिप्ट]]
|-
|-
| insert element at back || inject, snoc, push ||<code>Append</code> || <code>push_back</code> || <code>offerLast</code> || <code>push</code> || <code>array_push</code> || <code>append</code> || <code>push</code>  
| पीछे की ओर तत्व निर्दिष्ट करे || इंजेक्ट, स्नोक, पुश ||<code>Append</code> || <code>push_back</code> || <code>offerLast</code> || <code>push</code> || <code>array_push</code> || <code>append</code> || <code>push</code>  
|<code>push_back</code>||<code>push</code>
|<code>push_back</code>||<code>push</code>
|-
|-
| insert element at front || push, cons || <code>Prepend</code> || <code>push_front</code> || <code>offerFirst</code> || <code>unshift</code> || <code>array_unshift</code> || <code>appendleft</code> || <code>unshift</code>  
| सामने तत्व निर्दिष्ट करे || पुश, कॉन्स || <code>Prepend</code> || <code>push_front</code> || <code>offerFirst</code> || <code>unshift</code> || <code>array_unshift</code> || <code>appendleft</code> || <code>unshift</code>  
|<code>push_front</code>||<code>unshift</code>
|<code>push_front</code>||<code>unshift</code>
|-
|-
| remove last element || eject || <code>Delete_Last</code> || <code>pop_back</code> || <code>pollLast</code> || <code>pop</code> || <code>array_pop</code> || <code>pop</code> || <code>pop</code>  
| अंतिम तत्व को हटा दें || इजेक्ट || <code>Delete_Last</code> || <code>pop_back</code> || <code>pollLast</code> || <code>pop</code> || <code>array_pop</code> || <code>pop</code> || <code>pop</code>  
|<code>pop_back</code>||<code>pop</code>
|<code>pop_back</code>||<code>pop</code>
|-
|-
| remove first element || pop || <code>Delete_First</code> || <code>pop_front</code> || <code>pollFirst</code> || <code>shift</code> || <code>array_shift</code> || <code>popleft</code> || <code>shift</code>  
| पहले तत्व को हटा दें || पॉप || <code>Delete_First</code> || <code>pop_front</code> || <code>pollFirst</code> || <code>shift</code> || <code>array_shift</code> || <code>popleft</code> || <code>shift</code>  
|<code>pop_front</code>||<code>shift</code>
|<code>pop_front</code>||<code>shift</code>
|-
|-
| examine last element || peek
| अंतिम तत्व का परीक्षण || पीक
| <code>Last_Element</code> || <code>back</code> || <code>peekLast</code> || <code>$array[-1]</code> || <code>end</code> || <code><obj>[-1]</code> || <code>last</code>  
| <code>Last_Element</code> || <code>back</code> || <code>peekLast</code> || <code>$array[-1]</code> || <code>end</code> || <code><obj>[-1]</code> || <code>last</code>  
|<code>back</code>||<code><obj>.at(-1)</code>
|<code>back</code>||<code><obj>.at(-1)</code>
|-
|-
| examine first element || || <code>First_Element</code> || <code>front</code> || <code>peekFirst</code> || <code>$array[0]</code> || <code>reset</code> || <code><obj>[0]</code> || <code>first</code>  
| पहले तत्व का परीक्षण || || <code>First_Element</code> || <code>front</code> || <code>peekFirst</code> || <code>$array[0]</code> || <code>reset</code> || <code><obj>[0]</code> || <code>first</code>  
|<code>front</code>||<code><obj>[0]</code>
|<code>front</code>||<code><obj>[0]</code>
|}
|}
Line 48: Line 49:


== कार्यान्वयन ==
== कार्यान्वयन ==
डेक को प्रभावी ढंग से लागू करने के कम से कम दो सामान्य तरीके हैं: एक संशोधित [[गतिशील सरणी]] के साथ या एक [[दोगुनी लिंक्ड सूची]] के साथ।
डेक को प्रभावी रूप से प्रयुक्त करने के कम से कम दो सामान्य तरीके हैं: एक संशोधित [[गतिशील सरणी]] के साथ या एक [[दोगुनी लिंक्ड सूची]] के साथ।


गतिशील सरणी दृष्टिकोण गतिशील सरणी के एक प्रकार का उपयोग करता है जो दोनों सिरों से बढ़ सकता है, जिसे कभी-कभी सरणी डेक कहा जाता है। इन सरणी deques में एक गतिशील सरणी के सभी गुण होते हैं, जैसे कि निरंतर-समय यादृच्छिक अभिगम, संदर्भ का अच्छा स्थान, और बीच में अक्षम सम्मिलन/हटाना, इसके बजाय दोनों सिरों पर परिशोधित निरंतर-समय सम्मिलन/हटाना शामिल है। सिर्फ एक छोर का। तीन आम कार्यान्वयन में शामिल हैं:
गतिशील सरणी दृष्टिकोण गतिशील सरणी के एक प्रकार का उपयोग करता है जो दोनों सिरों से बढ़ सकता है, जिसे कभी-कभी सरणी डेक कहा जाता है। इन सरणी डीक्यू में एक गतिशील सरणी के सभी गुण होते हैं, जैसे कि निरंतर-समय यादृच्छिक अभिगम, संदर्भ का अच्छा स्थान, और बीच में अप्रभावी प्रविष्टि/हटाना, इसके अतिरिक्त दोनों सिरों पर परिशोधित निरंतर-समय प्रविष्टि/हटाना जिसमे सिर्फ एक एंड सम्मिलित है। इसमे तीन सामान्य कार्यान्वयन में सम्मिलित हैं:
* deque सामग्री को एक गोलाकार बफ़र में संग्रहीत करना, और केवल तभी आकार बदलना जब बफ़र पूर्ण हो जाता है। इससे आकार बदलने की आवृत्ति कम हो जाती है।
* डेक सामग्री को एक परिपत्र बफ़र में संग्रहीत करना, और केवल तभी आकार बदलना जब बफ़र पूर्ण हो जाता है। इससे आकार बदलने की आवृत्ति कम हो जाती है।
* अंतर्निहित सरणी के केंद्र से डेक सामग्री आवंटित करना, और अंत तक पहुंचने पर अंतर्निहित सरणी का आकार बदलना। इस दृष्टिकोण को अधिक बार-बार आकार बदलने और अधिक स्थान बर्बाद करने की आवश्यकता हो सकती है, खासकर जब तत्व केवल एक छोर पर डाले जाते हैं।
* अंतर्निहित सरणी के केंद्र से डेक सामग्री आवंटित करना, और अंत तक पहुंचने पर अंतर्निहित सरणी का आकार बदलना। इस दृष्टिकोण को अधिक बार आकार बदलने और अधिक स्थान नष्ट करने की आवश्यकता हो सकती है, विशेषकर जब तत्व केवल एक एंड पर निर्दिष्ट किए जाते हैं।
* सामग्री को कई छोटे सरणियों में संग्रहीत करना, आवश्यकतानुसार शुरुआत या अंत में अतिरिक्त सरणियाँ आवंटित करना। प्रत्येक छोटे सरणियों में पॉइंटर्स युक्त एक गतिशील सरणी रखकर इंडेक्सिंग को कार्यान्वित किया जाता है।
* सामग्री को कई छोटे सरणियों में संग्रहीत करना, आवश्यकतानुसार प्रारंभ या अंत में अतिरिक्त सरणियाँ आवंटित करना। प्रत्येक छोटे सरणियों में पॉइंटर्स युक्त एक गतिशील सरणी रखकर इंडेक्सिंग को कार्यान्वित किया जाता है।


=== विशुद्ध रूप से कार्यात्मक कार्यान्वयन ===
=== पूर्ण रूप से कार्यात्मक कार्यान्वयन ===
डबल-एंडेड कतारों को [[विशुद्ध रूप से कार्यात्मक डेटा संरचना]] के रूप में भी लागू किया जा सकता है।<ref name="functional">{{cite thesis |url=https://www.cs.cmu.edu/~rwh/theses/okasaki.pdf |first=Chris |last=Okasaki |title=विशुद्ध रूप से कार्यात्मक डेटा संरचनाएं|type=Ph.D. thesis |date=September 1996 |publisher=Carnegie Mellon University |id=CMU-CS-96-177}}</ref>{{rp|115}} कार्यान्वयन के दो संस्करण मौजूद हैं। पहला, जिसे रीयल-टाइम डेक'' कहा जाता है, नीचे प्रस्तुत किया गया है। यह कतार में संचालन के साथ [[लगातार डेटा संरचना]] होने की अनुमति देता है {{math|''O''(1)}} सबसे खराब समय, लेकिन [[memoization]] के साथ [[आलसी मूल्यांकन]] सूचियों की आवश्यकता होती है। दूसरा, जिसमें कोई आलसी सूची नहीं है और न ही संस्मरण खंडों के अंत में प्रस्तुत किया गया है। इसका [[परिशोधित विश्लेषण]] समय है {{math|''O''(1)}} यदि दृढ़ता का उपयोग नहीं किया जाता है; लेकिन किसी ऑपरेशन की सबसे खराब समय जटिलता है {{math|''O''(''n'')}} कहाँ {{mvar|n}} डबल-एंडेड कतार में तत्वों की संख्या है।
डबल-एंडेड कतारों को [[विशुद्ध रूप से कार्यात्मक डेटा संरचना]] के रूप में भी प्रयुक्त किया जा सकता है।<ref name="functional">{{cite thesis |url=https://www.cs.cmu.edu/~rwh/theses/okasaki.pdf |first=Chris |last=Okasaki |title=विशुद्ध रूप से कार्यात्मक डेटा संरचनाएं|type=Ph.D. thesis |date=September 1996 |publisher=Carnegie Mellon University |id=CMU-CS-96-177}}</ref>{{rp|115}} कार्यान्वयन के दो संस्करण सम्मिलित हैं। पहला, जिसे 'वास्तविक समय डेक' कहा जाता है, नीचे प्रस्तुत किया गया है। यह क्यू  को ओ (1) सबसे विकृत समय में संचालन के साथ निरंतर रहने की स्वीकृति देता है, लेकिन मेमोइज़ेशन के साथ लेज़ी सूचियों की आवश्यकता होती है। दूसरा, जिसमें कोई लेज़ी सूची नहीं है और न ही मेमोइज़ेशन भागों के अंत में प्रस्तुत किया गया है। इसका परिशोधन समय O(1) है यदि दृढ़ता का उपयोग नहीं किया जाता है; लेकिन किसी संचालन की सबसे विकृत समय की जटिलता O(n) है जहां n डबल-एंडेड क्यू में तत्वों की संख्या है।


आइए याद करते हैं कि, एक सूची के लिए <code>l</code>, <code>|l|</code> इसकी लंबाई को दर्शाता है, कि <code>NIL</code> एक खाली सूची का प्रतिनिधित्व करता है और <code>CONS(h, t)</code> उस सूची का प्रतिनिधित्व करता है जिसका प्रमुख है <code>h</code> और पूंछ किसकी है <code>t</code>. कार्य <code>drop(i, l)</code> और <code>take(i, l)</code> सूची वापस करो <code>l</code> इसके पहले के बिना <code>i</code> तत्व, और पहला <code>i</code> घटक <code>l</code>, क्रमश। या अगर <code>|l| < i</code>, वे खाली सूची लौटाते हैं और <code>l</code> क्रमश।
आइए पुनः कॉल करते हैं कि, एक सूची के लिए <code>l</code>, <code>|l|</code> इसकी लंबाई को दर्शाता है, कि <code>NIL</code> एक रिक्त सूची का प्रतिनिधित्व करता है और <code>CONS(h, t)</code> उस सूची का प्रतिनिधित्व करता है जिसका शीर्ष  <code>h</code> है और टैल  <code>t</code> है।  फ़ंक्शन <code>drop(i, l)</code> और <code>take(i, l)</code> क्रमशः <code>l</code> के पहले <code>i</code>तत्वों और <code>i</code> के पहले <code>l</code>, तत्वों के बिना सूची<code>देते हैं। या, यदि |l|< i</code>, वे क्रमशः रिक्त सूची और <code>l</code> देते है।


==== आलसी पुनर्निर्माण और शेड्यूलिंग के माध्यम से रीयल-टाइम डेक ====
==== लेज़ी पुनर्निर्माण और शेड्यूलिंग के माध्यम से वास्तविक समय डेक ====
एक डबल-एंडेड कतार को सेक्स्टुपल के रूप में दर्शाया गया है <code>(len_front, front, tail_front, len_rear, rear, tail_rear)</code> कहाँ <code>front</code> एक [[लिंक्ड सूची]] है जिसमें लंबाई की कतार के सामने होता है <code>len_front</code>. इसी प्रकार, <code>rear</code> एक लिंक की गई सूची है जो लंबाई की कतार के पीछे के हिस्से का प्रतिनिधित्व करती है <code>len_rear</code>. साथ ही यह भी आश्वासन दिया है <code>|front| ≤ 2|rear|+1</code> और <code>|rear| ≤ 2|front|+1</code> - सहज रूप से, इसका मतलब है कि आगे और पीछे दोनों में एक तिहाई माइनस एक और दो तिहाई प्लस एक तत्व होता है। आखिरकार, <code>tail_front</code> और <code>tail_rear</code> की पूंछ हैं <code>front</code> और का <code>rear</code>, वे उस पल को शेड्यूल करने की अनुमति देते हैं जहां कुछ आलसी संचालन को मजबूर किया जाता है। ध्यान दें कि, जब एक डबल-एंडेड क्यू में शामिल होता है <code>n</code> सामने की सूची में तत्व और <code>n</code> पीछे की सूची में तत्व, उसके बाद असमानता अपरिवर्तनीय संतुष्ट रहती है <code>i</code> निवेशन और <code>d</code> विलोपन जब <code>(i+d) &leq; n/2</code>. यानी ज्यादा से ज्यादा <code>n/2</code> संचालन प्रत्येक पुनर्संतुलन के बीच हो सकता है।
एक डबल-एंडेड क्यू  को सेक्स्टुपल के रूप में दर्शाया गया है <code>(len_front, front, tail_front, len_rear, rear, tail_rear)</code> कहाँ <code>front</code> एक [[लिंक्ड सूची]] है जिसमें लंबाई की क्यू  के सामने होता है <code>len_front</code>. इसी प्रकार, <code>rear</code> एक लिंक की गई सूची है जो लंबाई की क्यू  के पीछे के हिस्से का प्रतिनिधित्व करती है <code>len_rear</code>. साथ ही यह भी आश्वासन दिया है <code>|front| ≤ 2|rear|+1</code> और <code>|rear| ≤ 2|front|+1</code> - सहज रूप से, इसका मतलब है कि आगे और पीछे दोनों में एक तिहाई माइनस एक और दो तिहाई प्लस एक तत्व होता है। आखिरकार, <code>tail_front</code> और <code>tail_rear</code> की पूंछ हैं <code>front</code> और का <code>rear</code>, वे उस पल को शेड्यूल करने की स्वीकृति देते हैं जहां कुछ लेज़ी संचालन को मजबूर किया जाता है। ध्यान दें कि, जब एक डबल-एंडेड क्यू में सम्मिलित होता है <code>n</code> सामने की सूची में तत्व और <code>n</code> पीछे की सूची में तत्व, उसके बाद असमानता अपरिवर्तनीय संतुष्ट रहती है <code>i</code> निवेशन और <code>d</code> विलोपन जब <code>(i+d) &leq; n/2</code>. यानी ज्यादा से ज्यादा <code>n/2</code> संचालन प्रत्येक पुनर्संतुलन के बीच हो सकता है।


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


<syntaxhighlight lang="sml">
<syntaxhighlight lang="sml">
empty = (0, NIL, NIL, 0, NIL, NIL)
empty = (0, NIL, NIL, 0, NIL, NIL)
fun insert'(x, (len_front, front, tail_front, len_rear, rear, tail_rear)) =
fun insert'(x, (len_front, front, tail_front, len_rear, rear, tail_rear)) =
Line 75: Line 76:
fun tail'((_, NIL, _, _, CONS(h, NIL), _)) = empty   
fun tail'((_, NIL, _, _, CONS(h, NIL), _)) = empty   
</syntaxhighlight>
</syntaxhighlight>
यह समझाने के लिए बनी हुई है कि किसी विधि को कैसे परिभाषित किया जाए <code>balance</code> कि deque अगर rebalance <code>insert'</code> या <code>tail</code> अपरिवर्तनीय तोड़ दिया। प्रक्रिया <code>insert</code> और <code>tail</code> पहले आवेदन करके परिभाषित किया जा सकता है <code>insert'</code> और <code>tail'</code> और फिर आवेदन करना <code>balance</code>.
यह समझाने के लिए बनी हुई है कि किसी विधि को कैसे परिभाषित किया जाए <code>balance</code> कि डेक अगर rebalance <code>insert'</code> या <code>tail</code> अपरिवर्तनीय तोड़ दिया। प्रक्रिया <code>insert</code> और <code>tail</code> पहले आवेदन करके परिभाषित किया जा सकता है <code>insert'</code> और <code>tail'</code> और फिर आवेदन करना <code>balance</code>.


<syntaxhighlight lang="sml">
<syntaxhighlight lang="sml">
Line 110: Line 111:


==== आलस्य के बिना कार्यान्वयन ====
==== आलस्य के बिना कार्यान्वयन ====
ध्यान दें कि, कार्यान्वयन के आलसी भाग के बिना, यह कतार में एक गैर-निरंतर कार्यान्वयन होगा {{math|''O''(1)}} परिशोधित विश्लेषण। इस मामले में, सूचियाँ <code>tail_front</code> और <code>tail_rear</code> डबल-एंडेड कतार के प्रतिनिधित्व से हटाया जा सकता है।
ध्यान दें कि, कार्यान्वयन के लेज़ी भाग के बिना, यह क्यू  में एक गैर-निरंतर कार्यान्वयन होगा {{math|''O''(1)}} परिशोधित विश्लेषण। इस मामले में, सूचियाँ <code>tail_front</code> और <code>tail_rear</code> डबल-एंडेड क्यू  के प्रतिनिधित्व से हटाया जा सकता है।


== भाषा समर्थन ==
== भाषा समर्थन ==
[[एडा (प्रोग्रामिंग भाषा)]] के कंटेनर सामान्य पैकेज प्रदान करते हैं <code>Ada.Containers.Vectors</code> और <code>Ada.Containers.Doubly_Linked_Lists</code>, क्रमशः गतिशील सरणी और लिंक्ड सूची कार्यान्वयन के लिए।
[[एडा (प्रोग्रामिंग भाषा)]] के कंटेनर सामान्य पैकेज प्रदान करते हैं <code>Ada.Containers.Vectors</code> और <code>Ada.Containers.Doubly_Linked_Lists</code>, क्रमशः गतिशील सरणी और लिंक्ड सूची कार्यान्वयन के लिए।


सी++ की [[मानक टेम्पलेट लाइब्रेरी]] वर्ग टेम्पलेट प्रदान करती है <code>std::deque</code> और <code>std::list</code>, क्रमशः एकाधिक सरणी और लिंक्ड सूची कार्यान्वयन के लिए।
सी++ की [[मानक टेम्पलेट लाइब्रेरी]] क्लास टेम्पलेट प्रदान करती है <code>std::डेक</code> और <code>std::list</code>, क्रमशः एकाधिक सरणी और लिंक्ड सूची कार्यान्वयन के लिए।


जावा 6 के अनुसार, जावा का कलेक्शंस फ्रेमवर्क एक नया प्रदान करता है {{Javadoc:SE|java/util|Deque}} इंटरफ़ेस जो दोनों सिरों पर सम्मिलन और हटाने की कार्यक्षमता प्रदान करता है। यह जैसे वर्गों द्वारा कार्यान्वित किया जाता है {{Javadoc:SE|java/util|ArrayDeque}} (जावा 6 में भी नया) और {{Javadoc:SE|java/util|LinkedList}}, क्रमशः डायनेमिक सरणी और लिंक्ड सूची कार्यान्वयन प्रदान करता है। हालांकि <code>ArrayDeque</code>, इसके नाम के विपरीत, रैंडम एक्सेस का समर्थन नहीं करता है।
जावा 6 के अनुसार, जावा का कलेक्शंस फ्रेमवर्क एक नया प्रदान करता है {{Javadoc:SE|java/util|Deque}} इंटरफ़ेस जो दोनों सिरों पर प्रविष्टि और हटाने की कार्यक्षमता प्रदान करता है। यह जैसे वर्गों द्वारा कार्यान्वित किया जाता है {{Javadoc:SE|java/util|ArrayDeque}} (जावा 6 में भी नया) और {{Javadoc:SE|java/util|LinkedList}}, क्रमशः डायनेमिक सरणी और लिंक्ड सूची कार्यान्वयन प्रदान करता है। हालांकि <code>ArrayDeque</code>, इसके नाम के विपरीत, रैंडम एक्सेस का समर्थन नहीं करता है।


जावास्क्रिप्ट के [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array Array प्रोटोटाइप] और [[पर्ल]] की सरणियों को दोनों को हटाने के लिए मूल समर्थन है ([http://perldoc.perl.org /functions/shift.html shift] और [http://perldoc.perl.org/functions/pop.html pop]) और जोड़ना ([http://perldoc.perl.org/functions/unshift.html unshift] और [http://perldoc.perl.org/functions/push.html push]) दोनों सिरों पर तत्व।
जावास्क्रिप्ट के [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array Array प्रोटोटाइप] और [[पर्ल]] की सरणियों को दोनों को हटाने के लिए मूल समर्थन है ([http://perldoc.perl.org /functions/shift.html shift] और [http://perldoc.perl.org/functions/pop.html pop]) और जोड़ना ([http://perldoc.perl.org/functions/unshift.html unshift] और [http://perldoc.perl.org/functions/push.html push]) दोनों सिरों पर तत्व।
Line 123: Line 124:
पायथन 2.4 ने पेश किया <code>collections</code> [https://docs.python.org/3/library/collections.html#deque-objects डेक ऑब्जेक्ट्स] के समर्थन के साथ मॉड्यूल। इसे निश्चित-लंबाई वाली उप-सरणियों की दोगुनी लिंक्ड सूची का उपयोग करके कार्यान्वित किया जाता है।
पायथन 2.4 ने पेश किया <code>collections</code> [https://docs.python.org/3/library/collections.html#deque-objects डेक ऑब्जेक्ट्स] के समर्थन के साथ मॉड्यूल। इसे निश्चित-लंबाई वाली उप-सरणियों की दोगुनी लिंक्ड सूची का उपयोग करके कार्यान्वित किया जाता है।


PHP 5.3 के अनुसार, PHP के SPL एक्सटेंशन में 'SplDoublyLinkedList' वर्ग शामिल है जिसका उपयोग Deque डेटास्ट्रक्चर को लागू करने के लिए किया जा सकता है। पहले डेक संरचना बनाने के लिए सरणी फ़ंक्शन array_shift/unshift/pop/push का उपयोग इसके बजाय किया जाना था।
PHP 5.3 के अनुसार, PHP के SPL एक्सटेंशन में 'SplDoublyLinkedList' क्लास सम्मिलित है जिसका उपयोग Deque डेटास्ट्रक्चर को प्रयुक्त करने के लिए किया जा सकता है। पहले डेक संरचना बनाने के लिए सरणी फ़ंक्शन array_shift/unshift/pop/push का उपयोग इसके अतिरिक्त किया जाना था।


[[ग्लासगो हास्केल कंपाइलर]] [http://hackage.haskell.org/package/containers-0.6.0.1/docs/Data-Sequence.html Data.Sequence] मॉड्यूल [[हास्केल (प्रोग्रामिंग भाषा)]] में एक कुशल, कार्यात्मक डेक संरचना लागू करता है। कार्यान्वयन 2–3 ट्री | 2–3 फिंगर ट्री का उपयोग करता है जो आकार के साथ एनोटेट किए गए हैं। विशुद्ध रूप से कार्यात्मक (इस प्रकार भी लगातार डेटा संरचना) डबल कतारों को लागू करने के लिए अन्य (तेज) संभावनाएं हैं (ज्यादातर आलसी मूल्यांकन का उपयोग करते हुए)।<ref name="functional"/><ref>Adam L. Buchsbaum and Robert E. Tarjan. Confluently persistent deques via data structural bootstrapping. Journal of Algorithms, 18(3):513–547, May 1995. (pp. 58, 101, 125)</ref> कापलान और टारजन सबसे पहले इष्टतम कंफर्टेबलली परसिस्टेंट कैटेनेबल डेक्स को लागू करने वाले थे।<ref>Haim Kaplan and Robert E. Tarjan. Purely functional representations of catenable sorted lists. In ACM Symposium on Theory of Computing, pages 202–211, May  1996. (pp. 4, 82, 84, 124)</ref> उनका कार्यान्वयन पूरी तरह से कार्यात्मक था इस अर्थ में कि यह आलसी मूल्यांकन का उपयोग नहीं करता था। ओकासाकी ने बूटस्ट्रैप्ड डेटा संरचना के साथ आलसी मूल्यांकन का उपयोग करके डेटा संरचना को सरल बनाया और प्रदर्शन सीमा को सबसे खराब स्थिति से परिशोधित कर दिया। कापलान, ओकासाकी, और टारजन ने एक सरल, गैर-बूटस्ट्रैप्ड, परिशोधित संस्करण का उत्पादन किया जिसे या तो आलसी मूल्यांकन का उपयोग करके या व्यापक रूप से अभी भी प्रतिबंधित फैशन में म्यूटेशन का उपयोग करके अधिक कुशलता से लागू किया जा सकता है। मिहासौ और टारजन ने एक सरल (लेकिन अभी भी अत्यधिक जटिल) कैटेनेबल डेक्स का सख्ती से कार्यात्मक कार्यान्वयन बनाया, और सख्ती से पूरी तरह कार्यात्मक गैर-कैटेनेबल डेक्स का बहुत सरल कार्यान्वयन भी किया, जिनमें से दोनों में इष्टतम सबसे खराब स्थिति सीमा है।
[[ग्लासगो हास्केल कंपाइलर]] [http://hackage.haskell.org/package/containers-0.6.0.1/docs/Data-Sequence.html Data.Sequence] मॉड्यूल [[हास्केल (प्रोग्रामिंग भाषा)]] में एक कुशल, कार्यात्मक डेक संरचना प्रयुक्त करता है। कार्यान्वयन 2–3 ट्री | 2–3 फिंगर ट्री का उपयोग करता है जो आकार के साथ एनोटेट किए गए हैं। विशुद्ध रूप से कार्यात्मक (इस प्रकार भी लगातार डेटा संरचना) डबल कतारों को प्रयुक्त करने के लिए अन्य (तेज) संभावनाएं हैं (ज्यादातर लेज़ी मूल्यांकन का उपयोग करते हुए)।<ref name="functional"/><ref>Adam L. Buchsbaum and Robert E. Tarjan. Confluently persistent deques via data structural bootstrapping. Journal of Algorithms, 18(3):513–547, May 1995. (pp. 58, 101, 125)</ref> कापलान और टारजन सबसे पहले इष्टतम कंफर्टेबलली परसिस्टेंट कैटेनेबल डेक्स को प्रयुक्त करने वाले थे।<ref>Haim Kaplan and Robert E. Tarjan. Purely functional representations of catenable sorted lists. In ACM Symposium on Theory of Computing, pages 202–211, May  1996. (pp. 4, 82, 84, 124)</ref> उनका कार्यान्वयन पूरी तरह से कार्यात्मक था इस अर्थ में कि यह लेज़ी मूल्यांकन का उपयोग नहीं करता था। ओकासाकी ने बूटस्ट्रैप्ड डेटा संरचना के साथ लेज़ी मूल्यांकन का उपयोग करके डेटा संरचना को सरल बनाया और प्रदर्शन सीमा को सबसे खराब स्थिति से परिशोधित कर दिया। कापलान, ओकासाकी, और टारजन ने एक सरल, गैर-बूटस्ट्रैप्ड, परिशोधित संस्करण का उत्पादन किया जिसे या तो लेज़ी मूल्यांकन का उपयोग करके या व्यापक रूप से अभी भी प्रतिबंधित फैशन में म्यूटेशन का उपयोग करके अधिक कुशलता से प्रयुक्त किया जा सकता है। मिहासौ और टारजन ने एक सरल (लेकिन अभी भी अत्यधिक जटिल) कैटेनेबल डेक्स का सख्ती से कार्यात्मक कार्यान्वयन बनाया, और सख्ती से पूरी तरह कार्यात्मक गैर-कैटेनेबल डेक्स का बहुत सरल कार्यान्वयन भी किया, जिनमें से दोनों में इष्टतम सबसे खराब स्थिति सीमा है।


जंग का <code>std::collections</code> इसमें [https://doc.rust-lang.org/std/collections/struct.VecDeque.html VecDeque] शामिल है जो बढ़ने योग्य रिंग बफर का उपयोग करके डबल-एंडेड कतार को लागू करता है।
जंग का <code>std::collections</code> इसमें [https://doc.rust-lang.org/std/collections/struct.VecDeque.html VecDeque] सम्मिलित है जो बढ़ने योग्य रिंग बफर का उपयोग करके डबल-एंडेड क्यू  को प्रयुक्त करता है।


== जटिलता ==
== जटिलता ==
* एक दोगुनी-लिंक्ड सूची कार्यान्वयन में और कोई आवंटन/डीललोकेशन ओवरहेड नहीं मानते हुए, सभी डेक परिचालनों का [[कम्प्यूटेशनल जटिलता सिद्धांत]] [[बिग ओ नोटेशन]] है। ओ (1)इसके अतिरिक्त, बीच में सम्मिलन या विलोपन की समय जटिलता, एक पुनरावर्तक दिया गया है, ओ (1) है; हालाँकि, इंडेक्स द्वारा रैंडम एक्सेस की समय जटिलता O(n) है।
* एक दोगुनी-लिंक्ड सूची कार्यान्वयन में और कोई आवंटन/डीललोकेशन ओवरहेड नहीं मानते हुए, सभी डेक संचालन की समय जटिलता ओ (1) है। इसके अतिरिक्त, बीच में सम्मिलन या विलोपन की समय जटिलता, एक पुनरावर्तक दिया गया है, ओ (1) है; हालाँकि, इंडेक्स द्वारा रैंडम एक्सेस की समय जटिलता O(n) है।
* एक बढ़ते सरणी में, सभी डीक्यू ऑपरेशनों की परिशोधित विश्लेषण समय जटिलता बिग ओ नोटेशन है। ओ (1)इसके अतिरिक्त, इंडेक्स द्वारा रैंडम एक्सेस की समय जटिलता O(1) है; लेकिन बीच में सम्मिलन या विलोपन की समय जटिलता बिग ओ नोटेशन | ओ (एन) है।
* एक बढ़ते सरणी में, सभी डेक संचालन की परिशोधित समय जटिलता हे (1) है। इसके अतिरिक्त, इंडेक्स द्वारा रैंडम एक्सेस की समय जटिलता O(1) है; लेकिन बीच में प्रविष्टि या विलोपन की समय जटिलता (एन) है।


== अनुप्रयोग ==
== एप्लीकेशन ==
[[File:Back button history (Ecosia browser - Google Pixel 4a) - Google Android 12 (cropped).png|thumb|[[वेब ब्राउज़िंग इतिहास]] को संग्रहीत करने के लिए एक डबल-एंडेड कतार का उपयोग किया जा सकता है: कतार के अंत में नई वेबसाइटें जोड़ी जाती हैं, जबकि इतिहास बहुत बड़ा होने पर सबसे पुरानी प्रविष्टियां हटा दी जाएंगी। जब कोई उपयोगकर्ता पिछले एक घंटे के ब्राउज़िंग इतिहास को साफ़ करने के लिए कहता है, तो सबसे हाल ही में जोड़ी गई प्रविष्टियाँ हटा दी जाती हैं।]]एक उदाहरण जहां डेक का उपयोग किया जा सकता है वह कार्य चोरी है।<ref name="jacm">{{cite journal |last1=Blumofe |first1=Robert D. |first2=Charles E. |last2=Leiserson |author-link2=Charles E. Leiserson |title=काम चोरी करके मल्टीथ्रेडेड कंप्यूटेशंस शेड्यूल करना|journal=J ACM |volume=46 |issue=5 |year=1999 |pages=720–748 |url=http://supertech.csail.mit.edu/papers/ft_gateway.pdf |doi=10.1145/324133.324234|s2cid=5428476 }}</ref> यह एल्गोरिथम कई प्रोसेसरों के लिए टास्क शेड्यूलिंग को लागू करता है। प्रत्येक प्रोसेसर के लिए निष्पादित किए जाने वाले थ्रेड्स के साथ एक अलग डेक बनाए रखा जाता है। अगले थ्रेड को निष्पादित करने के लिए, प्रोसेसर को डेक से पहला तत्व मिलता है (पहले तत्व डेक ऑपरेशन को हटाकर)। यदि वर्तमान थ्रेड फोर्क होता है, तो इसे डीक्यू के सामने वापस रखा जाता है (सामने तत्व डालें) और एक नया थ्रेड निष्पादित किया जाता है। जब प्रोसेसर में से एक अपने स्वयं के थ्रेड्स का निष्पादन पूरा करता है (अर्थात इसका डेक खाली है), तो यह दूसरे प्रोसेसर से एक थ्रेड चुरा सकता है: यह दूसरे प्रोसेसर के डेक से अंतिम तत्व प्राप्त करता है (अंतिम तत्व को हटा दें) और इसे निष्पादित करता है। समानांतर प्रोग्रामिंग के लिए इंटेल के थ्रेडिंग बिल्डिंग ब्लॉक्स (टीबीबी) लाइब्रेरी द्वारा कार्य चोरी एल्गोरिदम का उपयोग किया जाता है।
[[File:Back button history (Ecosia browser - Google Pixel 4a) - Google Android 12 (cropped).png|thumb|[[वेब ब्राउज़िंग इतिहास]] को संग्रहीत करने के लिए एक डबल-एंडेड क्यू  का उपयोग किया जा सकता है: क्यू  के अंत में नई वेबसाइटें जोड़ी जाती हैं, जबकि इतिहास बहुत बड़ा होने पर सबसे पुरानी प्रविष्टियां हटा दी जाएंगी। जब कोई उपयोगकर्ता पिछले एक घंटे के ब्राउज़िंग इतिहास को साफ़ करने के लिए कहता है, तो सबसे हाल ही में जोड़ी गई प्रविष्टियाँ हटा दी जाती हैं।]]उदाहरण जहां डेक का उपयोग किया जा सकता है वह कार्य स्टालिंग एल्गोरिथम है।<ref name="jacm">{{cite journal |last1=Blumofe |first1=Robert D. |first2=Charles E. |last2=Leiserson |author-link2=Charles E. Leiserson |title=काम चोरी करके मल्टीथ्रेडेड कंप्यूटेशंस शेड्यूल करना|journal=J ACM |volume=46 |issue=5 |year=1999 |pages=720–748 |url=http://supertech.csail.mit.edu/papers/ft_gateway.pdf |doi=10.1145/324133.324234|s2cid=5428476 }}</ref> यह एल्गोरिथम कई प्रोसेसरों के लिए टास्क शेड्यूलिंग को प्रयुक्त करता है। प्रत्येक प्रोसेसर के लिए निष्पादित किए जाने वाले थ्रेड्स के साथ एक अलग डेक बनाए रखा जाता है। अगले थ्रेड को निष्पादित करने के लिए, प्रोसेसर को डेक से पहला तत्व मिलता है (पहले तत्व डेक संचालन को हटाकर)। यदि वर्तमान थ्रेड फोर्क होता है, तो इसे डीक्यू के सामने वापस रखा जाता है (फ्रंट तत्व निर्दिष्ट) और एक नया थ्रेड निष्पादित किया जाता है। जब प्रोसेसर में से एक अपने स्वयं के थ्रेड्स का निष्पादन पूरा करता है (अर्थात इसका डेक रिक्त है), तो यह दूसरे प्रोसेसर से एक थ्रेड 'स्टील' सकता है: यह दूसरे प्रोसेसर के डेक से अंतिम तत्व प्राप्त करता है (बैक तत्व को हटा दें) और इसे निष्पादित करता है। समानांतर प्रोग्रामिंग के लिए इंटेल के थ्रेडिंग बिल्डिंग ब्लॉक्स (टीबीबी) लाइब्रेरी द्वारा कार्य स्टालिंग एल्गोरिदम का उपयोग किया जाता है।


== यह भी देखें ==
== यह भी देखें ==
* पाइपलाइन (यूनिक्स) # पाइप चरित्र
* पाइप (यूनिक्स)  
* कतार (डेटा संरचना)
* क्यू  (डेटा संरचना)
*[[प्राथमिकता कतार]]
*[[प्राथमिकता कतार|प्राथमिकता क्यू]]  


== संदर्भ ==
== संदर्भ ==
Line 146: Line 147:


== बाहरी संबंध ==
== बाहरी संबंध ==
* [http://ccodearchive.net/info/deque.html Type-safe open source deque implementation at Comprehensive C Archive Network]
* [http://ccodearchive.net/info/deque.html Type-safe open source डेक implementation at Comprehensive C Archive Network]
* [http://www.sgi.com/tech/stl/Deque.html SGI STL Documentation: deque<T, Alloc>]
* [http://www.sgi.com/tech/stl/Deque.html SGI STL Documentation: डेक<T, Alloc>]
* [http://www.codeproject.com/KB/stl/vector_vs_deque.aspx Code Project: An In-Depth Study of the STL Deque Container]
* [http://www.codeproject.com/KB/stl/vector_vs_deque.aspx Code Project: An In-Depth Study of the STL Deque Container]
* [http://www.martinbroadhurst.com/articles/deque.html Deque implementation in C]
* [http://www.martinbroadhurst.com/articles/deque.html Deque implementation in C]
* [https://web.archive.org/web/20110714000645/http://www.ludvikjerabek.com/downloads.html VBScript implementation of stack, queue, deque, and Red-Black Tree]
* [https://web.archive.org/web/20110714000645/http://www.ludvikjerabek.com/downloads.html VBScript implementation of stack, queue, डेक, and Red-Black Tree]
* [https://code.google.com/p/deques/source/browse/ Multiple implementations of non-catenable deques in Haskell]
* [https://code.google.com/p/deques/source/browse/ Multiple implementations of non-catenable deques in Haskell]



Revision as of 09:25, 2 March 2023

"डीक्यू" यहां पुनर्निर्देश करता है। डीक्यूइंग, क्यू संचालन के साथ भ्रमित नहीं होना चाहिए।

डबल-एंडेड प्राथमिकता क्यू के साथ भ्रमित नहीं होना चाहिए।

कंप्यूटर विज्ञान में, डबल-एंडेड क्यू (संक्षिप्त रूप से डीक्यू, स्पष्ट 'डेक', जैसे चेक[1]) एक अमूर्त डेटा प्रकार है जो एक क्यू (डेटा संरचना) को सामान्यीकृत करता है, जिसके लिए तत्वों को फ्रंट (हेड) या बैक (टैल) से जोड़ा या हटाया जा सकता है।[2] इसे प्रायः हेड-टेल लिंक्ड सूची भी कहा जाता है, हालांकि सही से यह डीक्यू की एक विशिष्ट डेटा संरचना कार्यान्वयन को संदर्भित करता है (नीचे देखें)।

नामोल्लेखन कन्वेंशन

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

विभेद और सबटाइप

यह क्यू अमूर्त डेटा टाइप या ''प्रथम प्रवेश प्रथम निर्गम'' सूची (फीफो (कंप्यूटिंग और इलेक्ट्रॉनिक्स)) से भिन्न है, जहाँ तत्वों को केवल एक एंड (सिरे) पर जोड़ा जा सकता है और दूसरे से हटाया जा सकता है। इस सामान्य डेटा क्लास के कुछ संभावित सबटाइप हैं:

  • एक इनपुट-प्रतिबंधित डेक वह है जहां दोनों सिरों से विलोपन किया जा सकता है, लेकिन प्रविष्टि केवल एक एंड पर किया जा सकता है।
  • एक आउटपुट-प्रतिबंधित डेक वह है जहां दोनों सिरों पर प्रविष्टि किया जा सकता है, लेकिन विलोपन केवल एक एंड से किया जा सकता है।

कंप्यूटिंग, क्यू (डेटा संरचना) और स्टैक (डेटा संरचना) में आधारभूत और सबसे सामान्य सूची प्रकार दोनों को डेक की विशेषज्ञता माना जा सकता है, और डेक का उपयोग करके कार्यान्वित किया जा सकता है।

संचालन

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

भाषाओं के बीच नाम भिन्न होते हैं; प्रमुख कार्यान्वयन में सम्मिलित हैं:

संचालन सामान्य नाम एडीए C++ जावा व्यावहारिक निष्कर्षण

और रिपोर्ट भाषा

हाइपरटेक्स्ट प्रीप्रोसेसर पायथन रूबी आरयूएसटी जावास्क्रिप्ट
पीछे की ओर तत्व निर्दिष्ट करे इंजेक्ट, स्नोक, पुश Append push_back offerLast push array_push append push push_back push
सामने तत्व निर्दिष्ट करे पुश, कॉन्स Prepend push_front offerFirst unshift array_unshift appendleft unshift push_front unshift
अंतिम तत्व को हटा दें इजेक्ट Delete_Last pop_back pollLast pop array_pop pop pop pop_back pop
पहले तत्व को हटा दें पॉप Delete_First pop_front pollFirst shift array_shift popleft shift pop_front shift
अंतिम तत्व का परीक्षण पीक Last_Element back peekLast $array[-1] end <obj>[-1] last back <obj>.at(-1)
पहले तत्व का परीक्षण First_Element front peekFirst $array[0] reset <obj>[0] first front <obj>[0]


कार्यान्वयन

डेक को प्रभावी रूप से प्रयुक्त करने के कम से कम दो सामान्य तरीके हैं: एक संशोधित गतिशील सरणी के साथ या एक दोगुनी लिंक्ड सूची के साथ।

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

  • डेक सामग्री को एक परिपत्र बफ़र में संग्रहीत करना, और केवल तभी आकार बदलना जब बफ़र पूर्ण हो जाता है। इससे आकार बदलने की आवृत्ति कम हो जाती है।
  • अंतर्निहित सरणी के केंद्र से डेक सामग्री आवंटित करना, और अंत तक पहुंचने पर अंतर्निहित सरणी का आकार बदलना। इस दृष्टिकोण को अधिक बार आकार बदलने और अधिक स्थान नष्ट करने की आवश्यकता हो सकती है, विशेषकर जब तत्व केवल एक एंड पर निर्दिष्ट किए जाते हैं।
  • सामग्री को कई छोटे सरणियों में संग्रहीत करना, आवश्यकतानुसार प्रारंभ या अंत में अतिरिक्त सरणियाँ आवंटित करना। प्रत्येक छोटे सरणियों में पॉइंटर्स युक्त एक गतिशील सरणी रखकर इंडेक्सिंग को कार्यान्वित किया जाता है।

पूर्ण रूप से कार्यात्मक कार्यान्वयन

डबल-एंडेड कतारों को विशुद्ध रूप से कार्यात्मक डेटा संरचना के रूप में भी प्रयुक्त किया जा सकता है।[3]: 115  कार्यान्वयन के दो संस्करण सम्मिलित हैं। पहला, जिसे 'वास्तविक समय डेक' कहा जाता है, नीचे प्रस्तुत किया गया है। यह क्यू को ओ (1) सबसे विकृत समय में संचालन के साथ निरंतर रहने की स्वीकृति देता है, लेकिन मेमोइज़ेशन के साथ लेज़ी सूचियों की आवश्यकता होती है। दूसरा, जिसमें कोई लेज़ी सूची नहीं है और न ही मेमोइज़ेशन भागों के अंत में प्रस्तुत किया गया है। इसका परिशोधन समय O(1) है यदि दृढ़ता का उपयोग नहीं किया जाता है; लेकिन किसी संचालन की सबसे विकृत समय की जटिलता O(n) है जहां n डबल-एंडेड क्यू में तत्वों की संख्या है।

आइए पुनः कॉल करते हैं कि, एक सूची के लिए l, |l| इसकी लंबाई को दर्शाता है, कि NIL एक रिक्त सूची का प्रतिनिधित्व करता है और CONS(h, t) उस सूची का प्रतिनिधित्व करता है जिसका शीर्ष h है और टैल t है। फ़ंक्शन drop(i, l) और take(i, l) क्रमशः l के पहले iतत्वों और i के पहले l, तत्वों के बिना सूचीदेते हैं। या, यदि |l|< i, वे क्रमशः रिक्त सूची और l देते है।

लेज़ी पुनर्निर्माण और शेड्यूलिंग के माध्यम से वास्तविक समय डेक

एक डबल-एंडेड क्यू को सेक्स्टुपल के रूप में दर्शाया गया है (len_front, front, tail_front, len_rear, rear, tail_rear) कहाँ front एक लिंक्ड सूची है जिसमें लंबाई की क्यू के सामने होता है len_front. इसी प्रकार, rear एक लिंक की गई सूची है जो लंबाई की क्यू के पीछे के हिस्से का प्रतिनिधित्व करती है len_rear. साथ ही यह भी आश्वासन दिया है |front| ≤ 2|rear|+1 और |rear| ≤ 2|front|+1 - सहज रूप से, इसका मतलब है कि आगे और पीछे दोनों में एक तिहाई माइनस एक और दो तिहाई प्लस एक तत्व होता है। आखिरकार, tail_front और tail_rear की पूंछ हैं front और का rear, वे उस पल को शेड्यूल करने की स्वीकृति देते हैं जहां कुछ लेज़ी संचालन को मजबूर किया जाता है। ध्यान दें कि, जब एक डबल-एंडेड क्यू में सम्मिलित होता है n सामने की सूची में तत्व और n पीछे की सूची में तत्व, उसके बाद असमानता अपरिवर्तनीय संतुष्ट रहती है i निवेशन और d विलोपन जब (i+d) ≤ n/2. यानी ज्यादा से ज्यादा n/2 संचालन प्रत्येक पुनर्संतुलन के बीच हो सकता है।

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

empty = (0, NIL, NIL, 0, NIL, NIL)
fun insert'(x, (len_front, front, tail_front, len_rear, rear, tail_rear)) =
  (len_front+1, CONS(x, front), drop(2, tail_front), len_rear, rear, drop(2, tail_rear))
fun head((_, CONS(h, _), _, _, _, _)) = h
fun head((_, NIL, _, _, CONS(h, NIL), _)) = h
fun tail'((len_front, CONS(head_front, front), tail_front, len_rear, rear, tail_rear)) =
  (len_front - 1, front, drop(2, tail_front), len_rear, rear, drop(2, tail_rear))
fun tail'((_, NIL, _, _, CONS(h, NIL), _)) = empty

यह समझाने के लिए बनी हुई है कि किसी विधि को कैसे परिभाषित किया जाए balance कि डेक अगर rebalance insert' या tail अपरिवर्तनीय तोड़ दिया। प्रक्रिया insert और tail पहले आवेदन करके परिभाषित किया जा सकता है insert' और tail' और फिर आवेदन करना balance.

fun balance(q as (len_front, front, tail_front, len_rear, rear, tail_rear)) =
  let floor_half_len = (len_front + len_rear) / 2 in
  let ceil_half_len = len_front + len_rear - floor_half_len in
  if len_front > 2*len_rear+1 then
    let val front' = take(ceil_half_len, front)
        val rear' = rotateDrop(rear, floor_half_len, front)
    in (ceil_half_len, front', front', floor_half_len, rear', rear')
  else if len_front > 2*len_rear+1 then
    let val rear' = take(floor_half_len, rear)
        val front' = rotateDrop(front, ceil_half_len, rear)
    in (ceil_half_len, front', front', floor_half_len, rear', rear')
  else q

कहाँ rotateDrop(front, i, rear)) का संयोजन वापस करें front और का drop(i, rear). वह हैfront' = rotateDrop(front, ceil_half_len, rear) में डालें front' की सामग्री front और की सामग्री rear वह पहले से ही अंदर नहीं है rear'. गिरने के बाद से n तत्व लेता है समय, हम आलस्य का उपयोग यह सुनिश्चित करने के लिए करते हैं कि तत्वों को दो-दो से गिराया जाए, प्रत्येक के दौरान दो बूंद की जाए tail' और प्रत्येक insert' कार्यवाही।

fun rotateDrop(front, i, rear) =
  if i < 2 then rotateRev(front, drop(i, rear), $NIL)
  else let $CONS(x, front') = front in
    $CONS (x, rotateDrop(front', j-2, drop(2, rear)))

कहाँ rotateRev(front, middle, rear) एक ऐसा कार्य है जो सामने लौटाता है, उसके बाद मध्य उलटा होता है, उसके बाद पीछे होता है। इस फ़ंक्शन को आलस्य का उपयोग करके भी परिभाषित किया गया है ताकि यह सुनिश्चित किया जा सके कि प्रत्येक चरण के दौरान एक चरण के साथ इसकी गणना चरण दर चरण की जा सकती है insert' और tail' और लगातार समय ले रहा है। यह फ़ंक्शन उस अपरिवर्तनीय का उपयोग करता है |rear|-2|front| 2 या 3 है।

fun rotateRev(NIL, rear, a)=
  reverse(rear++a)
fun rotateRev(CONS(x, front), rear, a)=
  CONS(x, rotateRev(front, drop(2, rear), reverse (take(2, rear))++a))

कहाँ ++ दो सूचियों को जोड़ने वाला कार्य है।

आलस्य के बिना कार्यान्वयन

ध्यान दें कि, कार्यान्वयन के लेज़ी भाग के बिना, यह क्यू में एक गैर-निरंतर कार्यान्वयन होगा O(1) परिशोधित विश्लेषण। इस मामले में, सूचियाँ tail_front और tail_rear डबल-एंडेड क्यू के प्रतिनिधित्व से हटाया जा सकता है।

भाषा समर्थन

एडा (प्रोग्रामिंग भाषा) के कंटेनर सामान्य पैकेज प्रदान करते हैं Ada.Containers.Vectors और Ada.Containers.Doubly_Linked_Lists, क्रमशः गतिशील सरणी और लिंक्ड सूची कार्यान्वयन के लिए।

सी++ की मानक टेम्पलेट लाइब्रेरी क्लास टेम्पलेट प्रदान करती है std::डेक और std::list, क्रमशः एकाधिक सरणी और लिंक्ड सूची कार्यान्वयन के लिए।

जावा 6 के अनुसार, जावा का कलेक्शंस फ्रेमवर्क एक नया प्रदान करता है Deque इंटरफ़ेस जो दोनों सिरों पर प्रविष्टि और हटाने की कार्यक्षमता प्रदान करता है। यह जैसे वर्गों द्वारा कार्यान्वित किया जाता है ArrayDeque (जावा 6 में भी नया) और LinkedList, क्रमशः डायनेमिक सरणी और लिंक्ड सूची कार्यान्वयन प्रदान करता है। हालांकि ArrayDeque, इसके नाम के विपरीत, रैंडम एक्सेस का समर्थन नहीं करता है।

जावास्क्रिप्ट के Array प्रोटोटाइप और पर्ल की सरणियों को दोनों को हटाने के लिए मूल समर्थन है (/functions/shift.html shift और pop) और जोड़ना (unshift और push) दोनों सिरों पर तत्व।

पायथन 2.4 ने पेश किया collections डेक ऑब्जेक्ट्स के समर्थन के साथ मॉड्यूल। इसे निश्चित-लंबाई वाली उप-सरणियों की दोगुनी लिंक्ड सूची का उपयोग करके कार्यान्वित किया जाता है।

PHP 5.3 के अनुसार, PHP के SPL एक्सटेंशन में 'SplDoublyLinkedList' क्लास सम्मिलित है जिसका उपयोग Deque डेटास्ट्रक्चर को प्रयुक्त करने के लिए किया जा सकता है। पहले डेक संरचना बनाने के लिए सरणी फ़ंक्शन array_shift/unshift/pop/push का उपयोग इसके अतिरिक्त किया जाना था।

ग्लासगो हास्केल कंपाइलर Data.Sequence मॉड्यूल हास्केल (प्रोग्रामिंग भाषा) में एक कुशल, कार्यात्मक डेक संरचना प्रयुक्त करता है। कार्यान्वयन 2–3 ट्री | 2–3 फिंगर ट्री का उपयोग करता है जो आकार के साथ एनोटेट किए गए हैं। विशुद्ध रूप से कार्यात्मक (इस प्रकार भी लगातार डेटा संरचना) डबल कतारों को प्रयुक्त करने के लिए अन्य (तेज) संभावनाएं हैं (ज्यादातर लेज़ी मूल्यांकन का उपयोग करते हुए)।[3][4] कापलान और टारजन सबसे पहले इष्टतम कंफर्टेबलली परसिस्टेंट कैटेनेबल डेक्स को प्रयुक्त करने वाले थे।[5] उनका कार्यान्वयन पूरी तरह से कार्यात्मक था इस अर्थ में कि यह लेज़ी मूल्यांकन का उपयोग नहीं करता था। ओकासाकी ने बूटस्ट्रैप्ड डेटा संरचना के साथ लेज़ी मूल्यांकन का उपयोग करके डेटा संरचना को सरल बनाया और प्रदर्शन सीमा को सबसे खराब स्थिति से परिशोधित कर दिया। कापलान, ओकासाकी, और टारजन ने एक सरल, गैर-बूटस्ट्रैप्ड, परिशोधित संस्करण का उत्पादन किया जिसे या तो लेज़ी मूल्यांकन का उपयोग करके या व्यापक रूप से अभी भी प्रतिबंधित फैशन में म्यूटेशन का उपयोग करके अधिक कुशलता से प्रयुक्त किया जा सकता है। मिहासौ और टारजन ने एक सरल (लेकिन अभी भी अत्यधिक जटिल) कैटेनेबल डेक्स का सख्ती से कार्यात्मक कार्यान्वयन बनाया, और सख्ती से पूरी तरह कार्यात्मक गैर-कैटेनेबल डेक्स का बहुत सरल कार्यान्वयन भी किया, जिनमें से दोनों में इष्टतम सबसे खराब स्थिति सीमा है।

जंग का std::collections इसमें VecDeque सम्मिलित है जो बढ़ने योग्य रिंग बफर का उपयोग करके डबल-एंडेड क्यू को प्रयुक्त करता है।

जटिलता

  • एक दोगुनी-लिंक्ड सूची कार्यान्वयन में और कोई आवंटन/डीललोकेशन ओवरहेड नहीं मानते हुए, सभी डेक संचालन की समय जटिलता ओ (1) है। इसके अतिरिक्त, बीच में सम्मिलन या विलोपन की समय जटिलता, एक पुनरावर्तक दिया गया है, ओ (1) है; हालाँकि, इंडेक्स द्वारा रैंडम एक्सेस की समय जटिलता O(n) है।
  • एक बढ़ते सरणी में, सभी डेक संचालन की परिशोधित समय जटिलता हे (1) है। इसके अतिरिक्त, इंडेक्स द्वारा रैंडम एक्सेस की समय जटिलता O(1) है; लेकिन बीच में प्रविष्टि या विलोपन की समय जटिलता (एन) है।

एप्लीकेशन

वेब ब्राउज़िंग इतिहास को संग्रहीत करने के लिए एक डबल-एंडेड क्यू का उपयोग किया जा सकता है: क्यू के अंत में नई वेबसाइटें जोड़ी जाती हैं, जबकि इतिहास बहुत बड़ा होने पर सबसे पुरानी प्रविष्टियां हटा दी जाएंगी। जब कोई उपयोगकर्ता पिछले एक घंटे के ब्राउज़िंग इतिहास को साफ़ करने के लिए कहता है, तो सबसे हाल ही में जोड़ी गई प्रविष्टियाँ हटा दी जाती हैं।

उदाहरण जहां डेक का उपयोग किया जा सकता है वह कार्य स्टालिंग एल्गोरिथम है।[6] यह एल्गोरिथम कई प्रोसेसरों के लिए टास्क शेड्यूलिंग को प्रयुक्त करता है। प्रत्येक प्रोसेसर के लिए निष्पादित किए जाने वाले थ्रेड्स के साथ एक अलग डेक बनाए रखा जाता है। अगले थ्रेड को निष्पादित करने के लिए, प्रोसेसर को डेक से पहला तत्व मिलता है (पहले तत्व डेक संचालन को हटाकर)। यदि वर्तमान थ्रेड फोर्क होता है, तो इसे डीक्यू के सामने वापस रखा जाता है (फ्रंट तत्व निर्दिष्ट) और एक नया थ्रेड निष्पादित किया जाता है। जब प्रोसेसर में से एक अपने स्वयं के थ्रेड्स का निष्पादन पूरा करता है (अर्थात इसका डेक रिक्त है), तो यह दूसरे प्रोसेसर से एक थ्रेड 'स्टील' सकता है: यह दूसरे प्रोसेसर के डेक से अंतिम तत्व प्राप्त करता है (बैक तत्व को हटा दें) और इसे निष्पादित करता है। समानांतर प्रोग्रामिंग के लिए इंटेल के थ्रेडिंग बिल्डिंग ब्लॉक्स (टीबीबी) लाइब्रेरी द्वारा कार्य स्टालिंग एल्गोरिदम का उपयोग किया जाता है।

यह भी देखें

संदर्भ

  1. Jesse Liberty; Siddhartha Rao; Bradley Jones. C++ in One Hour a Day, Sams Teach Yourself, Sixth Edition. Sams Publishing, 2009. ISBN 0-672-32941-7. Lesson 18: STL Dynamic Array Classes, pp. 486.
  2. Donald Knuth. The Art of Computer Programming, Volume 1: Fundamental Algorithms, Third Edition. Addison-Wesley, 1997. ISBN 0-201-89683-4. Section 2.2.1: Stacks, Queues, and Deques, pp. 238–243.
  3. 3.0 3.1 Okasaki, Chris (September 1996). विशुद्ध रूप से कार्यात्मक डेटा संरचनाएं (PDF) (Ph.D. thesis). Carnegie Mellon University. CMU-CS-96-177.
  4. Adam L. Buchsbaum and Robert E. Tarjan. Confluently persistent deques via data structural bootstrapping. Journal of Algorithms, 18(3):513–547, May 1995. (pp. 58, 101, 125)
  5. Haim Kaplan and Robert E. Tarjan. Purely functional representations of catenable sorted lists. In ACM Symposium on Theory of Computing, pages 202–211, May 1996. (pp. 4, 82, 84, 124)
  6. Blumofe, Robert D.; Leiserson, Charles E. (1999). "काम चोरी करके मल्टीथ्रेडेड कंप्यूटेशंस शेड्यूल करना" (PDF). J ACM. 46 (5): 720–748. doi:10.1145/324133.324234. S2CID 5428476.


बाहरी संबंध