C++中的STL用法

字符串:

头文件

#include<string>

定义

string str;

获取长度

str.length();

重载操作符[],返回下标所在字符。
字符串连接

str = str1+str2;

标准模板库(STL)

顺序容器:vector/deque/list

关联容器:set/map/multiset/multimap

头文件分别为< vector>/< deque>/< list>/< set>/< map>

迭代器

用于遍历容器中的元素
头文件< iterator>

算法

头文件< algorithm>

find() 找到一个给定的键的元素,若被找到,则返回该元素的一个迭代器。否则返回最后一个元素的下一个位置。(即vec.end())

copy()是将容器的内容复制到另一个容器中。

vector

vector作为STL提供的标准容器之一,是经常要使用的,有很重要的地位,并且使用起来也是灰常方便。vector又被称为向量,vector可以形象的描述为长度可以动态改变的数组,功能和数组较为相似。实际上更专业的描述为:vector是一个多功能的,能够操作多种数据结构和算法的模板类和函数库,vector之所以被认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单地说,vector是一个能够存放任意类型的动态数组,能够增加和压缩数据。(注:STL的容器从实现的角度讲可以说是类模板(class teplate)。)

那么vector和数组的主要区别是什么呢??这对于理解vector是很有帮助的~~~~

数组:分配的是静态空间,一般分配了就不可以改变,就像我们熟知的定义了一个数组,那么数组的长度就不可以改变了,我们也不可以进行越界访问,但是编译器不检查越界,这一点在我们编程的时候要尤为注意(很多都可能会烦这样的错误!!)。一般申请的数组长度不能满足我们的要求了,我们要重新申请大一点数组,然后把原数组中数据复制过来。

vector:分配的是动态空间,即:我们发现在声明vector容器的时候也可以不指定容器的大小,vector是随着元素的加入,空间自动扩展的。但是,我们必须要负责任的肯定vector分配的空间是连续的,也就是支持数组中的下标随机访问,实际上vector的实现机制是:预留一部分空间,而且预留空间的大小是按一定比率增长的,如果空间不够用的话,要保证连续,就必须重新new一片空间,然后将原有元素移动到新空间,同时预留新的空间(并且新分配的空间比原来分配的空间),最后将原来的那部分空间释放掉。这样预留空间的好处就是不用每次向vector中加元素都重新分配空间。

创建:
2.1.vector容器的构造函数

vector容器的声明方式主要包括一下几种:

vector v ,创建一个空的vector。

vector v1(v) ,复制一个vector。

vector v(n) ,创建一个vector,含有n个数据,数据均已缺省构造产生。

vector v(n, elem) ,创建一个含有n个elem拷贝的vector。

vector v(beg,end) ,创建一个以[beg;end)区间的vector。

v.~ vector () ,销毁所有数据,释放内存。
注意:注意这种:vector c(beg,end)声明方式,创建一个和[beg;end)区间元素相同的vector,一定要注意是左闭右开区间,同时需要说的是,STL中不论是容器还是算法都是采用的这种左闭右开区间办事的,包括v.end()函数也是返回的vector末端的下位置,相当于int a[n]的a[n],并不能访问。

v.assign(beg,end) , 将[beg; end)区间中的数据赋值给v。

v.assign(n,elem) , 将n个elem的拷贝赋值给v。

v.at(idx) , 传回索引idx所指的数据,如果idx越界,抛出out_of_range。

v.begin() , 传回迭代器中的第一个数据。

v.capacity() , 返回容器中数据个数。

v.clear() , 移除容器中所有数据。

v.empty() , 判断容器是否为空。

v.end() , 指向迭代器中的最后一个数据地址。

v.insert(pos,elem)       在pos位置插入一个elem拷贝,传回新数据位置(位置指传回地址值)。

v.insert(pos,n,elem)      在pos位置插入n个elem数据。无返回值。

v.insert(pos,beg,end)     在pos位置插入在[beg,end)区间的数据。无返回值。

v.erase(pos)          删除pos位置的数据,传回下一个数据的位置。

v.erase(beg,end)       删除[beg,end)区间的数据,传回下一个数据的位置。

