目录
注:原创不易,转载请务必注明原作者和出处,感谢支持!
注:内容来自某培训课程,不一定完全正确!
一 deque容器
1.1 deque容器基本概念
如上图所示,双端队列deque是一个双口容器,它可以同时在首尾两边进行插入和删除。
push_front(); // 头部插入 pop_front(); // 头部删除 push_back(); // 尾部插入 pop_back(); // 尾部删除 front(); // 返回队首元素 back(); // 返回队尾元素 dq.begin(); // 起始迭代器 dq.end(); // 终止迭代器
deque是“double-ended queue”的缩写,和vector一样,deque也支持随机存取。vector是单向开口的连续性空间,deque则是一种双向开口的连续性空间,所谓双向开口,意思是可以在头尾两段分别做元素的插入和删除操作,vector当然也可以在头尾两段进行插入和删除操作,但是头部插入和删除操作效率奇差,无法接受。
deque和vector最大的差异在于:
(1)deque允许常数时间内对头端进行元素插入和删除操作。
(2)deque没有容量的概念,因为它是动态的以分段的连续空间组合而成,随时可以增加一段新的空间并链接起来,换句话说,像vector那样“因为旧空间不足而重新分配一块更大的空间,然后再复制元素,释放空间”这样的操作不会发生在deque身上,也因此deque没有必要提供所谓的空间保留功能。
deque的特性总结如下:
(1)双端插入和删除元素效率较高
(2)指定位置插入也会导致数据元素移动,降低效率
(3)可随机存取,效率高
如上图所示是deque的内部实现原理示意图。对deque中的元素进行排序一般是选择将deque中的元素拷贝到vector中,在vector中完成排序之后再将排序后的元素拷贝回deque当中。
1.2 deque构造函数
// 默认构造形式 deque<T> dq; // 构造函数将[beg, end)区间中的元素拷贝给本身 deque(beg, end) // 构造函数将n个elem拷贝给本身 deque(n, elem); // 拷贝构造函数 deque(const deque &deq);
1.3 deque赋值操作
// 将[beg, end)区间中的数据拷贝赋值给本身 assign(beg, end); // 将n个elem拷贝赋值给本身 assign(n, elem); // 重载等号操作符 deque &operator=(const deque &dep); // 将deq与本身的元素互换 swap(dep);
1.4 deque大小操作
// 返回容器中元素的个数 deque.size(); // 判断容器是否为空 deque.empty(); // 重新制定容器长度为num,若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除 deque.resize(num); // 制定填充的默认值 deque.resize(num);
1.5 deque双端插入和删除操作
// 在容器尾部和首部插入元素 push_back(elem); push_front(elem); // 在容器尾部和首部删除元素 pop_back(); pop_front();
1.6 deque数据存取
// 返回索引idx所指的数据,如果idx越界,则抛出out_of_range异常 at(idx); // 返回索引idx所指的数据,如果idx越界,不抛出异常,程序 operator[]; // 返回首部元素 front(); // 返回末尾元素 back();
1.7 deque插入和删除
// 往位置position处插入元素val insert(const_iterator position, const valtype &val); // 清空容器中的元素 clear(); // 删除[beg, end)区间的数据,返回下一个数据的位置 erase(beg, end); // 删除pos位置的数据,返回下一个数据的位置 erase(pos);
1.8 deque应用案例
// 选手类型 class Player { public: Player() {} Player(string name, int score) : mName(name), mScore(score) {} public: string mName; int mScore; }; // 创建选手 void CreatePlayer(vector<Player> &v) { string nameList = "ABCDE"; for (int i = 0; i < 5; ++i) { Player p; p.mName = "选手"; p.mName += nameList[i]; p.mScore = 0; v.push_back(p); } } // 打分 void SetScore(vector<Player> &v) { for (vector<Player>::iterator it = v.begin(); it != v.end(); ++it) { // 10个评委打分 deque<int> dScore; for (int i = 0; i < 10; ++i) { int score = rand() % 41 + 60; dScore.push_back(score); } // 对分数排序 sort(dScore.begin(), dScore.end()); // 去除最高和最低分 dScore.pop_back(); dScore.pop_front(); // 求平均分 int totalScore = 0; for (deque<int>::iterator dit = dScore.begin(); dit != dScore.end(); ++dit) totalScore += (*dit); int avgScore = totalScore / dScore.size(); // 保存平均分 it->mScore = avgScore; } } // 排序规则 bool cmp(Player &p1, Player &p2) { return (p1.mScore > p2.mScore); } // 得分排名 void PrintRank(vector<Player> &v) { // 从大到小排序 sort(v.begin(), v.end(), cmp); for (vector<Player>::iterator it = v.begin(); it != v.end(); ++it) { cout << "name : " << it->mName << " score : " << it->mScore << endl; } } int main() { vector<Player> v; CreatePlayer(v); SetScore(v); PrintRank(v); getchar(); return 0; }