वेक्टर / सूची का उपयोग कब किया जाना चाहिए?


17

मैं समझ सकता हूं कि सूचियों का उपयोग कब करना है, लेकिन मुझे समझ में नहीं आता है कि वीडियो गेम में सूचियों का उपयोग करने से बेहतर है कि कब वैक्टर का उपयोग किया जाए: जब बेहतर रैंडम एक्सेस हो तो बेहतर है?

(और मुझे समझ में आया कि सूचियों में सम्मिलित करना / हटाना अधिक तेज़ है क्योंकि यह केवल संकेत हटाता है / जोड़ता है, लेकिन इसे अभी भी संबंधित आइटम ढूंढना है ...)


इसमें पुन: जोड़ा हुआ वेक्टर टैग - यदि सूची एक वैध टैग है, तो वेक्टर भी है।
काइलोटन

संभवतः वेक्टर को हटा दिया गया था क्योंकि इसका मतलब गणितीय वेक्टर है, न कि std :: वेक्टर।

1
कैसे उन दोनों के बारे में निक्स और डाल दिया container
deft_code

@ Kylotan: यह जो कहा के रूप में है। यह सवाल निश्चित रूप से वैक्टर के बारे में था, लेकिन यह वेक्टर टैग के साथ नहीं था।
doppelgreener

1
तो क्या हम कोई अस्पष्ट टैग हटा देते हैं? यह मेरे लिए गलत निर्णय की तरह लगता है - बेहतर है कि आपकी खोज पर्याप्त नहीं की तुलना में बहुत अधिक जानकारी को बदल देती है। अनचाहे परिणामों को छोड़ना समानार्थी शब्द खोजने के लिए मंथन से आसान है।
काइलोटन

जवाबों:


29

मेरे अंगूठे का नियम, और मुझे यकीन है कि इस पर बहस होगी, कभी भी सूचियों का उपयोग नहीं करना है (जब तक कि आपको बहुत जरूरत नहीं है, बहुत बार बड़ी सूची के बीच से चीजों को हटा दें)।

आपके कंटेनर में आपके सभी तत्व सन्निहित स्मृति (और इसलिए अधिक कैश-फ्रेंडली) में होने से आपको जो गति मिलेगी, वह वेक्टर को जोड़ने / हटाने / आकार बदलने की अतिरिक्त लागतों की भरपाई के लायक है।

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


1
मुझे लगता है कि यह आपकी आवश्यकताओं पर अत्यधिक निर्भर करता है, अगर आपको कभी किसी विशिष्ट तत्व तक पहुंचने की आवश्यकता नहीं है और बस उन सभी को पढ़ने की आवश्यकता है और आप अक्सर तत्वों को जोड़ते और निकालते हैं, तो सूची एक बेहतर समाधान है।
Frédérick Imbeault

11
@ Frédérick: यह मानक C ++ ज्ञान है, लेकिन यह भी लगभग हमेशा गलत है। वेक्टर्स, खासकर जब पॉइंटर्स के वैक्टर (जो आप लगभग हमेशा गेम के लिए होते हैं) के साथ काम करते हैं, बीच से सामान निकालने के लिए बेहद तेज़ होते हैं - यह रैखिक समय है, लेकिन यह प्रति आइटम बहुत छोटा ओवरहेड है। यह भी एक वेक्टर पर क्रमिक रूप से पुनरावृति करने के लिए बहुत तेज है।

1
मुझे यकीन नहीं है कि आप किस प्रकार की संरचना प्राप्त कर रहे हैं - इस तरह के अनुकूलन को निश्चित रूप से कुछ भी कहने के लिए ठोस उदाहरणों की आवश्यकता होती है। उदाहरण के लिए, आपके उपयोग के मामले में मेरी पहली प्रतिक्रिया एक अनियंत्रित सेट होगी, जो समान रूप से तेज़ प्रविष्टि, विलोपन और लुकअप की अनुमति देता है; मेरे अनुभव के सेट संपादकों की वस्तुओं के लिए बहुत अच्छे हैं। लेकिन जैसा कि संपादकों के पास वास्तविक समय की प्रदर्शन आवश्यकताएं होती हैं - जैसे कि "डिलीट" बटन का जवाब देना ठीक है, दूसरे का 1/20 वाँ समय लेता है या दूसरे 10% समय का 1/2 वां हिस्सा लेता है - इस स्तर का अनुकूलन उन पर भी शायद ही कभी लागू होता है।