v.capacity()     返回容器中数据个数。

v.size()       返回容器中实际数据的个数。

v.reserve()     保留适当的容量。

v.resize(num)    重新指定队列的长度。

v.max_size()   返回容器中最大数据的数量。

c.pop_back()     删除最后一个数据。

c.push_back(elem)   在尾部加入一个数据。

c.front()       传回地一个数据。

c.back()        传回最后一个数据,不检查这个数据是否存在。

c1.swap(c2)      将c1和c2元素互换。

swap(c1,c2)     同上操作。

#include<iostream>
#include<vector>
#include<algorithm>
#include<iterator>
using namespace std;
int main(){
	const int sz=6;
	int array[sz]={1,2,3,4,5,6};
	vector<int> v;//创建空数组
	//声明jint型的容器,并用数组赋初值
	vector<int> vec(array,array+sz);
	cout<<vec[0]<<endl;//下标访问
	cout<<vec.front()<<endl;//返回第一个元素
	cout<<vec.back()<<endl;//返回最后一个元素
	vec[1]=7;//通过下标操作符来修改容器中元素内容 
	vec.at(2)=10;//用at函数修改,更安全,因为会检查下标是否越界
	vec.insert(vec.begin()+1,22);//在第二个元素位置插入22这一元素
	vec.push_back(19);//尾部添加19元素
	//声明一个迭代器,遍历
	vector<int>::iterator iter;
	for(iter=vec.begin();iter!=vec.end();iter++)
	{
		cout<<*iter<<endl;
	} 
	iter = find(vec.begin(),vec.end(),22);//查找22元素的位置,并返回给迭代器
	if(iter!=vec.end()){
		cout<<"location:"<<(iter-vec.begin())<<endl;
	} else{
		cout<<"not found"<<endl;
	}
	cout<<vec.max_size()<<endl;
	cout<<vec.capacity()<<endl;
	
	vec.erase(vec.begin());
	vec.erase(vec.begin(),vec.end());
	cout<<(vec.empty()?"empty":"not empty")<<endl;;
	vec.insert(vec.begin(),array,array+sz);
	cout<<(vec.empty()?"empty":"not empty")<<endl;;
	vec.clear();//清空容器
	cout<<(vec.empty()?"empty":"not empty");
	return 0;
} 
vector<int> ret;//创建
ret.empty();//判空
ret.push_back(111);//尾插
ret.pop_back();//尾删
ret.size();//获取大小
ret.swap();//交换
ret[0];//访问
ret.insert(ret.begin()+i,222);//在第i+1个元素前插入222
ret.erase(ret.begin()+2);//删除第三个元素
ret.erase(ret.begin()+i,ret.begin()+j);//删除[i,j-1]区间的元素
//遍历,或者也可以对下标用for循环去遍历
vector<int>::iterator iter;
	for(iter=ret.begin();iter!=ret.end();iter++)
	{
		cout<<*iter<<endl;
	} 
//翻转元素
reverse(ret.begin(),ret.end());
//升序排
sort(ret.begin(),ret.end());
//降序排
sort(ret.begin(),ret.end(),cmp);
static bool cmp(int a,int b){
        string A=to_string(a)+to_string(b);
        string B=to_string(b)+to_string(a);
        return A<B;
    }
//将arr复制到array中
copy(arr.begin(),arr.end(),array.begin());

list

1、list是一种序列式容器。list容器完成的功能实际上和数据结构中的双向链表是极其相似的,list中的数据元素是通过链表指针串连成逻辑意义上的线性表,也就是list也具有链表的主要优点,即:在链表的任一位置进行元素的插入、删除操作都是快速的。list的实现大概是这样的:list的每个节点有三个域:前驱元素指针域、数据域和后继元素指针域。前驱元素指针域保存了前驱元素的首地址;数据域则是本节点的数据;后继元素指针域则保存了后继元素的首地址。其实,list和循环链表也有相似的地方,即:头节点的前驱元素指针域保存的是链表中尾元素的首地址,list的尾节点的后继元素指针域则保存了头节点的首地址,这样,list实际上就构成了一个双向循环链。由于list元素节点并不要求在一段连续的内存中,显然在list中是不支持快速随机存取的,因此对于迭代器,只能通过“++”或“–”操作将迭代器移动到后继/前驱节点元素处。而不能对迭代器进行+n或-n的操作,这点,是与vector等不同的地方。

