STL算法的精髓在于  算法的  返回值!!!

String:
  string是STL的字符串类型,通常用来表示字符串;C语言中一般用char*
  char*字符指针;string是类封装了char*,管理这个字符串,是一个char*型的容器;
  string不用考虑内存释放和越界,string管理char*所分配的内存。
  string提供了一系列字符串操作函数(find,copy,erase,replace,insert)
初始化 :

  string s1 = "abcd"; //重载operator=
  string s2("abcd") //有参构造函数
  string s3 = s2; //初始化调用的是拷贝构造函数,跟赋值调用operator=()不同
  string s1(,'a'); //s1的内容:aaa;将字符复制n份

遍历:

通过数组的方式:

for(int i = ; i < s1.length(); i++)
{
cout << s1[i] << " ";
}

通过迭代器:

for(string::iterator k = s1.begin(); k = s1.end(); k++)
{
cout << *k << " ";
}

通过at()函数:

与数组的[]方法相比,at()可以抛出异常,提示下标越界;而[]不抛出异常直接中断程序。

字符指针和string的转换:

string->char* //生成一个const char*指针,c_str()指向以空字符终止的数组;data()返回的数组不以空字符终止。
string s1 = "aaaaa";
printf("s1 : %s \n",s1.c_str()); s1的指针
char*->string
char buf[]; // char buf[128] = {0}; //c风格字符串
s1.copy(buf,,);//从位置0开始,拷贝3个字符,到buf内;注意自己拷贝\0,不然后面的值都无效。

连接字符串:

string s1 = "aaa";
string s2 = "bbb";
s1 = s1+s2; s1.append(s4); //s1为aaabbb

字符串查找和替换:

string s1 = "jgaaa jjdsj aaa sljf aaa sjfj aaa dfj99";
int index = s1.find("aaa",); //从下标为0开始找aaa,找到后返回下标2,找不到返回-1; 返回当前元素下标
//统计aaa的个数:
int offIndex = s1.find("aaa",);
while(offIndex != string::npos) //npos即-1
{
cout++;
    offIndex += ;
   offIndex = s1.find("aaa",offIndex);
}

大小写替换:

int offIndex = s1.find("aaa",);
while(offIndex != string::npos) //npos即-1
{
s1.replace(offIndex,,"AAA"); //从offIndex开始,删除3份字符,替换为AAA
offIndex += ;
offIndex = s1.find("aaa",offIndex);
}

字符串的删除和插入:

string s1 = "qbb";
s1.insert(,"aaa"); //qaaabb
s1.insert(,,'c'); //qcccaaabb
s1.insert(s1.length(),"zzz"); //qcccaaabbzzz
string::iterator it = find(s1.begin(),s1.end(),'q'); // 迭代器相关的算法 find 返回指向当前元素的迭代器位置
while(it != s1.end())
{
   s1.erase(it); //bb 此时的it已经不存在,erase()会返回指向下一个元素是迭代器位置 it1 = s1.erase(it); //*it == c;
}
s1.erase(s1.begin(),s1.end()); //区间删除:删除整个字符串

字符串相关算法:大小写转换

transform(s1.begin(),s1.end(),s1.begin,toupper); //s1从开始到结尾将小写转大写,并输出到begin的位置(第三个参数)
transform(s1.begin(),s1.end(),s1.begin,tolower);// s1从开始到结尾将小写转大写,并输出到begin的位置(第三个参数)

STL容器简介:

vector:动态数组(尾部添加删除元素)
vector<int>v1;
push_back(); //数组的尾部插入
pop_back(); //删除最后一个元素
v1.front(); //取第一个元素 (其实现返回了一个引用,可以当左值)
v1.back(); //取最后一个元素 (可以当左值)

初始化:

push_back();
vector<int>v2 = v1;
vector<int>v3(v1.begin(),v1.begin()+);
vector<int>v4(,); //

遍历:

vector<int>v1(); //通过数组方式;通过等号操作符需要提前分配内存push_back()在尾部添加元素,新增元素在11号位处
迭代器:(插入,输出,)
begin()指向头元素;end()指向最后一个元素的后面的一个位置
正向迭代器:
for(vector<int>::iterator k = v1.begin(); k = v1.end(); k++)
逆向迭代器: //逆序输出
for(vector<int>::reverse_iterator k = v1.rbegin(); k = v1.rend(); k++)
const迭代器(只读)有2种:(不可当左值)
vector<int>::const_iterator
vector<int>::const_reverse_iterator
《effective STL》建议使用iterator 代替其余三种迭代器;

