笔记:C++学习之旅---顺序容器

STL = Standard Template Library   标准库模版
容器可以使用范围for输出或者迭代器进行输出
一个容器就是一些特定类型对象的集合。顺序容器为程序员提供了控制元素存储和访问顺序的能力。
list和forward和vector 将两个容器的设计目的是令容器任何位置的添加和删除操作都很快速。作为代价这两个容器不支持元素的随机访问:为了访问一个元素,我们只能遍历整个容器,而且,与vector、deque和array相比,这两个容器的额外内存开销都很大。(array的对象大小是固定的)。




 
构成迭代器范围的迭代器有何限制?

两个迭代器begin和end必须指向同一个容器中的元素,或者是容器最后一个元素之后的位置;而且,对begin反复进行递增操作,可以保证达到end,即end不在begin之前。

练习:
/*练习:9.4 编写函数,接受一对指向vector<int> 的迭代器和一个int值。
 *在俩个迭代器指定的范围中查找给定的值,返回一个布尔值来制定指出是否找到
 *
 *练习:9.5 重写上一题的函数,返回一个迭代器指向找到的元素。
 *注意,程序必须处理未找到给定值的情况
 */
#include
<iostream>
#include
<vector>
using
namespace
std;

//返回bool来指出是否找到
/*
bool find(vector<int>::iterator begin,vector<int>::iterator end,int value)
{
            for (auto iter = begin; iter != end; ++iter)
            {
                        if (*iter == value)
                                    return true;
                        //else
            }
            return false;
}*/
//返回一个迭代器指向找到的元素
const
vector
<
int
>::
iterator
find(
vector
<
int
>::
iterator
begin
,
vector
<
int
>::
iterator
end
,
int
value
)
//返回一个迭代器就相当于返回一个指针
{
            
for
(
auto
iter =
begin
; iter !=
end
;++iter)
            {
                        
if
(*iter ==
value
)
                                    
return
iter;
                        
//else
            }
            
return
end
;
}
int
main()
{
            
vector
<
int
> vec;
            
int
i;
            cout <<
"请输入整数到容器中:\n"
;
            
while
(cin >> i)
            {
                        
if
(i == -1)
                                    
break
;
                        vec.push_back(i);
//往容器中添加元素
            }
            
int
value;
            cout <<
"请输入要查找的元素数值\n"
;
            cin >> value;
            
if
(vec.empty())
            {
                        cout <<
"容器为空\n"
<< endl;
                        
return
-1;
            }
            
else
            {
                        cout<<find(vec.begin(), vec.end(),value)-vec.begin()<<endl;
//查找指定元素
            }
            
return
0;
}

练习9.9:begin和cbegin两个函数有什么不同?

cbegin是C++新标准引入来的,用来与auto结合使用。它返回指向容器第一个元素的const迭代器,可以用来只读地访问容器,但不能对容器元素进行修改。因此,当不需要写访问时,应该使用cbegin。

begin则是被重载过的,有两个版本:其中一个是const成员函数,也返回const迭代器;另一个则返回普通迭代器,可以对容器元素进行修改。

下面4个对象分别是什么类型?

[cpp] 
view plain
 copy
 

  1. vector<int> v1;
  2. const vector<int> v2;
  3. auto it1 = v1.begin(), it2 = v2.begin();
  4. auto it3 = v1.begin(), it4 = v2.cbegin();</span>

v1是int的vector类型,可以修改v1的内容,包括添加、删除元素以及修改元素等操作。

v2是int的常量vector类型,其内容不能修改,添加、删除元素以及修改元素值等均不允许。

it1是普通迭代器,可对容器元素进行读写访问,it2是const迭代器,不能对容器元素进行写访问。it3和it4都是const迭代器


标准库array具有固定的大小

与内置数组一样,标准库array的大小也是类型的一部分。当定义一个array时,除了指定元素类型,还要指定容器的大小:
array<int,42>      //类型为:保存42个int的数组
array<string,10>    //类型为:保存10个string的数组

为了使用array类型,我们必须同时指定元素类型和大小:
array<int,10> ::size_type i; //数组类型包括元素类型和大小;
array<int>::size_type j;      //错误:array<int>不是一个类型




练习:9.13  
如何从一个list<int>  初始化一个vector<double>?从一个vector<int> 又该如何创建?编写代码验证你的答案。
#include
<iostream>
#include
<vector>
#include
<list>
using
namespace
std;
int
main()
{
            
list
<
int
> ilst = {1,2,3,4,5,6,7,8};
            
vector
<
int
> ivc = {2,7,4,3,5,1,10,6};

            
//! from list<int> to vector<double>
            
vector
<
double
> dvc(ilst.begin(), ilst.end());
            
for
(
auto
i : ilst) cout << i;
            cout << endl;
            
for
(
auto
t : dvc) cout << t;
            cout << endl;

            
//! from vector<int> to vector<double>
            
vector
<
double
> dvc2(ivc.begin(), ivc.end());
            
for
(
auto
i : ivc) cout << i;
            cout << endl;
            
for
(
auto
t : dvc2) cout << t;

            
return
0;
}