#include<iostream>
#include<list>
using namespace std;
int main(){
	list<int> lst;
	for(int i=0;i<5;++i)
	{
		lst.push_front(i);//前插
		lst.push_back(i);//尾插
	}
	list<int>::iterator itor=lst.begin();//遍历
	while(itor!=lst.end())
	{
		cout<<*itor++<<" ";//输出 4321001234
	}
	cout<<endl;
	return 0;
} 

2.1 list中的构造函数:

list() 声明一个空列表;

list(n) 声明一个有n个元素的列表,每个元素都是由其默认构造函数T()构造出来的

list(n,val) 声明一个由n个元素的列表,每个元素都是由其复制构造函数T(val)得来的

list(n,val) 声明一个和上面一样的列表

list(first,last) 声明一个列表,其元素的初始值来源于由区间所指定的序列中的元素

2.2 begin()和end():通过调用list容器的成员函数begin()得到一个指向容器起始位置的iterator,可以调用list容器的 end() 函数来得到list末端下一位置,相当于:int a[n]中的第n+1个位置a[n],实际上是不存在的,不能访问,经常作为循环结束判断结束条件使用。

2.3 push_back() 和push_front():使用list的成员函数push_back和push_front插入一个元素到list中。其中push_back()从list的末端插入,而 push_front()实现的从list的头部插入。

2.4 empty():利用empty() 判断list是否为空。

2.5 resize(): 如果调用resize(n)将list的长度改为只容纳n个元素,超出的元素将被删除,如果需要扩展那么调用默认构造函数T()将元素加到list末端。如果调用resize(n,val),则扩展元素要调用构造函数T(val)函数进行元素构造,其余部分相同。

2.6 clear(): 清空list中的所有元素。

2.7 front()和back(): 通过front()可以获得list容器中的头部元素,通过back()可以获得list容器的最后一个元素。但是有一点要注意,就是list中元素是空的时候,这时候调用front()和back()会发生什么呢?实际上会发生不能正常读取数据的情况,但是这并不报错,那我们编程序时就要注意了,个人觉得在使用之前最好先调用empty()函数判断list是否为空。

2.8 pop_back和pop_front():通过pop_back删除最后一个元素,通过pop_front()删除第一个元素;序列必须不为空,如果当list为空的时候调用pop_back()和pop_front()会使程序崩掉。

2.9 assign():具体和vector中的操作类似,也是有两种情况,第一种是:l1.assign(n,val)将 l1中元素变为n个T(val)。第二种情况是:l1.assign(l2.begin(),l2.end())将l2中的从l2.begin()到l2.end()之间的数值赋值给l1。

2.10 swap():交换两个链表(两个重载),一个是l1.swap(l2); 另外一个是swap(l1,l2),都可能完成连个链表的交换。

2.11 reverse():通过reverse()完成list的逆置。

2.12 merge():合并两个链表并使之默认升序(也可改),l1.merge(l2,greater()); 调用结束后l2变为空,l1中元素包含原来l1 和 l2中的元素,并且排好序,升序。其实默认是升序,greater()可以省略,另外greater()是可以变的,也可以不按升序排列。

2.13 insert():在指定位置插入一个或多个元素(三个重载):

l1.insert(l1.begin(),100); 在l1的开始位置插入100。

l1.insert(l1.begin(),2,200); 在l1的开始位置插入2个100。

l1.insert(l1.begin(),l2.begin(),l2.end());在l1的开始位置插入l2的从开始到结束的所有位置的元素。

2.14 erase():删除一个元素或一个区域的元素(两个重载)

l1.erase(l1.begin()); 将l1的第一个元素删除。

l1.erase(l1.begin(),l1.end()); 将l1的从begin()到end()之间的元素删除。

set