1
@ Frédérick Imbeault संशोधित एक समस्या का ज्यादा नहीं है यह Add \ Remove है जो समस्याओं का कारण बनता है। वेक्टर के अंत को जोड़ने के लिए वेक्टर के अंत में add \ remove किए गए बिंदु से कॉपी किया जाता है। यदि तत्व आदेश मायने नहीं रखता है, तो आप हटाए गए तत्व को अंतिम तत्व के साथ स्वैप कर सकते हैं फिर हटाएं और जोड़ के लिए अंत में जोड़ें।
पत्थरबाज़ २al

4
ठीक है, एक वेक्टर में एक तत्व का पता लेने और भंडारण कि सुरक्षित नहीं है। लेकिन आम तौर पर आप शायद ही कभी ऐसा बोल रहे हों, इसके बजाय तत्वों के संकेत का एक वेक्टर पसंद करते हैं और पॉइंटर को चारों ओर (या समान रूप से) कॉपी करते हैं।
तेतराद

8

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

आप Deque का उपयोग करने पर भी विचार कर सकते हैं। इसमें वेक्टर के समान प्रदर्शन विशेषताएं होती हैं, लेकिन सन्निहित स्मृति के लिए वेक्टर की आवश्यकता नहीं होती है, और थोड़ा अधिक लचीला होता है।


+1 देवताओं का उल्लेख करने वाले एकमात्र व्यक्ति होने के लिए - आपको वैक्टर की मेमोरी और लुकअप गति का लाभ मिलता है, जिसमें दोनों सिरों को तेजी से सम्मिलित / हटाया जाता है।

5

आपकी पसंद आपकी आवश्यकताओं को दर्शाती है। वैक्टर के सभी तत्व स्मृति में निरंतर हैं और सूचियों में अगले / पिछले तत्वों की ओर संकेत है ताकि वे प्रत्येक को अपना लाभ / नुकसान दे सकें:

सूची:

  • प्रत्येक तत्व पिछले और अगले तत्वों को इंगित करने के लिए 2 पूर्णांक लेता है, इसलिए सबसे अधिक, यह आपकी सूची में प्रत्येक तत्वों के लिए 8 बाइट्स अधिक है
  • सम्मिलित समय में रैखिक है: O (n)
  • निकालें एक निरंतर ऑपरेशन है: O (1)
  • एक्स तत्व को समय में रैखिक है: O (n)

क्षेत्र:

  • कम मेमोरी की आवश्यकता है (अन्य तत्वों के लिए कोई संकेत नहीं है, यह एक सरल गणित एल्गोरिदम है)
  • निकालें समय में रैखिक है: O (n)
  • एक्स तत्व को एक्सेस करना स्थिर है: O (1) (क्योंकि मेमोरी में तत्व निरंतर हैं इसलिए यह एक साधारण गणित ऑपरेशन वेक्टरप्रेट + (x * बाइट्सऑफटाइप) है)
  • सम्मिलित करें रैखिक समय में हो सकता है, लेकिन सबसे आम तौर पर, यह एक निरंतर ऑपरेशन है: O (1) (ऐसा इसलिए है क्योंकि किसी सरणी में वेक्टर लेकिन हमेशा 2 बार आरक्षित होता है जब सरणी पूरी होती है तो सरणी प्रतिलिपि अक्सर नहीं होती है)

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

स्टैकओवरफ़्लो पर इस पोस्ट की जाँच करें, यह आपकी आवश्यकताओं पर बुनियादी सवालों के साथ एक बहुत अच्छा ग्राफ पेश करता है जो आपको एक विशेष कंटेनर में आपके कंप्यूटर पर निर्भर करता है:

/programming/366432/extending-stdlist


3
उस ग्राफ को वास्तव में "क्या आप पॉइंटर्स स्टोर कर रहे हैं और एक हजार से कम है? नहीं -> वेक्टर" नोड।

हां शायद आप सही हैं, मैंने इस बात पर विचार नहीं किया कि संग्रहित प्रकार का भी विश्लेषण किया जाना चाहिए।
Frédérick Imbeault

2

आमतौर पर सूचियों का उपयोग कतारों जैसी संरचनाओं के लिए किया जाता है जहां बहुत सारे एपेंड होते हैं और संचालन को हटाते हैं। उदाहरण: अद्यतन करने वाली संस्थाओं की कभी बदलती सूची। सूची में स्क्रीन पर केवल इकाइयाँ ही होती हैं और इसलिए अक्सर बदलती रहती हैं।

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

Tetrads की राय सत्य हो सकती है, लेकिन यह उस प्रोग्रामिंग भाषा पर निर्भर करता है जिसका उपयोग किया जाता है। मैं देखता हूं कि आपने अपने प्रश्न को टैग कर दिया है c++, लेकिन मैंने एक ऐसा उत्तर देने की कोशिश की, जो भाषा-विशिष्ट नहीं है।