删除:

vector<int>v1();
v1.erase(); //删除全部
v1.erase(v1.begin(),v1.begin()+); //区间删除:删除2个元素;顺序容器可以调用随机存储器
v1.erase(v1.begin()+); //删除第3个元素
删除某类元素:
for(vector<int>::iterator it = v1.begin(); it = v1.end();)
{
  if(*it == )
  {
    it = v1.erase(it); //删除迭代器位置处的元素,同时指向已删除元素的迭代器也失效了;自增后返回当前位置 也就是说返回当前删除元素的下一个元素的迭代器,如果不用it去保存该位置,原来it++就报错
  }
  else
  {
    it++;
  }
}

插入:

vector.insert(pos,elem); //pos位置插入一个elem元素的拷贝,返回新元素的位置
vector.insert(pos,n,elem); //无返回值
vector.insert(pos,beg,end); //pos,beg,end均为迭代器的相对位置
eg: vec1.insert(vec1.begin()+,vec2.begin(),vec2.end());

重点:vector中保存对组pair< , >的插入和遍历:

#include <iostream>
#include <vector>
#include <algorithm> using namespace std; bool lessCompare(const pair<string,int>& obj1, const pair<string,int>& obj2)
{
return obj1.second < obj2.second;
}
bool greatCompare(const pair<string,int>& obj1, const pair<string,int>& obj2)
{
return obj1.second > obj2.second;
}
int main()
{ int N, Mode;
cout << "please input N and Mode" <<endl;
while(cin>>N>>Mode)
{
cout << "please input name and age" << endl;
string name;
int age;
vector<pair<string,int>>vec1; //这个地方一旦初始化N了,新插入元素从N+1位置插入
for(int i = ; i < N && cin>>name>>age; ++i)
{
vec1.push_back(make_pair(name,age)); //其他的方法都不成功
}
if(Mode == )
{
stable_sort(vec1.begin(),vec1.end(),lessCompare);
}
if(Mode == )
{
stable_sort(vec1.begin(),vec1.end(),greatCompare);
}
cout << "data after sort: " << endl;
vector<pair<string,int>>::iterator it = vec1.begin();
for( ; it != vec1.end(); ++it)
{
cout << it->first << " " << it->second << endl; //vector放单一变量可以用*it取值,pair应该用这种方法取值
}
/*
for(int i = 0; i < vec1.size(); ++i)
{
cout << vec1[i].first << " " << vec1[i].second << endl; //这个也是可以用的
}*/
} cout << "Hello World!" << endl;
return ;
}

deque:双端数组(头尾插入删除)

插入:
push_front() ,push_back() //注意:插入都是向外扩散的,所以push_front()插入元素显示与插入顺序相反
删除:
pop_front() ;pop_back();

利用迭代器查找元素下标:

deque<int>::iterator it = find(d1.begin(),d1.end(),); //find是算法,要加头文件#include "algorithm"
if(it != d1.end())
{
  cout << "元素12的下标是:" << distance(d1.begin(),it) << endl;
}

stack:(先进后出) 

push();// 压入一个元素
top();// 获取栈顶元素先进后出
pop();// 弹出栈顶元素
empty();
size();
//容器的值语义。容器是将元素复制了一份到栈,如果是对象的话,其成员有指针就会导致浅拷贝的问题。

queue:(先进先出)
push() front() pop() empty()

list:(双向链表容器)
可高效地进行插入删除元素;
不可以随机存取元素,所以不支持at(pos)函数和[]操作符,迭代器不支持it+5;
注:可以当数组用,此时可以用at()和[],顺序操作,支持it++和it--等顺序操作

push_back(elem);
push_front(elem);
pop_back();
pop_front();
front();
back();

重要:链表结点index序号从0号位置开始

在3号位置插入,即在原来3号元素的前面插入;  //  insert(it2,100);

list.clear(); //删除所有数据
list.erase(beg, end); //删除[beg, end)区间的数据,返回下一个数据位置,左闭右开的删除
重要:erase(it1, it2); //it1++;it1++;it2 = it1; 不支持list.begin()+2 //insert(it2,100);
list.erase(pos); //删除pos位置数据,返回下一个数据位置
list.remove(elem); //删除容器中所有与elem值匹配的元素

