STL x

作为C++标准不可缺少的一部分,STL应该是渗透在C++程序的角角落落里的。

STL不是实验室里的宠儿,也不是程序员桌上的摆设,她的激动人心并非昙花一现。

所以今天要整理的东西就是STL!(orz 杨乐大神)

一.引入

STL(Standard Template Library),即标准模板库。该库包含了诸多在计算机科学领域里所常用的基本数据结构和基本算法。

从逻辑层次来看,在STL中体现了泛型化程序设计的思想(generic programming),引入了诸多新的名词,比如像需求(requirements),概念(concept),模型(model),容器(container),算法(algorithmn),迭代子(iterator)等。

与OOP(object-oriented programming)中的多态(polymorphism)一样,泛型也是一种软件的复用技术。

从实现层次看,整个STL是以一种类型参数化(type parameterized)的方式实现的,这种方式基于一个在早先C++标准中没有出现的语言特性--模板(template)。

如果查阅任何一个版本的STL源代码,你就会发现,模板作为构成整个STL的基石是一件千真万确的事情。

除此之外,还有许多C++的新特性为STL的实现提供了方便。

STL 相当于一个工具箱,里面有 C++ 内置的函数与容器,可以直接拿来使用(这样就不用连工具都要自己造了)!

但这些我们暂且不深入谈,仅仅来了解她的大体,会使用她便可(反正深了我也不会hhhh)

二.分析?

运用头文件大部分都是

#include<algorithm>
用的时候只需要在头文件中包含进来即可

algorithm(算法)  完成特定功能

container(容器)  用于存储数据

iterator(迭代器)  访问容器中的内容[类似于指针]

三.我认为比较常用的STL:

1.Algorithm(算法)部分

1)

* min(x, y):取两者中的较小值
* max(x, y):取两者中的最大值

max+min函数(这个好像是在cmath也是有的吧,记不太清楚,有兴趣的可以手动Ctrl)

{  

  它们调用起来十分简单,只要满足 x,y 是相同类型,并且可以比较大小即可

  必须是同种类型之间进行的比较!

  (int与double不能够进行比较)

Eg:

int a = 5, b = 4, c = min(a, b); // c = 4
double x = 1.5, y = 3.5, z = max(x, y); // z = 3.5

}

2)

* swap(x, y):交换两者的值

swap函数

{ 

  调用时只要满足 x,y 是相同类型即可

Eg:

int a = 5, b = 4;
swap(a, b); // a = 4, b = 5
double x = -1.0, y = 2.5;
swap(x, y); // x = 2.5, y = -1.0
// !swap(a, x) 无法调用:类型不相同

}

3)

* sort(first, last):对于在 [first, last) 中的元素进行排序

* sort(first, last, comp):对于在 [first, last) 中的元素进行排序,其中 comp 为比较器

sort函数

{

  默认是从小到大进行排序,可以修改为从大到小进行排序,如下:

int a[10] = {5, 2, 1, 3, 4};

sort(a, a+5);// a = [1, 2, 3, 4, 5, ...] 普通排序

int cmp(int x, int y)
{
    return x > y;
} // 比较器

sort(a, a+5, cmp);// a = [5, 4, 3, 2, 1, ...] 从大到小排序

  几点需要注意的地方:

排序的区间为[first, last),左闭右开;

如果需要排序A[1..5]中的数,则需要调用sort(A+1, A+6);

* 其实还可以自己定义比较器,作为排序的准则:例如,我们需要按照个位数来比较大小,则可以定义比较器为

int cmp(int x, int y)
{
    return x % 10 < y % 10;
}

* 对于自己定义的结构体,可以定义自己的比较器来实现排序功能。
// 以 a 为第一关键字,b 为第二关键字进行排序

int cmp(Mystruct x, Mystruct y)
{
    return x.a == y.a ? x.b < y.b : x.a < y.a;//三目运算符
}

}

4)

* lower_bound(first, last, element):

给定 [first, last)中的已经从小到大好排序的元素,找出最前的一个不比    element   要小的元素的位置

lower_bound函数

{

  注意:element返回的是指针,并不是下标!!

  它的作用就是:

      找出最前的一个不比element要小的元素的位置

      ps:若均大于element,则返回最开始的位置

         (小)           (后)

Eg:


void lower_bound_stl()
{
int a[10] = {5, 2, 1, 3, 4, 3, 2, 4};
sort(a, a+8); // a = [1, 2, 2, 3, 3, 4, 4, 5] 已从小到大排好序
int p2 = lower_bound(a, a+8, 2) - a; // p2 = 1
// a中最前的不比 2 小的元素是: a[1] = 2
int p4 = lower_bound(a, a+8, 4) - a; // p4 = 5
// a中最前的不比 4 小的元素是: a[5] = 4
int p0 = lower_bound(a, a+8, 0) - a; // p0 = 0
// a中最前的不比 0 小的元素是: a[0] = 1
int p6 = lower_bound(a, a+8, 6) - a; // p6 = 8
// a中没有不比 6 小的元素,所以返回最后的一个位置 a[8]
// 注意:a[8] 中并没有值,是数组的最末端
    cout << p2 << endl;
    cout << p3 << endl;
    cout << p0 << endl;
    cout << p6 << endl;
}

}