顺序容器操作
除array外,所有标准库容器都提供灵活的内存管理。在运行时,可以动态添加或删除元素来改变大小。


练习:9.18
编写程序从标准输入读取string序列,存入一个deque中,编写一个循环,用迭代器打印deque中的元素。
#include
<iostream>
#include
<vector>
#include
<deque>
#include
<string>
using
namespace
std;

int
main()
{
            
deque
<
string
> input;
            
string
str;
            
while
(cin >> str)
            {
                        
if
(str ==
"#"
)
                                    
break
;
                        input.push_back(str);
            }
            
for
(
auto
iter = input.cbegin(); iter != input.cend(); ++iter)
            {
                        cout <<
"iter:"
<< *iter << endl;
            }
            
return
0;
}

访问元素

删除元素
与添加元素的多种方式类似,(非array)容器也有很多种删除元素的方式。



从容器内部删除元素


练习9.26:
使用下面代码定义的ia,将ia拷贝到一个vector和一个list中。使用单迭代器版本的erase从list中删除奇数元素,从vector中删除偶数元素。
int ia[] = {0,1,2,3,5,8,13,21,34,55,89};
#include
<iostream>
#include
<vector>
#include
<list>
using
namespace
std;

int
main()
{

            
int
ia[] = { 0, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 };
            
//init
            
vector
<
int
> vec(ia, end(ia));
            
list
<
int
> list(vec.begin(), vec.end());
            
//从list中删除奇元素
            
for
(
auto
lt = list.begin(); lt != list.end(); ++lt)
            {
                        
if
(*lt % 2)
                        {
                                    cout <<
"奇数:"
<<*lt << endl;
                        }
                        
else
                                    ++lt;
            }

            
//删除vector中的偶数
            
for
(
auto
vt = vec.begin(); vt != vec.end(); ++vt)
            {
                        
if
(*vt % 2 == 0)
                        {
                                    cout <<
"偶数:"
<<*vt << endl;
                        }
                        
else
                                    ++vt;
            }
            
return
0;
}

特殊的forword_list操作
当添加或删除一个元素时,删除或添加的元素之前的那个元素的后继会发生变化,为了添加或删除一个元素,我们需要访问其前驱,以便改变前驱的链接。但是forword_list是单向链表。在一个单向链表中,没有简单的方法来获取一个元素的前驱,出于这个原因,在一个forword_lisT中添加或删除元素的操作是通过改变给定元素之后的的元素来完成的,这样,我们总可以访问到被添加或删除操作所影响的元素。



练习:9.27
编写程序,查找并删除forwa
rd_list<int> 中的奇数元素。

#include
<iostream>
#include
<forward_list>
using
namespace
std;

int
main()
{
            
forward_list
<
int
> list = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
            
auto
prev = list.before_begin();
// 前驱,list中“首前元素”;
            
auto
curr = list.begin();
//开始位置,第一个元素;
            
while
(curr !=list.end())
            {
                        
if
(*curr % 2 == 1)
//元素为奇数
                        {
                                    curr = list.erase_after(prev);
//删除prev之后元素,即:curr指向的元素;
                        }
                        
else
                        {
                                    prev = curr;
//奇数时,将curr保存,curr自加;
                                    curr++;
                        }
                        
            }
            
for
(
auto
i : list)
                        cout <<
"i:"
<< i << endl;
            
return
0;
}


添加删除vector、string、或deque元素的循环程序必须考虑迭代器、引用和指针可能失效的问题。程序必须保证每个循环步骤中都更新迭代器、引用、或指针。如果循环中调用的是insert或erase,那么更新迭代器很容易。这些操作都返回迭代器,我们可以用来更新。


vector对象是如何增长的
为了避免每次添加新元素就执行一次内存分配和释放操作,当不得不获取新的内存空间时,vector和string的实现通常会分配比新的空间更大的内存空间。容器预留这些空间作为备用,可用来保存更多的新元素。这样,就不需要每次添加新元素都重新分配容器的内存空间了。

管理容量的成员函数


为什么list和array没有capacity?
list不能持续存储,array是固定数组大小,没有预先分配这么一说


额外的string操作


数值转换



练习9.50:
编写程序处理一个vector<string>,其元素都表示整型数值。计算vector中所有元素之和。修改程序,使之计算表示浮点值的string之和。
#include
<iostream>
#include
<string>
#include
<vector>
using
namespace
std;
int
All_Sum(
vector
<
string
> &
v
)
{
            
int
sum = 0;
            
for
(
auto
const
&s : v)
                        sum += stoi(s);
            
return
sum;
}
float
All_Float_Sum(
vector
<
string
> &
v
)
{
            
float
sum = 0.0;
            
for
(
auto
const
&s : v)
                        sum += stof(s);
            
return
sum;
}
int
main()
{
            
vector
<
string
> v = {
"1"
,
"2"
,
"3"
,
"4"
,
"5.5"
,
"6.1"
};
            cout<<
"All elements sum:"
<<All_Sum(v)<<endl;    //21
            cout<<
"ALL float elements string sum:"
<<All_Float_Sum(v)<<endl;    //21.6
            
return
0;
}