priority_queue(二叉堆,一种完全二叉树)
#include "queue"
empty();size();top();pop();push(item);

priority_queue<int> p1; //默认情况下是 最大值优先级队列
priority_queue<int, vector<int>, less<int>> p2; //最大值;提前定义好预定义函数 谓词
priority_queue<int, vector<int>, greater<int>> p3; //最小值优先级队列

set/multiset   #include "set"

//set是一个集合容器,元素唯一,已排序;默认从小到大
//按照排序规则插入,所以不能指定插入位置;
//不可直接存取元素(不可以使用at(pos)和[])
//不可以直接修改set/multiset容器中元素值,因为该类容器是自动排序的。可以删除原有元素,再插入新元素。
//采用红黑树变体的数据结构实现。红黑树属于平衡二叉树,插入和删除比vector快;
//multiset支持重复元素;
insert(); empty(); erase(pos);
set<int>::iterator set1; <=> set<int, less<int>>::iterator set2;
set<int, greater<int>>::iterator set3; //由大到小

复杂数据类型,自定义数据类型排序 ==>仿函数 函数对象

伪函数(仿函数):重载了"()"操作符的普通类对象,从语法上讲,它与普通函数行为类似。

struct FuncStudent
{
  bool operator()(const Student& left, const Student& right)
  {
  if(left.age < right.age)
  {
    return true;
  }
  else
  {
    return false;
  }
}
set<Student, FuncStudent>set1;
Student s1("s1",);
Student s2("s2",);
Student s3("s3",);
set1.insert(s1); //...
for(set<Student, FuncStudent>::iterator it = set1.begin();...)

重要:set是有序的,键值唯一,当age相同时,后面的插入失败;即不插入,然后继续插入后面不重复的元素

//insert()源码:F11单步进入 返回类型是 对组 pair<T1, T2>
//typedef pair<iterator, bool> _Pairib;
pair<set<Student, FuncStudent>::iterator, bool> pair1 = set1.insert(s1);
if(pair1.second == true)
{
  cout << "插入s1成功" << endl;
}

set的查找:

set.find(elem); //查找elem元素,返回指向该元素的迭代器。
set.count(elem); //元素个数,set为0或1;multiset值可能大于1
set.lower_bound(elem); //返回第一个>=elem的迭代器
set.upper_bound(elem); //返回第一个>elem的迭代器 set.equal_range(elem); //返回=elem的迭代器上下限,[beg, end),其中*beg>=elem, *end>elem
该函数返回两个迭代器,被封装在pair中。
pair<set<int>::iterator, set<int>::iterator> pair1 = set1.equal_range(elem);
set<int>::iterator it1 = pair1.first; //beg, *beg>=elem
set<int>::iterator it2 = pair1.second; //*end>elem

map/multimap #include "map"
标准的关联式容器。
key唯一;元素按一定顺序排列,插入过程按排序规则插入,不能指定插入位置、
红黑树变体的平衡二叉树,插入和删除比vector快。
map[key] = value;
multimap 相同键可多次出现,不支持[]操作符;

insert:

map<int, string>map1;
map1.insert(pair<int, string>(,"tracher1"));
map1.insert(make_pair(,"tracher2"));
map1.insert(map<int, string>::value_type(,"tracher3"));
map1[] = "teacher4";

前三种方法返回pair(对组)

pair<map<int, string>::iterator, bool> pair1 = map1.insert(make_pair(2,"tracher2"));
重要:
这种方式,插入已经存在的key就不插入;
通过第四种 = 操作,插入已经存在的key就覆盖;

遍历:
迭代器:

for(map<int,string>::iterator it = map1.begin(); it != map1.end(); it++)
{
  cout << it->first << "\t" << it->second << endl;
}

删除:

while(!map1.empty())
{
  map<int,string>::iterator it = map1.begin(); //erase()后it失效,需要赋新值
  map1.erase(it);
}

map1.erase(); //删除全部
map1.erase(v1.begin(),v1.begin()+2); //区间删除:删除2个元素
map1.erase(v1.begin()+3); //删除第3个元素

查找:(判断是否查找成功,即迭代器是否 = map1.end())
find:
map<int,string>::iterator it = map1.find(100);
首先,接到insert的返回值pair

//equal_range:
pair<map<int>::iterator, map<int>::iterator> pair1 = map1.equal_range(elem); //返回两个迭代器,>=elem 和 >elem
if(pair1.first == map1.end())
{
  cout << "第一个迭代器 >= elem 的位置不存在" << endl;
}
else
{
  cout << pair1.first->first << "\t" << pair1.first->second << endl;
}
//pair1->first 表示第一个迭代器 ->first表示->key

multimap:

1个key值可以对应多个value =>分组
部门做key,人对象做value;

容器总结:

一、容器的值语意:浅拷贝;

除了queue和stack外,每个容器都提供可返回迭代器的函数运用返回的迭代器可以访问元素!!!为什么呢???(后文解析)
每个容器都提供一个默认构造函数 和 一个默认拷贝构造函数值语意,浅拷贝)。

