计算机程序设计c++ 14-2:标准模版库STL-1

标准模版库概述

  • 标准模版库(Standard Template Library,STL)是一个具有工业强度的,高效的C++程序库,它实现了诸多在计算机科学领域里常用的基本数据结构和基本算法
  • STL主要包含了容器、算法、迭代器
  • STL系由Alexander Stepanov和Meng Lee等人创造于惠普实验室
  • STL于1994年2月年正式成为ANSI/ISO C++的一部份

容器

  • 容器是容纳、包含相同类型元素的对象,主要用类模板实现
  • 序列型容器:容器中的元素按线性结构组织起来,可以逐个读写元素。主要代表有vector(向量)、deque(双端队列) 、list(双向链表)
  • 关联型容器:关联容器通过键(key)存储和读取元素。主要有map(映射)、set(集合)等
  • 容器适配器:是对前面提到的某些容器(如vector)进行再包装,使其变为另一种容器。典型的有栈(stack)、队列(queue)等

迭代器

  • 迭代器是用于确定元素位置的数据类型,可用来遍历容器中的元素
  • 通过迭代器可以读取、修改它指向的元素,它的用法和指针类似
  • 每一种容器都定义了一种迭代器

定义迭代器的样式如下:

  • 容器类名<元素类型>::iterator 变量名;

访问:

  • *it;

修改:

  • *it = 5;
vector<int>:: iterator it;
// 访问一个迭代器指向的元素:
//* 迭代器变量名
//例如: 
*it=5

算法

  • 由许多函数模版组成的集合,实现了大量通用算法,用于操控各种容器
  • STL中提供的算法涉及到:比较、交换、查找、遍历、复制、修改、移除、反转、排序、合并等。大约有70种标准算法
  • 算法通过迭代器来操纵容器中的元素
  • 算法可以处理容器,也可以处理C语言的数组

vector

vector主要特征:

  • vector 实际上就是对动态数组封装
  • 可以像数组一样可以使用下标访问元素,若vector长度为n,则其下标为 0~n-1
  • 根据下标访问元素效率高
  • vector对象的空间随着插入删除操作自动调整
  • 因为空间自动调整比较耗费时间,因此频繁插入删除的情况下,vector效率稍差
vector-创建对象
  • 创建一个空向量
vector<int> v1; // int 类型向量
vector<string> s1; // string 类型向量
  • 从已有向量复制创建向量
vector<int> v2(v1); // 拷贝v1内容到v2(拷贝构造函数)
  • 创建10个元素的向量
vector<string> s2(10);
  • 创建10个元素的向量,所有元素都是 1.5
vector<double> v3(10, 1.5);
  • 创建向量指针
vector<int> *pvec = new vector<int>(10, -5);
vector-尾部添加元素
  • 使用 push_back() 函数向 vector 尾部添加元素
#include<iostream>
#include<vector>

using namespace std;
int main()
{
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	return 0;
}

在这里插入图片描述

vector-任意位置插入元素
  • 使用 insert() 函数向 vector 添加元素
#include<iostream>
#include<vector>
using namespace std;

int main()
{
	vector <int> v1;
	v1.push_back(1);
	v1.push_back(2);
	
	v1.insert(v1.begin(), 0);  // 头部插入
	v1.insert(v1.end(), 4);    // 尾部插入
	v1.insert(v1.end()-1, 3);  // 倒数第二位置
	return 0;
}

在这里插入图片描述

v1.begin(), v1.end() 获取相应位置的迭代器, begin()是开头,end()是尾部元素的下一个,不包含该位置

vector-用下标访问元素

使用下标[]可以获取元素值,修改元素

#include<iostream>
#include<vector>

using namespace std;
int main()
{
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	
	v1.insert(v1.begin(), 0);  // 头部插入
	v1.insert(v1.end(), 4);    // 尾部插入
	v1.insert(v1.end()-1, 3);  // 倒数第二位置
	v1[4] = 10;	               // 修改index为4的元素,v1[5]=6是不可以的,超界错误
	for(int i=0; i<v1.size(); i++)  // v1.size()为5
	{
		cout << v1[i]<< " ";
	}
	return 0;
}

在这里插入图片描述

0 1 2 3 10

vector-删除尾部元素
  • 使用pop_back()删除最后一个元素