5)

疑似扯远的感觉?

*unique()函数是一个去重函数

unique()函数

{

  STL中unique的函数 unique的功能是去除相邻的重复元素(只保留一个),还有一个容易忽视的特性是它并不真正把重复的元素删除。

  他是c++中的函数,所以头文件要加#include<iostream>,具体用法如下:

int num[100];

   unique(num,mun+n);

/*
返回的是num去重后的尾地址,之所以说比不真正把重复的元素删除,其实是,该函数把重复的元素一到后面去了,然后依然保存到了原数组中,然后返回去重后最后一个元素的地址,因为unique去除的是相邻的重复元素,所以一般用之前都会要排一下序
*/

}

6)

strchr()函数为字符串判断函数

strchr

{

char c[100];

strchr(c,‘.‘) //如果c字符串中含有 ‘.‘ 则返回 ‘.‘ 的位置指针,否则返回NULL;

此函数包含在头文件#include<cstring>中。

如果有两个或两个以上字符就返回第一个的地址。

}

/*--------------------啦啦啦~我是萌萌的分割线酱~---------------------*/

2.容器 (Container)部分

STL 中的容器被分配在不同的库中,用的时候只需要在头文件中包含对应的库即可

#include <vector>         // 向量:用于存储连续的元素,类似数组
#include <set>            // 集合
#include <queue>          // 队列
#include <stack>          // 栈
#include <map>            // 映射:相当于一个坐标无限大的数组
#include <priority_queue> // 优先队列:类似于堆
#include <list>           // 列表:类似于链表            

接下来介绍几个在程序中常使用的容器啦啦啦~

1)

  向量(vector)

    用于存储连续的元素,类似数组;并且可以动态改变数组的大小(不必提前声明数组大小)

给出可爱的代码酱~

void vector_stl()
{
    // vector 声明
    vector<int> a; // 声明一个空的 vector
    vector<int> b(5, 0); // 声明 vector 中有 5 个元素,并且初始值都为 0
    // vector 访问
    for(int i=0; i<5; i++) b[i] = i; // vector 中下标从 0 开始
    // ! a[0] = 1; 非法操作: a 还是空的,没有第一个位置
    // ! a[5] = 5; 非法操作: b 没有第六个位置
    // vector 添加元素
    for(int i=0; i<5; i++) a.push_back(i * i); // 在 a 最后增加一个元素
    for(int i=0; i<5; i++) cout << a[i] << " "; // 输出 vector a
    // 输出结果: 0 1 4 9 16
    // vector 设定长度
    vector<int> c;
    c.resize(5); // 设置 c 的大小为 5,下标 [0-4]
    c[4] = -4; // c[4] 是可以被访问的
    // vector 长度 (数组大小)
    int len = c.size(); // len = 5
    // vector 清空
    c.clear(); // 清空 c 数组
    // ! c[4] = -4; 非法操作:数组已经被清空,长度变为 0
}

2)

  二元组(pair)

    用于存储二元组 (x,y)(并且 x,y 类型可以不相同)

代码酱来也~

void pair_stl()
{
    // pair 声明
    pair<int, int> a; // 声明一个二元组a
    pair<int, int> b(3, 4); // 声明一个二元组b, x=3, y=4

    typedef pair<int, int> PI;
    PI c(5, 6); // 声明一个二元组c

    // pair 访问
    int x = c.first, y = c.second; // x = 5, y = 6
    PI d = c; // 相同类型的二元组可以直接赋值
    c = PI(7, 8); // 重新赋值二元组
    d = make_pair(9, 10); // 另一种赋值方式

/*二元组 (pair)的一个优点是可以直接比较大小;它会先比较第

一关键字(x),再比较第二关键字(y)*/

    PI arr[10];
    for(int i=0; i<5; i++) arr[i] = PI(5 - i, i * i);
    sort(arr, arr+5);
    for(int i=0; i<5; i++)
        cout << "First element:" << arr[i].first << " "
            << "Second element:" << arr[i].second << endl;
/* 通过二元组 (pair)可以把不同类型的元素给有机整合起来*/
    typedef pair<int, PI> PII; // 定义三元组
    PII p = PII(2, PI(4, 8));

    cout << p.first << "," << p.second.first << ","
        << p.second.second << endl;

    typedef pair<string, int> People; // 定义(字符串,整数)二元组
    People pa("Edward", 16);
    People pb("Bob", 17);
    if(pa > pb) swap(pa, pb); // 可以直接进行比较,以字符串为第一关键字,整数为第二关键字进行比较
    cout << pa.first << ":" << pa.second << endl;

}