当容器存放对象时,如果对象有指针,容器的值语意会造成浅拷贝。
vector.push_back(t1); //此时,C++编译器会调用Teacher类自带的拷贝构造函数,将t1拷贝一份到容器中
//如果不写一个深拷贝的拷贝构造函数,就会造成野指针。

解决办法: 定义自己的拷贝构造函数。
自定义的类中,最好自定义自己的 无参构造函数 拷贝构造函数 和 重载operator=操作符 将浅拷贝扼杀在摇篮里;
至于有参构造函数,根据需要定义。

class Teacher
{
public:
  Teacher(char* name, int age)
  {
    m_name = new char[strlen(name)+];
    strcpy(m_name,name);
    m_age = age;
  }
  ~Teacher()
  {
  if(m_name != NULL)
  {
    delete [] m_name;
    m_name = NULL;
    m_age = ;
  }
}
//自定义拷贝构造函数
Teacher(const Teacher& obj)
{
  m_name = new char[strlen(obj.m_name)+];
  strcpy(m_name, obj.m_name);
  m_age = obj.m_age;
}
//重载operator=操作符(成员函数)
Teacher& operator=(const Teacher& obj)
{
//1.析构左操作数原数据
  if(m_name != NULL)
  {
    delete [] m_name;
    m_name = NULL;
    m_age = ;
}
//2.根据右操作数,给左操作数申请内存
    m_name = new char[strlen(obj.m_name)+];
//3.赋值
    strcpy(m_name, obj.m_name);
    m_age = obj.age;
//4.返回调用对象
  return *this;
}
private:
  char* m_name;
  int age;
}

二、除了queue和stack外,每个容器都提供可返回迭代器的函数运用返回的迭代器可以访问元素!!!

  分别是vector、list和deque,这三种顺序容器的设计都会设计到迭代器的概念,STL要求任何一种容器都必须内置一个迭代器如果连迭代器都没有内置就谈不上”容器“的定义了。所以,stack只是一个容器适配器,并不是一个容器,因为stack不提供迭代器,所以在元素不弹出的前提下不能够遍历内部所有的元素。

  另外,queue是在stack基础上做了封装(两个栈怎么实现一个队列),所以也不是一个容器,而叫做容器适配器。

  任何提供末端插入(push_back函数)、删除(pop_back函数)、访问(back函数)都能够被stack容器封装与修饰。这里的封装指的是通过stack对象,你不能直接访问被封装的底层容器了,所谓的修饰指的是stack在对底层容器做封装的同时,还提供了必要的接口,以满足用户的需要。我们将被适配器封装的底层容器称为基础容器。

       在我们所学过的顺序容器中,只要能够提供末端的插入、删除和访问操作,都可以作为stack适配器的基础容器,所以vector、list和deque都可以作为stack的基础容器,而stack默认的基础容器为deque容器

参见:  http://blog.csdn.net/jxh_123/article/details/34411457

