1、deque容器的基本概念
Vector容器是單向開口的連續內存空間,deque則是一種雙向開口的連續線性空間,又稱雙端動態數組。所謂的雙向開口,意思是可以在頭尾兩端分別做元素的插入和刪除操作,當然,vector容器也可以在頭尾兩端插入元素,但是在其頭部操作效率奇差,無法被接受。
2、與vector區別不同
Deque容器和vector容器最大的差異。
一在于deque允許使用常數項時間對頭端進行元素的插入和刪除 操作。
二在于deque沒有容量的概念,因為它是動態的以分段連續空間組合而成,隨時可以增加一段新的空間并鏈接起來,換句話說,像vector那樣,”舊空間不足而重新配置一塊更大空間,然后復制元素,再釋放舊空間”這樣的事情在deque身上是不會發生的。也因此,deque沒有必須要提供所謂的空間保留(reserve)功能. 雖然deque容器也提供了Random Access Iterator,但是它的迭代器并不是普通的指針, 其復雜度和vector不是一個量級,這當然影響各個運算的層面。
因此,除非有必要,我們應該盡可能的 使用vector,而不是deque。對deque進行的排序操作,為了最高效率,可將deque先完整的復制到一個vector中,對vector容器進行排序,再復制回deque。
3、deque容器的實現原理
Deque容器是連續的空間,至少邏輯上看來如此,連續現行空間總是令我們聯想到array和vector,array 無法成長,vector雖可成長,卻只能向尾端成長,而且其成長其實是一個假象,事實上(1) 申請更大空間 (2)原數據復制新空間 (3)釋放原空間 三步驟,如果不是vector每次配置新的空間時都留有余裕,其成長假象所帶來的代價是非常昂貴的。 Deque是由一段一段的定量的連續空間構成。一旦有必要在deque前端或者尾端增加新的空間,便配置一段連續定量的空間,串接在deque的頭端或者尾端。Deque最大的工作就是維護這些分段連續的內存空間的整體性的假象,并提供隨機存取的接口,避開了重新配置空間,復制,釋放的輪回,代價就是復雜的迭代器架構。 既然deque是分段連續內存空間,那么就必須有中央控制,維持整體連續的假象,數據結構的設計及迭代器的前進后退操作頗為繁瑣。Deque代碼的實現遠比vector或list都多得多。 Deque采取一塊所謂的map(注意,不是STL的map容器)作為主控,這里所謂的map是一小塊連續的內存空間,其中每一個元素(此處成為一個結點)都是一個指針,指向另一段連續性內存空間,稱作緩沖區。緩沖區才是deque的存儲空間的主體。
4、deque容器常用API
4.1deque構造函數
deque<T> deqT;//默認構造形式 deque(beg, end);//構造函數將[beg, end)區間中的元素拷貝給本身。 deque(n, elem);//構造函數將n個elem拷貝給本身。 deque(const deque &deq);//拷貝構造函數
4.2deque賦值操作
assign(beg, end);//將[beg, end)區間中的數據拷貝賦值給本身。 assign(n, elem);//將n個elem拷貝賦值給本身。
deque& operator=(const deque &deq); //重載等號操作符 swap(deq);// 將deq與本身的元素互換
案例:
#define _CRT_SECURE_NO_WARNINGS#include<iostream>#include<deque>
using namespace std;void printDequeInt(deque<int> &d)
{
deque<int>::iterator it = d.begin();
for(;it!=d.end(); it++)
{
cout<<*it<<" ";
}
cout<<endl;}
void test01(){
deque<int> d1(5,100);
printDequeInt(d1);
deque<int> d2;
d2.assign(d1.begin(), d1.begin()+2);
printDequeInt(d2);
deque<int> d3(5,10);
printDequeInt(d1);
printDequeInt(d3);
d1.swap(d3);
printDequeInt(d1);
printDequeInt(d3);}int main(){
test01() ;
return EXIT_SUCCESS;}
4.3deque大小操作
deque.size();//返回容器中元素的個數
deque.empty();//判斷容器是否為空
deque.resize(num);//重新指定容器的長度為num,若容器變長,則以默認值填充新位置。如果容器變 短,則末尾超出容器長度的元素被刪除。
deque.resize(num, elem); //重新指定容器的長度為num,若容器變長,則以elem值填充新位置,如果 容器變短,則末尾超出容器長度的元素被刪除
4.4deque雙端插入和刪除操作
push_back(elem);//在容器尾部添加一個數據 push_front(elem);//在容器頭部插入一個數據 pop_back();//刪除容器最后一個數據 pop_front();//刪除容器第一個數據
案例:
#define _CRT_SECURE_NO_WARNINGS#include<iostream>#include<deque>
using namespace std;void printDequeInt(deque<int> &d)
{
deque<int>::iterator it = d.begin();
for(;it!=d.end(); it++)
{
cout<<*it<<" ";
}
cout<<endl;}
void test01(){
deque<int> d1;
d1.push_back(10);
d1.push_back(20);
d1.push_back(30);
d1.push_front(40);
d1.push_front(50);
d1.push_front(60);
printDequeInt(d1);
//尾部刪除
d1.pop_back();
printDequeInt(d1);//60 50 40 10 20
d1.pop_front();
printDequeInt(d1);//50 40 10 20
cout<<d1[2]<<endl;//10
cout<<d1.at(2)<<endl;//10
d1.insert(d1.begin()+2, 3, 100);
printDequeInt(d1);//50 40 100 100 100 10 20
d1.erase(d1.begin()+2, d1.begin()+5);
printDequeInt(d1);//50 40 10 20
}int main(){
test01() ;
return EXIT_SUCCESS;}
4.5deque數據存取
at(idx);//返回索引idx所指的數據,如果idx越界,拋出out_of_range。 operator[];//返回索引idx所指的數據,如果idx越界,不拋出異常,直接出錯。 front();//返回第一個數據。back();//返回最后一個數據。
4.6deque插入操作
insert(pos,elem);//在pos位置插入一個elem元素的拷貝,返回新數據的位置。 insert(pos,n,elem);//在pos位置插入n個elem數據,無返回值。 insert(pos,beg,end);//在pos位置插入[beg,end)區間的數據,無返回值。
4.7deque刪除操作
clear();//移除容器的所有數據 erase(beg,end);//刪除[beg,end)區間的數據,返回下一個數據的位置。 erase(pos);//刪除pos位置的數據,返回下一個數據的位置。
5、deque容器使用案例
有5名選手:選手ABCDE,10個評委分別對每一名選手打分,去除最高分,去除評委中最低分,取平均分。 1. 創建五名選手,放到vector中 2. 遍歷vector容器,取出來每一個選手,執行for循環,可以把10個評分打分存到deque容器中 3. sort算法對deque容器中分數排序,pop_back pop_front去除最高和最低分 4. deque容器遍歷一遍,累加分數,累加分數/d.size() 5. person.score = 平均分
#include <iostream>#include <string>#include <vector>#include <deque>#include <stdlib.h>//srand rand#include <time.h>//time#include <algorithm>//sortusing namespace std;
class Person
{
private:
string name;
int score;
public:
Person(){}
Person(string name, int score)
{
this‐>name = name;
this‐>score = score;
}
void showPerson(void)
{
cout<<"姓名:"<<name<<", 分數:"<<score<<endl;
}
void setScore(int score)
{
this‐>score = score;
}
};
void ceatePlayer(vector<Person> &v)
{
int i=0;
string tmp="ABCDE";
for(i=0;i<5;i++)
{
string name="選手";
name += tmp[i];
v.push_back(Person(name, 0));
}
}
void printVectorPerson(vector<Person> &v)
{
vector<Person>::iterator it=v.begin();
for(;it!=v.end();it++)
{
(*it).showPerson();
}
}
void playGame(vector<Person> &v)
{
//設置隨機數種子
srand(time(NULL));
vector<Person>::iterator it=v.begin();
for(; it!=v.end();it++)
{
//*it代表的就是每位選手
//定義一個deque容器存放評委的分數
deque<int> d;
int i=0;
for(i=0;i<10;i++)
{
int score = 0;
score = rand()%41+60;//60~100
//將評委的分數放入 d容器中
d.push_back(score);
}
//對容器排序(默認從小‐‐‐>大排序)
sort(d.begin(), d.end());
//去掉一個最高分
d.pop_back();
//去掉一個最低分
d.pop_front();
//求總分數
int sum = accumulate(d.begin(), d.end(), 0);
//求平均成績
int avg = sum/d.size();
//將平均成績賦值給選手
(*it).setScore(avg);
}
}
int main(int argc, char *argv[])
{
vector<Person> v;
//創建5名選手
ceatePlayer(v);
//遍歷容器
printVectorPerson(v);
//參加比賽
playGame(v);
cout<<"------------"<<endl;
//遍歷容器
printVectorPerson(v);
return 0;
}
更多關于物聯網培訓的問題,歡迎咨詢千鋒教育在線名師,如果想要了解我們的師資、課程、項目實操的話可以點擊咨詢課程顧問,獲取試聽資格來試聽我們的課程,在線零距離接觸千鋒教育大咖名師,讓你輕松從入門到精通。