8.C++ STL 基本容器和操作

STL初识

STL:标准模板库

建立了一套数据结构和算法的标准,包含容器、算法、迭代器

组件

STL大体分为六大组件,分别是:容器、算法、迭代器、仿函数、适配器(配接器)、空间配置器

  1. 容器:各种数据结构,如vector、 list、 deque、 set、 map等,用来存放数据。
    1. 序例式容器:强调值的排序,序例式容器中的每个元素均有固定的位置。
    2. 关联式容器:二叉树结构,各元素之间没有严格的物理上的顺序关系
  2. 算法:各种常用的算法,如sort、 find、 copy、 for__each等
    1. 质变算法:是指运算过程中会更改区间内的元素的内容。例如拷贝工替换,删除等等
    2. 非质变算法:是指运算过程中不会更改区间内的元素内容,例如查找、计数、遍历、寻找极值等等
  3. 迭代器:扮演了容器与算法之间的胶合剂。提供一种方法,使之能够依序寻访某个容器所含的各个元素,而又无需暴露该容器的内部表示方式。每个容器都有自己专属的迭代器,迭代器使用非常类似于指针,初学阶段我们可以先理解迭代器为指针
    1. 双向送代器
    2. 随机访问迭代器
  4. 函数:行为类似函数,可作为算法的某种策略。
  5. 适配器: - 种用来修饰容器或者仿函数或迭代器接口的东西。
  6. 空间配置器:负责空间的配置与管理。

String容器

string是一个类,维护了一个char*的容器,自动管理char*内存,不用担心越界问题。

构造函数

string();									//创建空串			string s1;
string(const char* s);		//用字符串初始化  string s1("hello world")
string(const string& str);//拷贝构造,用一个stringg对象初始化另一个  string s2(s1);
string(int n,char c);			//用n个c初始化   string(3,'c');

赋值操作

//运算符重载
string& operator=(const char*s);//char*类型学符串 赋值给当前的学符串  str1="hello world"
string& operator=(const string &s);//把字符串s赋给当前的字符串 str2=str1
string& operator=(char c);//字符赋值给当前的字符串 str2='c'

//函数方式
string& assign(const char *s)://把字符串s赋给当前的字符串 str1.assign("hell oworld")
string& assign(const char *s, int n)://把字符串s的前n个字符赋给当前的字符串 str1.assign("hell oworld",3)
string& assign(const string &s);//把字符串s赋给当前字符串 str2.assign(str1)
string& assign(int n, char c);//用n个字符c赋给当前字符串 str1.assign('c',6)

拼接操作

//重载
str1+="123";
str1+='c';
str2+=str1;
//成员函数
str1.append("123");
str1.append("123",2);//前两个追加到str1
str1.append('c',3);
str1.append(str2);

查找和替换

//查找第一次位置 返回位置下标 找不到返回-1
int find(const string& str, int pos =0) const;//查找str第一次出现位置,从pos开始查找  str1.find(str2,0)
int find(const char* s, int pos =0 ) const;//查找s第一次出现位置,从pos开始查找  str1.find("123",0)
int find(const char* s, int pos, int n) const;//从pos位置查找s的前n个字符第一次位置  str1.find("1233",0,2)
int find(const char c, int pos = 0) const;//查找字符c第一次出现位置 str1.find('c',0)
//查找最后一次位置
int rfind(const string& str, int pos = npos) const;//查找str最后一次位置,从pos开始查找 
int rfind(const char* s, int pos = npos) const;//查找s最后一次出现位置,从pos开始查找
int rfind(const char* s, int pos, int n) const;//从pos查找s的前n个字符最后一次位置
int rfind(const char c, int pos = ) const;//查找字符c最后一次出现位置
//替换
string& replace(int pos, int n, const string& str);//替换从pos开始n个字符为字符串str str1=str1.replace(0,3,str2)
string& replace(int pos, int n,const char* s);//替换从pos开始的n个字符为字符串s  str1=str1.replace(0,3,str1)