3)

  集合(set)

    1.在集合 (set)中,可以像普通的集合一样,保存所有不同的数

set<int> S; // 定义一个整型类型的 set
for(int i=0; i<10; i++) S.insert(i*i); // 把 0-9 的平方数加入集合中
set<int>::iterator p; // iterator:迭代器,相当于一个指针
p = S.find(4); // 指针 -- 找到 4 所在位置
cout << *p << endl; // 输出这个位置的值 -- 4
++p; // 指针后移
cout << *p << endl; // 输出后一个平方数的值 -- 9
/*
输出结果:
4
9
*/

    2.在集合 (set)中,可以支持查找一个数的位置

p = S.find(5); // 假如我们想要找一个集合中没有的数
cout << "Notice : (5 is not a square number) " << *p << endl;
cout << (p == S.end()) << endl;
// 就会返回一个特殊的指针:S.end() 结尾的指针
// C++ 中的容器都是左闭右开的:
// S.begin() 头指针 - 存放数据,S.end() 尾指针 - 不存放数据
/*
输出结果:
Notice : (5 is not a square number) 10
1
*/

    3.在集合 (set)中,还有另一种方式查看一个数是否在集合中

for(int i=0; i<10; i++)
if(S.count(i)) cout << i << " is an element of S." << endl;
else cout << i << " is not an element of S." << endl;
// count(x),如果 x 存在则返回 1,不存在则返回 0
/*
输出结果:
0 is an element of S.
1 is an element of S.
2 is not an element of S.
3 is not an element of S.
4 is an element of S.
5 is not an element of S.
6 is not an element of S.
7 is not an element of S.
8 is not an element of S.
9 is an element of S.
*/

    4.还有最后一点就是,在集合 (set)中,亦可以直接支持lower_bound 操作

p = S.lower_bound(20); // 假如我们想要找一个集合中不小于 20 的数
cout << "The first element not lower than 20: " << *p << endl;
S.delete(p); // 删除一个数:使用指针的方式
p = S.lower_bound(20); // 再次寻找
cout << "The first element not lower than 20: " << *p << endl;
p = S.lower_bound(100); // 假如我们想要找一个集合中不小于 100 的数
cout << (p == S.end()) << endl; // 假如没有数比它大,则返回尾指针
/*
输出结果:
The first element not lower than 20: 25
The first element not lower than 20: 36
1
*/

3.迭代器 (Iterator)部分

这里的其实我也不是很清楚w

STL 中的迭代器相当于不同的容器的指针

vector<int>::iterator vi; // 定义迭代器,直接在后面加::iteratorvector<int> V; // 定义容器
for(int i=1; i<10; i++)  V.push_back(i * 3 - 2); // 新增值
for(vi = V.begin(); vi != V.end(); ++vi)  cout << *vi << " ";
    cout << endl; // 按顺序输出容器中的值
        // 特殊的迭代器:V.begin(), V.end()(左闭右开)
        // 迭代器可以自增:往后挪一位
        // 不同容器的迭代器存在着区别        

输出结果:
1 4 7 10 13 16 19 22 25

// STL 中每个容器都有对应的迭代器

set<int> S; // 定义容器
set<int>::iterator p; // 定义迭代器

for(int i=0; i<10; i++) S.insert(i * i); // 插入平方数
p = S.begin(), ++p;
S.erase(p); // 第一种删除方式(迭代器) :删除第二个元素
S.erase(49); // 第二种删除方式(值删除) :删除 49
    cout << "The Sequence : ";
for(p = S.begin(); p != S.end() ; ++p) cout << *p << " ";
    cout << endl; // 顺序输出

输出结果:
The Sequence : 0 4 9 16 25 36 64 81

End.

时间: 2024-11-08 21:10:43

STL x的相关文章

STL学习思想

1.模版:一定要注意参数和返回值的模版 2.STL一系列的API:一定要注意返回值 3.容器中的都是值拷贝,而不是引用,在执行插入时,内部实行拷贝动作,所以STL中插入类时,一般都必须:无参构造函数,拷贝构造函数,重载=运算符,必须的自己重写,达到深拷贝!!! 4.一元谓词:函数只有一个参数,谓词:代表函数的返回值必须为bool类型;   二元谓词:函数只有二个参数,谓词:代表函数的返回值必须为bool类型; 5.算法和具体的数据类型相分离:通过函数对象(仿函数)来实现,本质:函数指针!!! 6

