list and deque in STL
दो और sequence containers
[vector](/tutorial/cpp/vector/?lang=hi) के बाद STL दो और general-purpose sequence containers देती है:
- **
std::list** (header<list>) — doubly linked list। हर element अपने node में रहता है, जिसमें पिछले और अगले node के pointers होते हैं। - **
std::deque** (header<deque>, उच्चारण "डेक") — double-ended queue। Elements कई fixed-size blocks में रखे जाते हैं, इसलिए यह आगे और पीछे दोनों तरफ़ बढ़ सकती है।
list : [78] <-> [91] <-> [66] <-> [84] (nodes memory में कहीं भी) deque: [ block ][ block ][ block ] (दोनों सिरों पर तेज़ बढ़त) vector: [ 78 | 91 | 66 | 84 | ... ] (एक लगातार block)
std::list
List के आम functions
| Function | काम | Cost |
|---|---|---|
push_back(x), push_front(x) | पीछे / आगे जोड़ना | O(1) |
pop_back(), pop_front() | पीछे / आगे से हटाना | O(1) |
insert(it, x) | Iterator it से पहले जोड़ना | O(1) |
erase(it) | it वाला element हटाना | O(1) |
remove(x) | x के बराबर सभी elements हटाना | O(n) |
remove_if(pred) | Condition वाले elements हटाना | O(n) |
sort() | List sort करना (member function!) | O(n log n) |
unique() | लगातार duplicates हटाना | O(n) |
reverse() | क्रम उल्टा करना | O(n) |
merge(other) | दो sorted lists मिलाना | O(n) |
splice(it, other) | दूसरी list से nodes लाना, बिना copy | पूरी list के लिए O(1) |
front(), back(), size(), empty() | Access / जानकारी | O(1) |
operator[] नहीं है — 5वें element तक पहुँचने के लिए शुरुआत से चलना पड़ता है।
List उदाहरण
#include <iostream>
#include <list>
void print(const std::list<int>& l) {
for (int x : l) std::cout << x << " ";
std::cout << "\n";
}
int main() {
std::list<int> tokens = {40, 10, 30};
tokens.push_front(5); // 5 40 10 30
tokens.push_back(20); // 5 40 10 30 20
print(tokens);
auto it = tokens.begin();
std::advance(it, 2); // 10 की ओर इशारा
tokens.insert(it, 99); // 10 से पहले जोड़ो
print(tokens);
tokens.remove(40); // हर 40 हटाओ
tokens.sort(); // list::sort, std::sort नहीं
print(tokens);
tokens.reverse();
print(tokens);
return 0;
}std::deque
Deque के आम functions
| Function | काम | Cost |
|---|---|---|
push_back(x), push_front(x) | पीछे / आगे जोड़ना | O(1) amortised |
pop_back(), pop_front() | पीछे / आगे से हटाना | O(1) |
operator[], at(i) | Index से access | O(1) |
front(), back() | पहला / आख़िरी element | O(1) |
insert(it, x), erase(it) | बीच में insert / erase | O(n) |
size(), empty(), clear() | जानकारी / खाली करना | O(1) / O(n) |
Deque उदाहरण: हाल के marks की sliding window
#include <iostream>
#include <deque>
int main() {
std::deque<int> lastThree;
int tests[] = {62, 70, 58, 81, 77};
for (int m : tests) {
lastThree.push_back(m);
if (lastThree.size() > 3) lastThree.pop_front(); // सिर्फ 3 रखो
int sum = 0;
for (int x : lastThree) sum += x;
std::cout << "after " << m << ": average of last "
<< lastThree.size() << " = " << sum / lastThree.size() << "\n";
}
std::cout << "oldest kept: " << lastThree[0]
<< ", newest: " << lastThree.back() << "\n";
return 0;
}पीछे जोड़ना और आगे से हटाना दोनों O(1) हैं — vector में erase(begin()) पर हर element खिसकाना पड़ता।
vector vs list vs deque
| Feature | vector | deque | list |
|---|---|---|---|
| Memory layout | एक लगातार block | कई blocks | अलग-अलग nodes |
Index [i] से access | O(1) | O(1) | उपलब्ध नहीं |
| पीछे insert/remove | O(1) amortised | O(1) | O(1) |
| आगे insert/remove | O(n) | O(1) | O(1) |
| बीच में insert/remove | O(n) | O(n) | Iterator के साथ O(1) |
| Iterator type | Random-access | Random-access | Bidirectional |
std::sort चलता है | हाँ | हाँ | नहीं — list.sort() लें |
| Cache friendliness | सबसे अच्छी | अच्छी | कमज़ोर |
| हर element पर extra memory | नहीं | थोड़ी | दो pointers |
कौन-सा चुनें?
- Default:
vector। - दोनों सिरों पर तेज़ push/pop (queues, sliding windows, सीमित undo):
deque। - Iterators valid रखते हुए बीच में बहुत insert/delete, या
spliceसे हिस्से ले जाने हों:list।
असल में list students की उम्मीद से कम चुनी जाती है: छोटे और मध्यम sizes में cache के कारण बीच के insertions में भी vector अक्सर जीतता है।
आम गलतियाँ
listपरstd::sort(l.begin(), l.end())— compile error;l.sort()लें।- List पर
l[2]चलने की उम्मीद करना। - खाली container पर
front()याpop_front()— undefined behaviour; पहलेempty()check करें। - Unsorted list पर
unique()से सारे duplicates हटने की उम्मीद — यह सिर्फ *लगातार* duplicates हटाता है। - Deque के elements को लगातार मानकर
&d[0]किसी array वाले C function को भेजना।
Canteen के लिए deque<int> से आसान "token counter" बनाएँ: नए tokens पीछे जुड़ें, VIP token आगे जुड़े, और serve हुए tokens आगे से हटें। फिर students के नाम list<string> में रखें, देर से आए admission को alphabetical जगह पर insert करें और sort करें।
सारांश
list= doubly linked list: iterator के साथ कहीं भी O(1) insert/erase, indexing नहीं।deque= double-ended queue: दोनों सिरों पर O(1) और O(1) indexing।listके अपनेsort,remove,unique,merge,spliceहैं।- Default अब भी
vector; दोनों सिरों के काम के लिएdeque, बीच में ज़्यादा बदलाव के लिएlist।
संबंधित: STL परिचय, vector, stack और queue, iterators।
अक्सर पूछे जाने वाले प्रश्न (FAQ)
C++ में list और deque में क्या अंतर है?
std::list doubly linked list है: हर element अलग node है, इसलिए iterator हो तो कहीं भी insert या erase O(1) है, पर indexing नहीं होती। std::deque double-ended queue है जो fixed-size blocks से बनी है: दोनों सिरों पर तेज़ insertion और [] से तेज़ random access देती है, पर बीच में insert धीमा है।vector की जगह list कब इस्तेमाल करें?
list तभी लें जब बड़े sequence के बीच में बार-बार insert या erase करना हो और iterators पकड़े रखने हों, या बिना copy के elements दूसरी list में ले जाने के लिए splice चाहिए। बाकी ज़्यादातर कामों में vector तेज़ है क्योंकि उसके elements लगातार memory में होते हैं और cache-friendly हैं।क्या list पर std::sort चला सकते हैं?
std::sort को random-access iterators चाहिए, और list के पास सिर्फ bidirectional iterators हैं। इसकी जगह member function myList.sort() लें, जो nodes को फिर से जोड़कर O(n log n) में sort करता है।क्या deque vector की तरह indexing support करती है?
deque vector की तरह constant time में operator[] और at() support करती है। फ़र्क यह है कि deque आगे से भी constant time में elements जोड़-हटा सकती है, और उसके elements एक लगातार block में नहीं होते।