比较

比较方式:按照ASCII码进行比较,挨个字符按顺序相比,直到第一个不一致的值

  • =返回 0

  • >返回 1

  • <返回 -1

int compare(const string &s) const; //str1.compare(str1)
int compare(const char *s) const; //str1.compare("123")

单个字符存取访问

使用[]或at成员函数

string str = "123";
for(int i = 0;i<str.size();i++){
  cout<<str[i]<<endl;
}

for(int i = 0;i<str.size();i++){
  cout<<str.at(i)<<endl;
}

str[0] = '8';
str.at(0) = '8';

插入删除

pos起始的(包含pos)字符串往后挪

string& insert(int pos, const char* s);//插入字符串   str.insert(0,"123")
string& insert(int pos, const string& str); //插入字符串  str1.insert(0,str2)
string& insert(int pos, int n, char c);//在指定位置插入n个字符c  str.insert(0,,3,'1')
string& erase(int pos, int n = npos);//删除从Pos开始的n个字符  str.erase(0,3)

子串获取

string substr(int pos = 0,int n = npos) const; //返回由pos开始的n个字符组成的字符串  str.substr(0,3)

vector容器

单端数组,可以动态扩展(申请新空间,释放旧空间,和栈不同的是,可以访问里面的元素,而栈只能访问栈顶)

请添加图片描述

构造函数、iterator遍历

vector<T> v;//采用模板实现类实现,默认构造函数
vector(v.begin(),v.end());//将v[begin(),end0)区间中的元素拷贝给本身
vector(int n, elem);//构造函数将n个elem拷贝给本身
vector(const vector &vec);//拷贝构造函数。

void printitem(vector<int>&v){
  for(vector<int>::iterator it=v.begin();it!=v.end();it++){
    cout<<*it<<endl;
  }
}

void test(){
  vector<int>v1;
  printitem(v1);
  
  vector<int>v2(v1.begin(),v1.end());
  
  vector<int>v3(v2);
  
  vector<int>v3(10,100);
}

赋值

vector& operator=(const vector &vec); //重载等号操作符  vector<int>v1=v2
assign(beg,end);//将[beg, end)区间中的数据拷贝赋值给本身.  v2.assign(v1.begin(),v1.end())
assign(n,elem)//将n个elem拷贝赋值给本身.  v2.assign(3,3)

容量和大小

capacity>size

empty();//判断容器是否为空
capacity();//容器的容量
size();//返回容器中元素的个数
resize(int num);//重新指定容器的长度为num比容器大,则以默认值0填满容器.
										//如果num比容器小,则末尾超出容器长度的元素被删除。
resize(int num, elem);//重新指定容器的长度为num,若容器变长,则以elem值填充新位置
										//如果容器变短,则末尾超出容器长度的元素被删除

插入和删除

push_back(ele);//尾部插入元素ele  入栈
pop_back();//删除最后一个元素  出栈
insert(const iterator pos, ele);//迭代器指向位置pos插入元素  v1.insert(v1.begin(),10)  在头插入10
eleinsert(const_iterator pos,int count,ele);//迭代器指向位置pos插入count个元素  v1.insert(v1.begin(),10,10)
eleerase(const iterator pos);//删除迭代器指向的元素  v1.insert(v1.begin())
erase(const_iterator start,const iterator end); //删除迭代器从start到end之间的元素
clear();//删除容器中所有元素

数据存取和访问遍历

at(int idx);//返回索引idx所指的数据
operator[];//返回索引idx所指的数据
front();//返回容器中第一个数据元素
back();//返回容器中最后一个数据元素

void printitem(vector<int>&v){     //若const vector<int>&v为参数,则下面迭代器也要改成const迭代器,且不能修改内容了
  //方式一
  for(vector<int>::iterator it=v.begin();it!=v.end();it++){  //vector<int>::const_iterator it=v.begin()
    cout<<*it<<endl;
  }
  
  //方式二
  for(int i = 0;i<v1.size();i++){
    cout<<v1.at(i)<<endl;
  }
  //方式三
  for(int i = 0;i<v1.size();i++){
    cout<<v1[i]<<endl;
  }
}