2_STL容器的更多相关文章

  1. docker——容器安装tomcat

    写在前面: 继续docker的学习,学习了docker的基本常用命令之后,我在docker上安装jdk,tomcat两个基本的java web工具,这里对操作流程记录一下. 软件准备: 1.jdk-7 ...

  2. 网页提交中文到WEB容器的经历了些什么过程....

    先准备一个网页 <html><meta http-equiv="Content-Type" content="text/html; charset=gb ...

  3. [Spring]IoC容器之进击的注解

    先啰嗦两句: 第一次在博客园使用markdown编辑,感觉渲染样式差强人意,还是github的样式比较顺眼. 概述 Spring2.5 引入了注解. 于是,一个问题产生了:使用注解方式注入 JavaB ...

  4. 深入理解DIP、IoC、DI以及IoC容器

    摘要 面向对象设计(OOD)有助于我们开发出高性能.易扩展以及易复用的程序.其中,OOD有一个重要的思想那就是依赖倒置原则(DIP),并由此引申出IoC.DI以及Ioc容器等概念.通过本文我们将一起学 ...

  5. Docker笔记一:基于Docker容器构建并运行 nginx + php + mysql ( mariadb ) 服务环境

    首先为什么要自己编写Dockerfile来构建 nginx.php.mariadb这三个镜像呢?一是希望更深入了解Dockerfile的使用,也就能初步了解docker镜像是如何被构建的:二是希望将来 ...

  6. JS判断鼠标进入容器方向的方法和分析window.open新窗口被拦截的问题

    1.鼠标进入容器方向的判定 判断鼠标从哪个方向进入元素容器是一个经常碰到的问题,如何来判断呢?首先想到的是:获取鼠标的位置,然后经过一大堆的if..else逻辑来确定.这样的做法比较繁琐,下面介绍两种 ...

  7. docker4dotnet #2 容器化主机

    .NET 猿自从认识了小鲸鱼,感觉功力大增.上篇<docker4dotnet #1 前世今生&世界你好>中给大家介绍了如何在Windows上面配置Docker for Window ...

  8. 深入分析Spring 与 Spring MVC容器

    1 Spring MVC WEB配置 Spring Framework本身没有Web功能,Spring MVC使用WebApplicationContext类扩展ApplicationContext, ...

  9. Set容器--HashSet集合

    Set容器特点: ①   Set容器是一个不包含重复元素的Collection,并且最多包含一个null元素,它和List容器相反,Set容器不能保证其元素的顺序; ②   最常用的两个Set接口的实 ...

随机推荐

  1. java读取properties配置文件信息

    一.Java Properties类 Java中有个比较重要的类Properties(Java.util.Properties),主要用于读取Java的配置文件,各种语言都有自己所支持的配置文件,配置 ...

  2. jQuery方法注意事项

    1.关于选择器中含有特殊符号 选择器中含有".","#","(","]"等特殊字符,根据W3C的规定,属性值中是不能含有 ...

  3. Uva442 hdu 1082 Matrix Chain Multiplication

    要注意取出来的时候 先取出q的是后面那个矩阵 后取出p的是前面的矩阵 所以是判断 p.a == q.b #include <iostream> #include <stack> ...

  4. JetS3t使用说明

    http://blog.csdn.net/hitmediaman/article/details/6636402

  5. iOS开发实用干货——强化你的Xcode控制台

    f(x) 郑秀晶程序员不要整天看代码,偶尔也要看看风景?? www.90168.org先上一张我的Xcode控制台的图片让你们感受一下 酷炫控制台 是不是觉得很酷?不过仅仅是酷还是远远不够的,当你点击 ...

  6. JavaScript 笔记 ( Prototype )

    这阵子实在好忙 ( 这样说好像也不是一两个月了... ),然后因为工作伙伴都是 JavaScript 神之等级的工程师,从中也学到不少知识,毕竟就是要和强者工作才会成长呀!为了想好好瞭解他们写的程式码 ...

  7. 快速傅里叶变换FFT学习小记

    FFT学得还是有点模糊,原理那些基本还是算有所理解了吧,不过自己推这个推不动. 看的资料主要有这两个: http://blog.miskcoo.com/2015/04/polynomial-multi ...

  8. javascript的基本语法、数据结构

    本篇学习资料主要讲解javascript的基本语法.数据结构      无论是传统的编程语言,还是脚本语言,都具有数据类型.常量和变量.运算符.表达式.注释语句.流程控制语句等基本元素构成,这些基本元 ...

  9. Web App开发入门

    WebApp与Native App有何区别呢? Native App: 1.开发成本非常大.一般使用的开发语言为JAVA.C++.Objective-C. 2.更新体验较差.同时也比较麻烦.每一次发布 ...

  10. android presentation

    对于双屏异显(lcd 和 hdmi 的双屏异显),android框架已经支持,但是底层接口功能还是要自己去实现,且需要底层驱动支持. 使用presentation 去画第二个display就好了. M ...