C++ STL学习——vector

学过C++的人肯定会很熟悉STL标准模板库,STL其实就是封装了一系列的接口,供我们调用.很多函数或者算法的实现不需要我们从头开始写,大大提高我们的编程效率.这篇博客在简单介绍STL的情况下,会详细的来介绍vector的使用. STL共有六大组件: 一.容器(Container):是一种数据结构,如list,vector,deque,queue等,以模板类的方法提供,为了访问容器中的数据,可以使用由容器类提供的迭代器. 二.迭代器(Iterator):提供了访问容器中对象的方法. 三.算法(Al

C++ STL中Map的按Key排序和按Value排序

原文  http://blog.csdn.net/iicy266/article/details/11906189 map是用来存放<key, value>键值对的数据结构,可以很方便快速的根据key查到相应的value.假如存储学生和其成绩(假定不存在重名,当然可以对重名加以区分),我们用map来进行存储就是个不错的选择. 我们这样定义,map<string, int>,其中学生姓名用string类型,作为Key:该学生的成绩用int类型,作为value.这样一来,我们可以根据学

stl容器区别: vector list deque set map及底层实现

在STL中基本容器有: vector.list.deque.set.map set 和map都是无序的保存元素,只能通过它提供的接口对里面的元素进行访问 set :集合, 用来判断某一个元素是不是在一个组里面,使用的比较少 map :映射,相当于字典 ,把一个值映射成另一个值,如果想创建字典的话使用它好了 底层采用的是树型结构,多数使用平衡二叉树实现 ,查找某一值是常数时间,遍历起来效果也不错, 只是每次插入值的时候,会重新构成底层的平衡二叉树,效率有一定影响. vector.list.dequ

STL vector,deque,list

一.vector可变长的动态数组必须包含头文件 #include <vector>支持随机访问迭代器• 根据下标随机访问某个元素时间为常数• 在尾部添加速度很快• 在中间插入慢所有STL算法 都能对vector操作 构造函数初始化:vector();无参构造函数, 将容器初始化成空的vector(int n);将容器初始化成有n个元素vector(int n, const T & val);假定元素类型是T, 将容器初始化成有n个元素, 每个元素的值都是valvector(iterat

C++ STL hash_map的使用以及STL hash_map的大“坑”

计算机编程中经常会用到hash表,而在C++中,使用STL编程更是少不了的.本文将介绍STL中hash_map的使用.在hash_map中使用自定义类型作为key值的方法以及在使用char *类型作为key值时遇到的问题. 一.需要的头文件以及命名空间 在linux下使用STL hash_map除了需要引用其所在头文件<hash_map>之外还要引用其命名空间.像这样写  1 using namespace __gnu_cxx; 二.hash_map的定义 先来看看hash_map是怎么定义的

c++ STL容器初探

什么是容器 首先,我们必须理解一下什么是容器,在C++ 中容器被定义为:在数据存储上,有一种对象类型,它可以持有其它对象或指向其它对像的指针,这种对象类型就叫做容器.很简单,容器就是保存其它对象的对象,当然这是一个朴素的理解,这种"对象"还包含了一系列处理"其它对象"的方法,因为这些方法在程序的设计上会经常被用到,所以容器也体现了一个好处,就是"容器类是一种对特定代码重用问题的良好的解决方案". 容器还有另一个特点是容器可以自行扩展.在解决问题时

stl源码剖析 详细学习笔记 算法总览

//****************************基本算法***************************** /* stl算法总览,不在stl标准规格的sgi专属算法,都以 *加以标记 算法名称              算法用途         质变                   所在文件 accumulate          元素累计            否                   <stl_numeric.h> adjacent_differenc

stl源码剖析 详细学习笔记 算法(1)

//---------------------------15/03/27---------------------------- //算法 { /* 质变算法:会改变操作对象之值 所有的stl算法都作用在由迭代器[first,last)所标示出来的区间上.质变算法 就是 运算过程会更改区间内的元素内容 非质变算法:和质变算法相反 */ /* stl算法的一般形式 1>所有的泛型算法的前两个参数都是一对迭代器,通常称为first和last,用以标示算法的操作区间 2>stl习惯采用前闭后开区间

UVAOJ 12096 The SetStack Computer(STL的运用)

12096 The SetStack Computer Background from Wikipedia: Set theory is a branch ofmathematics created principally by the German mathe-matician Georg Cantor at the end of the 19th century. Initially controversial, set theory has come to play therole of