वैसे मैंने इसमें C भी डाला होगा, लेकिन C में ऐसे कंटेनर नहीं हैं, लेकिन इस बारे में सोचने के लिए कुछ है: क्या C के लिए कुछ एसटीएल जैसा ट्रेंड है?
जोकून

मैंने अतीत में glib ( Library.gnome.org/devel/glib ) का उपयोग किया है, जो सी के लिए कई मानक डेटा संरचनाओं को लागू करता है। मुझे इससे नफरत थी क्योंकि यह आमतौर पर बहुत अधिक क्रियाशील है और सख्त तौर पर C ++ बनना चाहता है, लेकिन परिपक्व है। स्थिर।

0

कंसोल गेम में, हम कभी भी std :: सूची का उपयोग नहीं करते हैं क्योंकि:

  1. जब भी आप कोई नया आइटम जोड़ते हैं, तो यह मेमोरी आवंटन करता है। मेमोरी आवंटन धीमा है।
  2. यह संकेत से भरा है। पॉइंटर्स खराब हैं। एक सूचक एक कैश मिस है। कैश मिस खराब है।

यहां तक ​​कि एसटीडी :: वेक्टर कंसोल पर एहसान खो रहा है क्योंकि:

  1. आप अक्सर केवल देखभाल करते हैं, उदाहरण के लिए, सभी वस्तुओं की स्थिति। उदाहरण के लिए जैसे आप वस्तुओं को एक दूसरे से टकराना चाहते हैं, उस स्थिति में आपको परवाह नहीं है कि उनका रंग क्या है। इसलिए आप चाहते हैं कि सभी पद स्मृति में सन्निहित हों और आप चाहते हैं कि कैश को प्रदूषित होने से बचाने के लिए रंग कहीं और दूर हों। लेकिन std :: वेक्टर आपको मेमोरी के एक सन्निहित भाग में प्रत्येक वस्तु के लिए सब कुछ संग्रहीत करने की आवश्यकता है (जैसे स्थिति तब रंग।) इसलिए यदि आप ऐसा काम करते हैं जो केवल पदों को पढ़ता है, तो आपको सभी रंगों को कैश में भी पढ़ने की आवश्यकता है। यदि आप उनका उपयोग नहीं करते हैं। यह फिजूलखर्ची है।

5
@bmcnett "[] .. लेकिन std :: वेक्टर आपको प्रत्येक वस्तु के लिए स्मृति के एक सन्निहित भाग में सब कुछ संग्रहीत करने की आवश्यकता है" - यह कंटेनर का सवाल नहीं है, यह आपके डेटा-लेआउट का सवाल है, आपके पास सभी स्थिति हो सकती है एक std :: वेक्टर:struct point{float x, y, z, w}; std::vector<point> positions;
Maik सेमर

मेरा स्कूल इसे प्यार करने जा रहा है :)
jokoon

2
-1 क्योंकि यह उत्तर पहले से ही यहां की बनाम वेक्टर चर्चा की सूची में कुछ भी नहीं जोड़ता है, और वेक्टर के प्रदूषण के बारे में इसका दावा गलत है, जैसा कि मायक कहता है।

आपने मेरे दावे को गलत समझा। मैंने कभी नहीं कहा कि सभी कंटेनरों के बीच :: वेक्टर विशेष रूप से कैश को प्रदूषित करने का दोषी है। सभी कंटेनरों, और वास्तव में भी सरणियों, के बारे में समान रूप से दोषी हैं। std :: वेक्टर पक्ष से बाहर हो रहा है क्योंकि C ++ ऑब्जेक्ट स्वयं एहसान से गिर रहे हैं। C ++ यह बताता है कि प्रत्येक ऑब्जेक्ट का डेटा मेमोरी में सन्निहित है। जैसा कि ऊपर उल्लेख किया गया है, आप उदाहरण के लिए, C ++ ऑब्जेक्ट्स से बचकर, उदाहरण के लिए, st लगभग :: वेक्टर <स्थिति> का उपयोग करके प्राप्त कर सकते हैं।
bmcnett

3
सिवाय pointएक सी ++ ऑब्जेक्ट है (जैसा है std::vector, जैसा कि कुछ सरल है float)। मुझे पता है कि आप जिस अंतर को आकर्षित करने की कोशिश कर रहे हैं, लेकिन आप उसे समझाने का बुरा काम कर रहे हैं।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.