容器互换

swap(const vector &vec)

巧用swap可以收缩内存空间,容量大的容器里面放的元素较少的时候,可以收缩内存

vector<int>(v).swap(v);

vector(v)是匿名对象 相当于用拷贝构造创建了一个新的对象,元素等同于v但是容量少

随后调用.swap将v和匿名对象互换来达到收缩内存空间的目的。

预留空间

reserve(int len) 预留len空间的长度,多余空间不初始化,不可访问

避免重新分配的内存导致系统消耗

deque容器

双端数组,双端数组,可以对头部插入,插入效率比vector快

请添加图片描述

deque内部有一个中控器,使得deque像一片连续空间,类似邻接表/多级页表。

构造函数

deque<T> d;//采用模板实现类实现,默认构造函数
deque(d.begin(),d.end());//将d[begin(),end0)区间中的元素拷贝给本身
deque(int n, elem);//构造函数将n个elem拷贝给本身
deque(const deque &deq);//拷贝构造函数。

赋值、大小、数据存取和访问遍历操作

类似vector

插入删除

//插入操作
push_back(elem);//在容器尾部添加一个数据
push_front(elem);//在容器头部插入一个数据
pop_back();//删除容器最后一个数据
pop_front();//删除容器第一个数据

//位置操作:
insert(pos,elem);//在pos位置插入一个elem元素的拷贝,返回新数据的位置
insert(pos,n,elem);//在pos位置插入n个elem数据,无返回值
insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值。
clear();//清空容器的所有数据
erase(beg,end) ;//删除[beg,end)区间的数据,返回下一个数据的位置。
erase(pos);//删除pos位置的数据,返回下一个数据的位置

排序操作

sort(iterator beg,iterator end) 对beg和end之间进行排序,要引入algorithm.h头文件,默认从小到大

sort(d.begin(),d.end())

对于迭代器支持随机访问的容器,都支持sort

stack容器

与vector不容,stack不能遍历

请添加图片描述

常用接口

//构造函数:
stack<T> stk;//stack采用模板类实现,stack对象的默认构造形式
stack(const stack &stk);//拷贝构造函数

//赋值操作:
stack& operator=(const stack &stk);//重载等号操作符
//数据存取:
push(elem);//向栈顶添加元素
pop();//从栈顶移除第一个元素
top();//返回栈顶元素
//大小操作:
empty() ;//判断堆栈是否为空
size();//返回栈的大小

queue容器

不能遍历,先进先出

请添加图片描述

常用操作

//构造函数:
queue<T> que;//queue采用模板类实现,queue对象的默认构造形式
queue( const queue &que);//拷贝构造函数

//赋值操作:
queue& operator= (const queue &que);//重载等号操作符

//数据存取:
push(elem);//往队尾添加元素
pop();//从队头移除第一个元素
back();//返回最后一个元素
front();//返回第一个元素

//大小操作:
empty();//判断堆栈是否为空
size();//返回栈的大小

list容器

链表

  • 优点
    • 非连续存储,双向循环链表
    • 插入删除时间复杂度较小
  • 缺点
    • 随机访问代价大

请添加图片描述

迭代器只支持前后移,是双向迭代器

List有一个重要性质:插入、删除都不会造成原有list迭代器失效,vector则不成立。(在vector中,如果插满了需要重新找一个内存空间存放,那么原有内存的迭代器就会失效)

构造函数、赋值、互换、大小

与vector相同

插入删除、存取

双向迭代器不能随机访问,不能类似vector进行at操作、[]随机访问

