《C++程序设计语言》学习笔记1-容器

容器

顺序容器数据结构
vector<T>可变大小向量
list<T>双向链表
forward_list<T>单向链表
deque<T>双端队列

forward_list 是一种专为空链表和极短链表优化过的数据结构,一个空forward_list只占用一个内存字。不提供insert()、erase()、emplace(),而提供 *_after 系列操作;不提供back()、push_back()、pop_back()、emplace_back();不提供reverse_iterator、const_reverse_iterator、rbegin()、crbegin()、crend()、size()

有序关联容器数据结构
map<K,V>关联数组
multimap<K,V>允许重复关键字的map
set<T>集合
multiset<T>允许重复值的集合

multi*系列关联容器或集合不提供 [] 和 at()

无序关联容器数据结构
unordered_map<K,V>采用哈希搜索的map
unordered_multimap<K,V>采用哈希搜索的multimap
unordered_set<T>采用哈希搜索的set
unordered_multiset<T>采用哈希搜搜的multiset

unordered_* 系列关联容器不提供 <、<=、>、>=

容器适配器数据结构
priority_queue<T,C,Cmp>T 的优先队列;Cmp是优先级函数类型,默认 std::less<T>
queue<T,C>T 的队列;支持 push() 和 pop() 操作;容器类型C默认std::deque<T>
stack<T,C>T的栈;支持 push() 和 pop() 操作;容器类型C默认std::deque<T>

T:value_type

一、vector

1.一个vector就是一个给定类型元素的序列,元素在内存中是连续存储的,进行元素的删除插入操作时其他元素可能会移动
在这里插入图片描述
2.用一组值来初始化vector(值的类型必须与vector元素类型符合)

//Entry代表“电话簿”结构体,包含string型名字,int型号码
vector<Entry> phone_book = {
    {"David Hume",123456},
    {"Karl Poper",234567},
    {"Bertrand Arthur William Russell",345678}
};

可以通过下标运算符访问元素,如phone_book[0]
可以返回元素的数目,如phone_book.size()
遍历vector元素,for(const auto& x : phone_book)
定义vector时可设置初始大小:

vector<int> v1 = {1, 2, 3,4};   //size为4
vector<string> v2;              //size为0
vector<Shape> v3(23);           //显示给出size为23;元素初值是nulptr
vector<double> v4(32, 9.9);     //显示size为32,元素初值是9.9(32个元素全部初始为9.9)

vector的初始大小随着程序的执行可以被改变
在赋值和初始化时,vector可以被拷贝,如vector<Entry> book2 = phone_book;
拷贝和移动vector是通过构造函数和赋值运算符实现的,vector的赋值过程包括拷贝其中的元素
4.方法1:vector.push_back(),它向vector末尾追加一个新元素
5.元素
vector<T>中,元素T可为:内置数据类型(char、int、double)、用户自定义类型(string、Entry、list<int>、Matrix<double,2>)、指针类型
6.范围检查
标准库vector不进行范围检查(可能越界),可以自定义范围检查


二、list

1.list是一个双向链表
在这里插入图片描述
如果希望在一个序列中添加和删除元素的同时无须移动其他元素,则应使用list,电话簿插入删除频繁可使用list

//Entry代表“电话簿”结构体,包含string型名字name,int型号码number
list<Entry> phone_book = {
    {"David Hume",123456},
    {"Karl Poper",234567},
    {"Bertrand Arthur William Russell",345678}
};

2.一般不用下标操作来访问链表元素
3.遍历链表list,for(const auto& x : phone_book):

int get_number(const string& s){
    for(const auto& x : phone_book)
        if(x.name == s)
            return x.number;
    return 0;
}

每个标准库容器都提供begin()和end()函数,显示地使用迭代器遍历list(p为指针)

int get_number(const string& s){
    for(auto p=phone_book.begin();p!=phone_book.end();++p)
        if(p->name == s)
            return p->number;
    return 0;
}

4.方法1,添加元素:

phone_book.insert(p,ee);    //将ee添加到p指向的元素之前

5.方法2,删除元素:

phone_book.erase(q);    //删除q指向的元素

6.当只需要一个元素序列,数据量较小时,应该使用vector(vector无论遍历如find()和count()、排序sort()、搜索binary_search()都优于list)


三、map

1.map是一个搜索树(红黑树),也称为关联数组或字典,通常用平衡二叉树实现

//map是值对的容器,(key,value)
map<string,int> phone_book {
    {"David Hume",123456},
    {"Karl Poper",234567},
    {"Bertrand Arthur William Russell",345678}
};

2.map支持下标操作(本质上是一次搜索),下标值应为map的第一个类型key,得到与关键字关联的值value,若key值不存在则向map插入一个新元素,复杂度O(log(n))

int get_number(const string& s){
    return phone_book[s];
}


四、unordered_map 无序容器

1.初始化

unordered_map<string,int> phone_book {
    {"David Hume",123456},
    {"Karl Poper",234567},
    {"Bertrand Arthur William Russell",345678}
};

2.下标操作

int get_number(const string& s){
    return phone_book[s];
}

五、set 集合:每个元素只出现一次,且自动由小到大排列

set<string> dict;

五、容器的大小和容量

大小是指容器中的元素数目;容器是指在重新分配更多内存之前容器能够保存的元素数目

方法含义
x = c.size()x 是 c 的元素数目
c.empty()c为空吗
x = c.max_size()x 是 c 的最大可能元素数目
x = c.capacity()x 是为 c 分配的空间大小;只适用于 vector 和 string
c.reserve(n)为 c 预留 n 个元素的空间;只适用于 vector 和 string
c.resize(n)将 c 的大小改变为 n;将增加的元素初始化为默认元素值;只适用于顺序容器和string
c.resize(n,v)将 c 的大小改变为 n;将增加的元素初始化为 v;只适用于顺序容器和string
c.shrink_to_fit()令 c.capacity() 等于 c.size();只适用于 vector、deque、string
c.clear()删除 c 的所有元素

在改变大小或容量时,元素可能会被移动到新的存储位置。这意味着指向元素的迭代器、指针、引用,可能会失效(即,指向旧元素的位置)

六、栈操作

标准 vector、deque、list(不包括 forward_list 和关联容器)提供了高效的元素序列尾部操作:

栈操作含义
c.push_back(x)将 x 添加到 c 的尾元素之后(使用拷贝或移动)
c.pop_back()删除 c 的尾元素
c.emplace_back(args)用 args 构造一个对象,将它添加到 c 的尾元素之后
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值