C++ STL 之所以得到广泛的赞誉,也被很多人使用,不只是提供了像vector, string, list等方便的容器,更重要的是STL封装了许多复杂的数据结构算法和大量常用数据结构操作。vector封装数组,list封装了链表,map和set封装了二叉树等,在封装这些数据结构的时候,STL按照程序员的使用习惯,以成员函数方式提供的常用操作,如:插入、排序、删除、查找等。让用户在STL使用过程中,并不会感到陌生。

关于set,必须说明的是set关联式容器。set作为一个容器也是用来存储同一数据类型的数据类型,并且能从一个数据集合中取出数据,在set中每个元素的值都唯一,而且系统能根据元素的值自动进行排序。应该注意的是set中数元素的值不能直接被改变。C++ STL中标准关联容器set, multiset, map, multimap内部采用的就是一种非常高效的平衡检索二叉树:红黑树,也成为RB树(Red-Black Tree)。RB树的统计性能要好于一般平衡二叉树,所以被STL选择作为了关联容器的内部结构。

begin()    ,返回set容器的第一个元素

end()      ,返回set容器的最后一个元素

clear()    ,删除set容器中的所有的元素

empty()    ,判断set容器是否为空

max_size()   ,返回set容器可能包含的元素最大个数

size()      ,返回当前set容器中的元素个数

rbegin     ,返回的值和end()相同

rend()     ,返回的值和rbegin()相同

#include<iostream>
#include<set>
using namespace std;
int main(){
	set<int> st;
	st.insert(10);
	st.insert(-5);
	st.insert(123);
	st.insert(10);
	
	set<int>::iterator itor=st.begin();
	while(itor!=st.end())
	{
		cout<<*itor++<<" ";//输出-5  10  123 
	}
	cout<<endl;
	int key;
	cin>>key;
	itor = st.find(key);
	if(itor!=st.end())
	{
		cout<<key<<" is in this set"<<endl;
	} else{
		cout<<key<<" is not in this set"<<endl;
	}
	cout<<"set 中 10 出现的次数是 :"<<st.count(10)<<endl;//  1
	cout<<"set 中 4 出现的次数是 :"<<st.count(4)<<endl;//  0
	return 0;
} 

count() 用来查找set中某个某个键值出现的次数。这个函数在set并不是很实用,因为一个键值在set只可能出现0或1次,这样就变成了判断某一键值是否在set出现过了。

erase(iterator) ,删除定位器iterator指向的值

erase(first,second),删除定位器first和second之间的值

erase(key_value),删除键值key_value的值

find() ,返回给定值值得定位器,如果没找到则返回end()。

insert(key_value); 将key_value插入到set中 ,返回值是pair<set::iterator,bool>,bool标志着插入是否成功,而iterator代表插入的位置,若key_value已经在set中,则iterator表示的key_value在set中的位置。

inset(first,second);将定位器first到second之间的元素插入到set中,返回值是void.

lower_bound(key_value) ,返回第一个小于等于key_value的定位器

upper_bound(key_value),返回最后一个大于等于key_value的定位器

map

Map是c++的一个标准容器,她提供了很好一对一的关系,在一些程序中建立一个map可以起到事半功倍的效果,总结了一些map基本简单实用的操作!

  1. map最基本的构造函数;
    map<string , int >mapstring;
    map<int ,string >mapint;
    map<sring, char>mapstring;
    map< char ,string>mapchar;
    map<char ,int>mapchar;
    map<int ,char >mapint;
  2. map添加数据;
    map<int ,string> maplive;
    1.maplive.insert(pair<int,string>(102,“aclive”));
    2.maplive.insert(map<int,string>::value_type(321,“hai”));
    3, maplive[112]=“April”;//map中最简单最常用的插入添加!

3,map中元素的查找:
find()函数返回一个迭代器指向键值为key的元素,如果没找到就返回指向map尾部的迭代器。

map<int ,string >::iterator l_it;; 
   l_it=maplive.find(112);
   if(l_it==maplive.end())
                cout<<"we do not find 112"<<endl;
   else cout<<"wo find 112"<<endl;