push_back(elem);//在容器尾部加入一个元素
pop_back()://删除容器中最后一个元素
push_front(elem);//在容器开头插入一个元素
pop_front()://从容器开头移除第一个元素
insert(pos,elem);//在pos位置插elem元素的拷贝,返回新数据的位置.
insert(pos,n,elem);//在pos位置插入n个elem数据,无返回值
insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值。
clear();//移除容器的所有数据erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置
erase(pos);//删除pos位置的数据,返回下一个数据的位置.
remove(elem);//删除容器中所有与elem值匹配的元素

front(); //返回第一个元素
back();  //返回最后一个元素

反转和排序、仿函数初识

reverse() 反转

sort() 排序:默认从小到大

仿函数进行从大到小排序

bool myCompare(int v1,int v2){  //myCompare(Person &p1,Person &v2)
  //降序 第一个数>第二个数
  return v1>v2;
}

List<int>l1;
l1.sort(myCompare);

set/multiset容器

所有元素都会在插入时自动被排序

关联式容器,结构是二叉树实现。

set/multiset区别

  • set不允许重复元素,插入数据同时会返回插入结果,表示插入是否成功(返回pair类型) pair<set<int>::iterator,bool> ret = s.insert(num)ret.second访问插入结果
  • multiset允许重复元素

构造和赋值

//构造:
set<T> st;//默认构造函数:
set(constet &st);//拷贝构造函数
//赋值:
set& operator=(const set &st);//重载等号操作符

大小和交换

不能进行resize的操作,因为会用相同元素填充,而set不允许重复元素。

size();//返回容器中元素的数目
empty( );//判断容器是否为空
swap(st);//交换两个集合容器

插入和删除

insert(elem);//在容器中插入元素。
clear();//清除所有元素
erase(pos);//删除pos迭代器所指的元素,返回下一个元素的迭代器
erase(beg, end);//删除区间[beg,end)的所有元素,返回下一个元素的迭代器
erase(elem);//删除容器中值为elem的元素

查找和统计

find(key)//查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end()
count(key); //统计key的元素个数

修改插入时的排序规则

要创建一个mycompare的类

class myCompare{  //myCompare(Person &p1,Person &v2)
  //降序 第一个数>第二个数
  public:
  bool operator()(int v1,int v2){  //重载运算符()  (const Person &p1,const Person &p2)
    return v1>v2;
  }
}

Set<int,mycompare>s2;
l1.insort(myCompare);

pair对组

//创建
pair<type, type> p( value1, value2 );
pair<type, type> p = make_pair( value1, value2 );

map/multimap容器

简介

  • map中所有元素都是pair

  • pair中第一个元素为key (键值) 起到索引作用,第二个元素为value (实值)

  • 所有元素都会根据元素的键值自动排序

本质
map/multimap属于关联式容器,底层结构是用二叉树实现。

优点

可以根据key值快速找到value值map和multimap。

区别

  • map不允许容器中有重复key值元素
  • multimap允许容器中有重复key值元素

构造和赋值

//构造:
map<T1,T2> mp;//map默认构造函数
map(const map &mp);//拷贝构造函数

//赋值:
map& operator=(const map &mp);//重载等号操作符

大小和交换

size/swap/empty用法和其他相同

插入和删除

注意 插入的elem一定要是元组

insert(elem);//在容器中插入元素。   m.insert(pair<int,int>(1,10))  或   m.insert(make_pair(1,10))
clear();//清除所有元素
erase(pos);//删除pos迭代器所指的元素,返回下一个元素的迭代器
erase(beg, end);//删除区间[beg,end)的所有元素,返回下一个元素的迭代器
erase(key);//删除容器中值为key的元素.

查找和统计

find(key); //存在返回迭代器,不存在返回set.end()
count(key);

修改排序规则

class myCompare{  //myCompare(Person &p1,Person &v2)
  //降序 第一个数>第二个数
  public:
  bool operator()(int v1,int v2){  //重载运算符()  (const Person &p1,const Person &p2)
    return v1>v2;
  }
}
map<int,int,mycompare> m
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值