#include<iostream>
#include<vector>

using namespace std;
int main()
{
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	
	v1.insert(v1.begin(), 0);  // 头部插入
	v1.insert(v1.end(), 4);    // 尾部插入
	v1.insert(v1.end()-1, 3);  // 倒数第二位置
	v1[4] = 10;	               // 修改index为4的元素,v1[5]=6是不可以的,超界错误
	v1.pop_back();             // 删除10 
	return 0;
}

在这里插入图片描述

vector-删除任意元素
  • 使用erase()删除任意位置元素
  • 使用clear() 全删除
#include<iostream>
#include<vector>

using namespace std;
int main()
{
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	
	v1.insert(v1.begin(), 0);  // 头部插入
	v1.insert(v1.end(), 4);    // 尾部插入
	v1.insert(v1.end()-1, 3);  // 倒数第二位置
	v1[4] = 10;	               // 修改index为4的元素,v1[5]=6是不可以的,超界错误
	v1.pop_back();             // 删除10 
	v1.erase(v1.begin());      // 删除0
	v1.erase(v1.begin(), v1.end());  // 全删
	return 0;
}

也可以使用v1.clear()全删除
在这里插入图片描述

vector-向量大小相关函数
  • v.size() : 返回向量的大小
  • v.max_size() : 返回向量可容纳的最大个数
  • v.empty() : 返回向量是否为空
  • v.resize(n) : 调整向量大小,使其可以容纳n个元素,如果n<v.size(), 则删除多出来的元素; 否则,添加新元素
  • v.resize(n, t) : 调整向量的大小,使其可以容纳n个元素,所有新添加的元素初始化为t
  • v.capacity() : 获取向量的容量,再分配内存空间之前所能容纳的元素个数

在这里插入图片描述

vector上的迭代器

迭代器的基本操作:

向量上的迭代器定义、使用
vector<int>::iterator it; *it = 5;

  • vector上迭代器支持随机访问:
    • 提供读写操作
    • 并能在数据中随机移动(前后,跳跃式)
  • 用加、减操作移动迭代器:
    • it++; ++it; //指向下一元素
    • it--; --it; //指向前一元素
    • it + i: 返回指向 it 后面的第i个元素的迭代器
    • it – i : 返回指向 it 前面的第i个元素的迭代器
  • <, <=, >, >=,==,!=判断迭代器前后、相等关系
    it1 < it2 // 表示 it1 在 it2 之前
begin()和end()函数
  • 每种容器都定义了一对命名为beginend的函数,用于返回迭代器。如果容器中有元素,由begin返回的迭代器指向第一个元素
    it = v1.begin(); // 指向v1[0]
  • end 返回的迭代器指向vector的末端元素的下一个。通常称为超出末端迭代器,表明它指向了一个不存在的元素
    it = v1.end(); // 指向末端元素的下一个
  • 如果vector为空,begin返回的迭代器不end返回的迭代器相同
用迭代器取元素
  • 将1~9加入vector,再将偶数取出
#include<iostream>
#include<vector>
using namespace std;

int main()
{
	vector<int> v1;

	for(int i=1; i<10; i++)
		v1.push_back(i); // 添加1~9

	vector<int>::iterator it;
	for(it=v1.begin(); it<v1.end(); it++)
		if(*it%2==0)
			cout << *it << " ";

	return 0;
}

2 4 6 8

以迭代器为参数的插入删除函数
  • 在迭代器p所指向的元素前面插入值为 t 的元素
    v.insert(p, t);

  • 在迭代器p所指向的元素前面插入n个值为t的新元素
    v.insert(p, n, t);

  • 在迭代器p所指向的元素前面插入迭代器b和e标记的范围内的元素
    v.insert(p, b, e);

  • 删除迭代器p指向的容器中的元素
    v.erase(p);

  • 删除迭代器b和e所标记范围内的元素
    v.erase(b, e);

例子

vector<int> v2(3, 1);  // init
vector<int> v1(4, 0);

v1.insert(v1.begin(), 5); // 在头部插入5
v1.insert(v1.end(), 7);  // 在尾部插入7

// 在下标为4处插入9
vector<int>::iterator it = v1.begin() + 4;
v1.insert(it, 9 );