4,map中元素的删除:
如果删除112;

  map<int ,string >::iterator l_it;;
   l_it=maplive.find(112);
   if(l_it==maplive.end())
        cout<<"we do not find 112"<<endl;
   else  maplive.erase(l_it);  //delete 112;

5,map中 swap的用法:
Map中的swap不是一个容器中的元素交换,而是两个容器交换;
For example:

#include <map>
#include <iostream>
using namespace std;
int main( )
  {
      map <int, int> m1, m2, m3;
      map <int, int>::iterator m1_Iter;
      m1.insert ( pair <int, int>  ( 1, 10 ) );
      m1.insert ( pair <int, int>  ( 2, 20 ) );
      m1.insert ( pair <int, int>  ( 3, 30 ) );
      m2.insert ( pair <int, int>  ( 10, 100 ) );
      m2.insert ( pair <int, int>  ( 20, 200 ) );
      m3.insert ( pair <int, int>  ( 30, 300 ) );
   cout << "The original map m1 is:";
   for ( m1_Iter = m1.begin( ); m1_Iter != m1.end( ); m1_Iter++ )
      cout << " " << m1_Iter->second;
      cout   << "." << endl;
   // This is the member function version of swap
   //m2 is said to be the argument map; m1 the target map
   m1.swap( m2 );
   cout << "After swapping with m2, map m1 is:";
   for ( m1_Iter = m1.begin( ); m1_Iter != m1.end( ); m1_Iter++ )
      cout << " " << m1_Iter -> second;
      cout  << "." << endl;
   cout << "After swapping with m2, map m2 is:";
   for ( m1_Iter = m2.begin( ); m1_Iter != m2.end( ); m1_Iter++ )
      cout << " " << m1_Iter -> second;
      cout  << "." << endl;
   // This is the specialized template version of swap
   swap( m1, m3 );
   cout << "After swapping with m3, map m1 is:";
   for ( m1_Iter = m1.begin( ); m1_Iter != m1.end( ); m1_Iter++ )
      cout << " " << m1_Iter -> second;
      cout   << "." << endl;
}

在这里插入图片描述

6.map的sort问题:
Map中的元素是自动按key升序排序,所以不能对map用sort函数:
For example:

#include <map>
#include <iostream>
using namespace std;
 int main( )
 {
   map <int, int> m1;
   map <int, int>::iterator m1_Iter;
   m1.insert ( pair <int, int>  ( 1, 20 ) );
   m1.insert ( pair <int, int>  ( 4, 40 ) );
   m1.insert ( pair <int, int>  ( 3, 60 ) );
   m1.insert ( pair <int, int>  ( 2, 50 ) );
   m1.insert ( pair <int, int>  ( 6, 40 ) );
   m1.insert ( pair <int, int>  ( 7, 30 ) );
   cout << "The original map m1 is:"<<endl;
   for ( m1_Iter = m1.begin( ); m1_Iter != m1.end( ); m1_Iter++ )
      cout <<  m1_Iter->first<<" "<<m1_Iter->second<<endl;
  
}

运行结果:
The original map m1 is:
1 20
2 50
3 60
4 40
6 40
7 30
请按任意键继续. . .

7, map的基本操作函数:
C++ Maps是一种关联式容器,包含“关键字/值”对

  begin()          返回指向map头部的迭代器
  clear()         删除所有元素
  count()          返回指定元素出现的次数
  empty()          如果map为空则返回true
  end()            返回指向map末尾的迭代器
  equal_range()    返回特殊条目的迭代器对
  erase()          删除一个元素
  find()           查找一个元素
  get_allocator()  返回map的配置器
  insert()         插入元素
  key_comp()       返回比较元素key的函数
  lower_bound()    返回键值>=给定元素的第一个位置
  max_size()       返回可以容纳的最大元素个数
  rbegin()         返回一个指向map尾部的逆向迭代器
  rend()           返回一个指向map头部的逆向迭代器
  size()           返回map中元素的个数
  swap()            交换两个map
  upper_bound()     返回键值>给定元素的第一个位置
  value_comp()      返回比较元素value的函数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值