笔记:C++学习之旅---顺序容器的更多相关文章

  1. 【c++ Prime 学习笔记】第9章 顺序容器

    一个容器是特定类型对象的集合 顺序容器中元素的顺序与其加入容器的位置对应 关联容器中元素的顺序由其关联的关键字决定,关联容器分为有序关联容器和无序关联容器 所有容器类共享公有接口,不同容器按不同方式扩 ...

  2. C++学习基础四——顺序容器和关联容器

    —顺序容器:vector,list,queue1.顺序容器的常见用法: #include <vector> #include <list> #include <queue ...

  3. C++ Primer 读书笔记: 第9章 顺序容器

    第9章 顺序容器 引: 顺序容器: vector 支持快速随机访问 list 支持快速插入/删除 deque 双端队列 顺序容器适配器: stack 后进先出栈 queue 先进先出队列 priori ...

  4. 笔记-JavaWeb学习之旅19

    Redis:redis是一款高性能的NOSQL系列的非关系型数据库 NOSQL: Not Only SQL ,意即"不仅仅是SQL",是一项全新的数据库理念,泛指非关系型数据库 r ...

  5. 笔记-JavaWeb学习之旅15

    Filter:过滤器 概念:当访问服务器的资源是,过滤器可以将请求拦截下来,完成一些特殊的功能 快速入门: 步骤: 定义一个类,实现接口Filter 复写方法 配置拦截路径 package com.d ...

  6. 笔记-JavaWeb学习之旅14

    JSTL:JavaServer Pages Tag Library JSP标准标签库 if标签 <%@ page import="java.util.ArrayList" % ...

  7. 笔记-JavaWeb学习之旅11

    请求转发:一种在服务器内部的资源跳转方式 使用步骤 1.通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path) ...

  8. 笔记-JavaWeb学习之旅8

    Window对象-定时器方法 <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...

  9. 笔记-JavaWeb学习之旅7

    JavaScript基础 概念:一门客户端脚本语言,运行在客户端浏览器中,每一个浏览器都有JavaScript的解析引擎,是一个脚本语言,不需要编译,直接就可以被浏览器解析执行. JavaScript ...

  10. 笔记-JavaWeb学习之旅5

    CP30的演示 package cn.itcast.datasourcejdbc; import com.mchange.v2.c3p0.ComboPooledDataSource; import j ...

随机推荐

  1. What is Weight Lifting?

    Weight lifting is the process of lifting items of great mass in order to increase the muscle size an ...

  2. Glist 按钮属性

    grayed 变灰与否不影响点击等事件 touchable 为false,不会变灰,但会无法点击, enabled为false自动变灰,且无法点击

  3. [极客大挑战 2019]LoveSQL 1

    很明显这时一道SQL注入的题目 这题很简单的SQL注入题目,使用union(联合查询注入),但是缠了我很久 为什么呢?因为我们学校的waf,很多可以注入成功的语句,他都会连接被重置,或者被burpsu ...

  4. LeetcodePractice-数组

    目录 88. 合并两个有序数组 思路解析 字节&1. 两数之和 思路解析 腾讯&15. 三数之和 思路解析 18. 四数之和 思路解析 解释下,tmpSum为什么用int不行,需要用i ...

  5. 【CS231n assignment 2022】 vscode 环境配置

    文章目录 前言 一.安装 Python 二.安装 vscode 三. cs231n 作业下载 四.配置 vscode 五.虚拟环境包安装 六.数据集 前言 今年成功考上了本校的研究生,要开始进入研究生 ...

  6. python + BeautifulSoup + selenium 实现爬取中医智库的古籍分类的数据

    爬取内容为 该图片下的七个分类, 然后对应的每个种类的书本信息(摘要和目录) 效果为 代码如下 import requests from bs4 import BeautifulSoup import ...

  7. 分布式缓存的一致性 Hash 算法

    一.使用一致性 Hash 算法的原因 简单的路由算法可以使用余数 Hash:用服务器数据除缓存数据 KEY 的 Hash 值,余数为服务器列表下标编码.这种算法可以满足大多数的缓存路由需求.但是,当分 ...

  8. Cisco模拟器配置DNS服务器遇到的问题

    1.使用工具: Cisco-Packet-Tracer(7.0或8.0版本及以上) 2.问题: 原因:安装思科模拟器后进行中文汉化: 过程:配置DNS服务时无法进行域名操作: 解决: 更改为原来的语言 ...

  9. SHA-256 简介及 C# 和 js 实现【加密知多少系列】

    〇.简介 SHA-256 是 SHA-2 下细分出的一种算法.截止目前(2023-03)未出现"碰撞"案例,被视为是绝对安全的加密算法之一. SHA-2(安全散列算法 2:Secu ...

  10. 移动端测试辅助工具 - adb

    1. 概念: adb(android debug bridge)是android提供的基于CS架构的命令行调试工具,使PC与安卓设备之间实现通信 2. 基础原理: 交互图: 主要由三部分组成: adb ...