// 删除偶数元素
for(it=v1.begin(); it<v1.end(); ) 
{
	if(*it%2 == 0) 
		it=v1.erase(it);
	else 
		it++;
}

//将v1的一部分拷贝到v2
v2.insert(v2.begin(), v1.begin(), v1.begin()+2);

在这里插入图片描述
用迭代器循环删除遇到的问题

vecotr<int>::iterator it = vc.begin();

for(; it != vc.end(); it++)  // 该条件是错误的
{ 
	if( ***** )
		vc.erase(it); 
}

上述代码中的循环条件是错误的,原因erase()删除元素后,it失效,并不是指向下一个元素

解决方案:

for(it=v1.begin(); it<v1.end(); ) {
	if(*******) 
		it = v1.erase(it);   // 将删除的返回值赋给it
	else
		it++;
}

在C++11标准中,erase() 会返回一个iterator,这个iterator指向了“当前删除元素的后继元素”

在vector上应用算法

常用算法
  • 排序 sort( )
  • 查找 find( )
  • 替换 replace( )
  • 合并 merge( )
  • 反序 reverse( )
  • 统计 count( )
  • 其他等等算法

许多算法往往以迭代器作参数。比如排序和查找都需要两个迭代器参数(表示起始位置、终止位置)
有的算法返回一个迭代器。比如find算法,在容器中查找一个元素,并返回一个指向该元素的迭代器
算法主要在头文件<algorithm><numeric>中定义

算法示例: find()

find( first, last, val)

  • firstlast 这两个参数都是容器的迭代器,它们给出了容器中的查找区间起点和终点
  • 这个区间是个左闭右开的区间[first, last),即区间的起点是位于查找范围之中的,而终点不是val参数是要查找的元素的值
  • 函数返回值是一个迭代器。如果找到,则该迭代器指向被找到的元素。如果找不到,则该迭代器指向查找区间终点
#include <vector>
#include <algorithm>
#include<iostream>

using namespace std;

int main()
{
	vector <int> v(5, 3);  // 5个3
	vector <int>::iterator p;

	p = find(v.begin(), v.end(), 3);
	if(p!=v.end())
		cout << *p << endl;  // 找到了

	p = find(v.begin(), v.end(), 5);  // 没有找到时,p==v.end()
	if(p==v.end())
		cout<<"not found\n";
		
	return 0;
}

3
not found

算法示例:sort()

void sort( first, last )

  • firstlast 这两个参数都是容器的迭代器,它们给出了容器中的查找区间起点和终点
#include <vector>
#include <algorithm>
#include <iostream>
#include <string>

using namespace std;

int main() 
{
	vector<string> v;
	
	v.push_back("food");
	v.push_back("candy");
	v.push_back("apple");
	
	sort(v.begin(), v.end());  // 排序,从小到大
	
	vector<string>::iterator it;
	for(it=v.begin(); it!=v.end(); it++)
		cout<< *it <<" ";
	
	return 0;
}

apple, candy, food

算法示例:merge()

merge(f1, e1, f2, e2, p)

  • f1、e1、f2、e2、p都是迭代器
  • 要求两个序列都是有序序列
  • 有序序列v1中[f1, e1)有序序列v2中[f2, e2)合并成有序序列,存入p的前面
#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

int main()
{
	int A[] = {5, 10, 15, 20, 25};
	int B[] = {50, 40, 30, 20, 10};
	
	vector<int> v(10);
	vector<int>::iterator it;
	
	sort(A, A+5);
	sort(B, B+5);  // 先排序

	merge(A, A+5, B, B+5, v.begin());
	
	for(it=v.begin(); it!=v.end(); ++it)
		cout << *it << " ";
	
	return 0;
}

5 10 10 15 20 20 25 30 40 50

其他算法示例
  • replace( first, last, old, new ) // first, last为迭代器
    作用:将 [ first, last )范围内的所有值为old的替换为new

  • reverse(start, end) // start, end为迭代器
    作用:将序列中[start, end)范围反转排列顺序

  • count(start, end, searchValue) // start, end为迭代器
    作用:统计[start, end)范围内等于searchValue的元素个数

  • accumulate(first, last, init) // first, last为迭代器
    作用:将[ first, last )范围内的所有值相加,再加上init后返回

STL中算法众多,算法可能丌一定适合的所有容器,使用时多查询手册

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

uncle_ll

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值