STL中deque和vector的建構函式,assign基本相同,重點介紹deque的特性,deque和vector的主要區別如下:
deque是雙端隊列的資料結構,可以在隊首和隊尾高效的添加和刪除元素,這是相對於vector的優勢。
deque內部採用分段連續的記憶體空間來儲存元素,在插入元素的時候隨時都可以重新增加一段新的空間並連結起來,因此雖然提供了隨機訪問操作,但訪問速度和vector相比要慢。
deque並沒有data函數,因為deque的元素並沒有放在數組中。
deque不提供capacity和reserve操作。 deque內部的插入和刪除元素要比list慢。
由於deque在效能上並不是最高效的,有時候對deque元素進行排序,更高效的做法是,將deque的元素移到vector再進行排序,然後在移到回來。
deque為了實現整體連續的假象,導致其實現起來比較繁瑣,盡量少使用它。
deque的實現原理:http://blog.csdn.net/baidu_28312631/article/details/48000123,該文敘述很清楚,可以參考。
deque的源碼剖析:http://blog.csdn.net/terence1212/article/details/52326945,該文可以參考 deque deque的初始化 deque的初始化,見如下代碼。deque的初始化和vector完全相同
deque的assign函數,同樣有三種方式,初始化列表,賦值若干個相同的值,任意一個序列容器的範圍
deque<int> v2; // deque with 0 elementdeque<int> v3(20); // deque with 20 elements whose value is 0deque<int> v4(20, 5);// deque with 20 elements whose value is 5deque<int> v5{ 20 }; // deque with 1 element whose value is 20deque<int> v6(v4); // copy construct functiondeque<int> v7(v4.begin(), v4.end());//construct functiondeque<int> v8({ 1,2,3,4,5 });// construct a deque with initialize listdeque<int> v9{ 1,2,3,4,5 };// construct a deque with initialize listdeque<int> v10 = { 1,2,3,4,5 };// assignment construct function
deque的assign
deque的assign有三種形式,assign
deque<int> mydeque;deque<int> temp{ 1,2,4,5,6 };mydeque.assign(temp.begin(), temp.end()); //接受序列容器的範圍mydeque.assign(3, 5); //變為3個值,每個值都是5mydeque.assign({ 1,2,3,4,5,6 }); //賦值一個初始化列表
deque的添加元素 deque中添加元素,除了push_back和emplace_back之外,由於是雙端隊列,因此可以在隊首添加元素,deque中還有push_front和emplace_front等。
deque<int> myDeque;myDeque.push_back(1);myDeque.push_front(2);myDeque.emplace_back(3);myDeque.emplace_front(6);copy(myDeque.begin(), myDeque.end(), ostream_iterator<double>(cout, " "));
list
list特點
list和deque的元素在記憶體的組織形式不同,以鏈表的形式儲存
list和deque相同,也可以在尾部和頭部加入元素,因此也支援push_back和push_front以及emplace_front和emplace_back
list可以高效的在內部插入元素而不需要移動元素,list是雙向鏈表
list的insert函數和emplace與vector,deque的方式完全相同 list的特有的一些函數 list專屬的成員函數remove()可以移除和參數匹配的元素。例如如下代碼:
std::list<int> numbers{2,5,2,3,6,7,8,2,9};numbers.remove(2);// 刪除元素值為2的元素copy(numbers.begin(), numbers.end(), ostream_iterator<int>(cout, " "));
成員函數remove_if()期望傳入一個一元斷言作為參數,一元斷言接受一個和元素同類型的參數或引用,返回一個布爾值。斷言返回true的元素都會被移除。斷言可以是一個函數,也可以是一個lambda運算式。
std::list<int> numbers{2,5,2,3,6,7,8,2,9};auto f = [](const int& i)->bool {return i % 2 == 0; };numbers.remove_if(f);//刪除所有偶數copy(numbers.begin(), numbers.end(), ostream_iterator<int>(cout, " "));
成員函數unique,可以移除
連續重複的元素 ,只留下一個,但是該函數不能刪除list中不連續的重複的元素。因此,如果需要重複資料刪除元素,則需要排序,排序之後再重複資料刪除元素。
unique()函數重載形式兩種,一種沒有參數,有參數的版本接受一個二元斷言。斷言返回true的元素被認為是相等的。
//沒有經過sort,直接uniquenumbers.assign({ 2,5,2,4,7,7,7,8});numbers.unique();// {2,5,2,4,7,8} 未重複資料刪除但不連續的元素copy(numbers.begin(), numbers.end(), ostream_iterator<int>(cout, " "));// sort 之後uniquenumbers.assign({ 2,5,2,4,7,7,7,8 });numbers.sort();// 2,2,4,5,7,7,7,8numbers.unique();// 2,4,5,7,8copy(numbers.begin(), numbers.end(), ostream_iterator<int>(cout, " "));//unique 的重載形式numbers.assign({ 2,5,2,4,7,7,7,8 });numbers.sort();// 2 2 4 5 7 7 7 8auto f1 = [](const int& a, const int& b)->bool {return a % 2 == b % 2; };numbers.unique(f1);// 2 5 8copy(numbers.begin(), numbers.end(), ostream_iterator<int>(cout, " "));
sort()函數有兩個版本:無參數的sort()將所有元素升序排列,有參數版本的sort()函數接受一個函數對象或者lambda函數,用來表明排序依據。
// 使用斷言numbers.assign({ 2,5,2,4,7,7,7,8 });numbers.sort(greater<>());// 2 2 4 5 7 7 7 8// 使用lambda函數numbers.assign({ 2,5,2,4,7,7,7,8 });auto f3 = [](const int&a, const int& b)->bool{return a>b;};numbers.sort(f3);// 2 2 4 5 7 7 7 8
上述例子中使用了functional中的模板greater<T>斷言,這裡可以使用gerater<int>的形式,也可以使用greater<>的形式,後者是簡潔版本的函數對象,可以接受任何類型的參數,使用完美轉寄(perfect forwarding)可以避免參數拷貝,被比較的參數會被移動而不是複製到函數中。