7.26C++:顺序容器、顺序容器的接口(详见P295)、反向迭代器、顺序容器操作实例、顺序容器的特征(vector、deque、list、forward_list、array)、顺序容器的比较和选择

deque(n):双端队列
emplace(v):安放
assign(v):分配、布置

1 顺序容器

一个容器是一些特定类型对象的集合。
容器是标准库中提供的数据结构(本质是数组扩展的vector、deque、array、string 和 指针扩展的list、forward_list)
顺序容器提供控制元素存储和访问顺序的能力,这种顺序与元素加入容器时的位置相对应。
在这里插入图片描述
2 顺序容器的接口(详见P295)

在这里插入图片描述
在这里插入图片描述
①构造函数:

C c;
C c1(c2); //构造c2的拷贝-c1
C c(b, e); //迭代器b和e范围内的元素拷贝到c
C c(a, b, c);//列表初始化c

②赋值函数:

c.assign(b, e);
c1 = c2;
c1 = {a, b, c...};//不适用于列表元素
a.swap(b);//交换a和b的元素
swap(a, b);

③获取迭代器:
返回指向c的首元素和尾元素之后位置的迭代器,因为对于容器迭代器区间是[begin,end)左闭右开的。

c.begin(), c.end() 

返回const_iterator

c.cbegin(), c.cend() 

3 反向迭代器:

反向迭代器详解
①反向迭代器的模板类定义在 < iterator> 头文件,并位于 std 命名空间中。

reverse_iterator //按逆序寻址元素的迭代器
const_reverse_iterator //不能修改元素的逆序迭代器
c.rbegin() //返回一个逆序迭代器,指向容器c的最后一个元素
c.crend() // 返回一个逆序迭代器,它指向容器c的第一个元素前面的位置
c.crbegin(),c.crend() //返回const_reverse_iterator

在这里插入图片描述
②反向迭代器自带base()函数,其基准迭代器为正序,且向右偏移1个元素
s.rbegin().base() == s.end()
s.rend().base() == s.begin()

③除了常规的正/反向迭代器begin()、end()、rbegin()、rend()、crbegin()、crend()外,可以通过find函数找到元素,并定义正/反向迭代器指向它

 string::reverse_iterator rcomma = find(line.rbegin(), line.rend(), ',');

④反向迭代器++,迭代器逆序前进1
⑤利用反向迭代器逆序排列

// sorts vec in "normal" order
sort(vec.begin(), vec.end());
// sorts in reverse: puts smallest element at the end of vec
sort(vec.rbegin(), vec.rend());

4 顺序容器操作实例

#include <iostream>
#include <list>
#include <deque>
using namespace std;

template <class T>
void printContainer(const char* msg, const T& s) {
    cout << msg << ": ";
    copy(s.begin(), s.end(), ostream_iterator<int>(cout, " ")); //输出流需要指定类型<int/double>
    //copy(迭代器左区间, 迭代器右区间, 容器中迭代器区间的全部元素复制到“标准输出流”中)
    cout << endl;
}
int main() {
    deque<int> s;
    for (int i = 0; i < 10; i++) {
        int x;
        cin >> x;
        s.push_front(x);
    }
    printContainer("deque at first: ", s); //由于把元素加到s队列的头部,s中元素是逆序的
    list<int> l(s.rbegin(), s.rend());//rbegin()->rend()是把原队列尾作为头,原队列头作为尾,逆序取元素
    printContainer("list at first: ", l);

    list<int>::iterator iter = l.begin();//注意这种定义方式,定义列表的迭代器iter
    while (iter != l.end()) { //将列表l的相邻两个元素交换
        int v = *iter;
        iter = l.erase(iter);//erase擦除iter迭代器对应的元素,返回下一个元素的地址
        l.insert(++iter, v);//++iter使迭代器再后移,此时指向初始位置的后面的后面的元素
        //insert是在迭代器指向的元素前面插入一个元素,此时迭代器还是指向第三个元素
    }
    printContainer("list at last: ", l);
    s.assign(l.begin(), l.end()); //通过assgin函数将列表l迭代器之间的元素复制给队列s
    //在不能使用赋值符“ = ”的情况下,可以将一个容器中的部分元素通过迭代器传递赋值到另一个容器中,
    //但是在assign的使用过程中,有一点需要特别注意,就是调用assign()函数的容器必须有足够的空间来容纳复制过来的元素
    printContainer("deque at last: ", s);
    return 0;
}

TIPS:
不用常规方法交换相邻元素是因为迭代器只是泛型的指针,未重载时不能像普通指针一样使用+、=等运算符。
通常使用迭代器特殊函数进行运算。

以下不可行:
while (iter != l.end()) {
        int v = *iter;
        *iter = *(iter + 1);
        *(iter + 1) = v;
        iter += 2;
    }

5 顺序容器的特征(vector、deque、list、forward_list、array)

向量与双端队列
在这里插入图片描述
在这里插入图片描述
随机访问速度:vector > deque > > list/forward_list
vector在尾部插入/删除元素快,deque在头部和尾部插入/删除元素快.
vector、deque在中间插入/删除元素慢,list/forward_list在任何位置插入/删除元素快

#include <iostream>
#include <vector>
#include <deque>
#include <algorithm>
using namespace std;
int main() {
	istream_iterator<int> i1(cin), i2;
	vector<int> s1(i1, i2); //通过迭代器构造
	sort(s1.begin(), s1.end());//正向排序,在algorithm头文件中
	deque<int> s2;
	for (vector<int>::iterator iter = s1.begin(); iter != s1.end(); ++iter) {
		//注意指明是哪个容器的迭代器
		if (*iter % 2 == 0) {
			s2.push_back(*iter);
		}
		else
			s2.push_front(*iter);
	}
	copy(s2.begin(), s2.end(), ostream_iterator<int>(cout, "  ")); 
	//注意输入、输出流迭代器都要指定数据类型
	//copy函数把容器元素放到输出流中
	cout << endl;
	return 0;
}

链表
在这里插入图片描述

#include <iostream>
#include <string>
#include <list>
#include <iterator>
using namespace std;
int main()
{
    string names1[] = { "Alice", "Helen", "Lucy", "Susan" };
    string names2[] = { "Bob", "David", "Levin", "Mike" };
    list<string> s1(names1, names1 + 4);
    list<string>s2(names2, names2 + 4);
    s2.splice(s2.end(), s1, s1.begin());//如果只写begin(),只拼接链表首元素
    list<string>::iterator iter1 = s1.begin();//通过创建链表迭代器来控制
    advance(iter1, 2);  //迭代器1前进两个部分
    list<string>::iterator iter2 = s2.begin();
    ++iter2; //迭代器++或者前进均可
    list<string>::iterator iter3 = iter2;
    advance(iter3, 2);
    s1.splice(iter1, s2, iter2, iter3);

    copy(s1.begin(), s1.end(), ostream_iterator<string>(cout, "  ")); //copy到输出流
    cout << endl;
    copy(s2.begin(), s2.end(), ostream_iterator<string>(cout, "  "));
    cout << endl;
    return 0;
}

单向链表
在这里插入图片描述
数组(array)
array是更好用、更方便的数组。
大小固定
在这里插入图片描述
顺序容器的比较和选择

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值