两者有什么区别?我的意思是方法都一样。因此,对于用户而言,它们的工作原理相同。
那是对的吗??
Answers:
双端队列非常类似于矢量:类似于矢量,它是一个序列,它支持对元素的随机访问,在序列末尾进行恒定时间的元素插入和删除,以及在中间对元素的线性时间插入和删除。
双端队列与向量不同的主要方式是,双端队列还支持在序列开始时恒定时间插入和删除元素。此外,双端队列没有类似于vector的Capacity()和reserve()的任何成员函数,并且不提供与那些成员函数相关的迭代器有效性的任何保证。
这是list
来自同一站点的摘要:
列表是一个双向链接列表。也就是说,它是一个序列,它支持向前和向后遍历,并且在元素的开始或结尾或中间支持(分摊)常量时间插入和删除元素。列表具有重要的属性,即插入和拼接不会使迭代器失效,甚至删除也只会使指向被删除元素的迭代器无效。迭代器的顺序可以更改(也就是说,list :: iterator在列表操作之后可能具有与之前不同的前任或后继者),但是除非该无效,否则迭代器本身不会失效或指向不同的元素。或突变是明确的。
总之,容器可能具有共享的例程,但是这些例程的时间保证因容器而异。考虑到使用的这些容器的一个任务时,这是非常重要的:考虑到如何容器将使用最频繁的(例如,更比的插入/删除搜索)走一段很长的路在指导你正确的容器。
让我列出差异:
复杂
Insert/erase at the beginning in middle at the end
Deque: Amortized constant Linear Amortized constant
List: Constant Constant Constant
constant
和之间有什么区别amortized constant
?
std::list
基本上是一个双向链表。
std::deque
另一方面,实现起来更像std::vector
。它具有按索引的恒定访问时间,以及在开头和结尾处的插入和删除,这提供了与列表明显不同的性能特征。
另一个重要的保证是每个不同容器将其数据存储在内存中的方式:
请注意,双端队列被设计为试图平衡vector和list的优点而没有各自的缺点。在内存受限的平台(例如微控制器)中,它是一个特别有趣的容器。
内存存储策略经常被忽略,但是,它经常是为特定应用选择最合适的容器的最重要原因之一。
这是列表,无序映射的概念验证代码使用,可提供O(1)查找和O(1)精确的LRU维护。需要(未擦除的)迭代器在擦除操作中生存下来。计划在O(1)任意大的软件托管的缓存中使用GPU内存上的CPU指针。向Linux O(1)调度程序点头(每个处理器的LRU <->运行队列)。unordered_map通过哈希表具有恒定的访问时间。
#include <iostream>
#include <list>
#include <unordered_map>
using namespace std;
struct MapEntry {
list<uint64_t>::iterator LRU_entry;
uint64_t CpuPtr;
};
typedef unordered_map<uint64_t,MapEntry> Table;
typedef list<uint64_t> FIFO;
FIFO LRU; // LRU list at a given priority
Table DeviceBuffer; // Table of device buffers
void Print(void){
for (FIFO::iterator l = LRU.begin(); l != LRU.end(); l++) {
std::cout<< "LRU entry "<< *l << " : " ;
std::cout<< "Buffer entry "<< DeviceBuffer[*l].CpuPtr <<endl;
}
}
int main()
{
LRU.push_back(0);
LRU.push_back(1);
LRU.push_back(2);
LRU.push_back(3);
LRU.push_back(4);
for (FIFO::iterator i = LRU.begin(); i != LRU.end(); i++) {
MapEntry ME = { i, *i};
DeviceBuffer[*i] = ME;
}
std::cout<< "************ Initial set of CpuPtrs" <<endl;
Print();
{
// Suppose evict an entry - find it via "key - memory address uin64_t" and remove from
// cache "tag" table AND LRU list with O(1) operations
uint64_t key=2;
LRU.erase(DeviceBuffer[2].LRU_entry);
DeviceBuffer.erase(2);
}
std::cout<< "************ Remove item 2 " <<endl;
Print();
{
// Insert a new allocation in both tag table, and LRU ordering wiith O(1) operations
uint64_t key=9;
LRU.push_front(key);
MapEntry ME = { LRU.begin(), key };
DeviceBuffer[key]=ME;
}
std::cout<< "************ Add item 9 " <<endl;
Print();
std::cout << "Victim "<<LRU.back()<<endl;
}