C++容器类型内置函数随笔

vector 容器

添加数据 vector <int> v ;  v.push_back(数据);

访问数据的两个迭代器b.begin()和v.end() 

vector <int> :: iterator it_begin = v. begin(); //容器起始位置元素的指针

vector <int> :: iterator it_end =v.end(); //指向容器最后一个元素下一个位置的指针

while (it_begin != it_end){

        cout<< *it_begin<<endl;

        it_begin++;

}

另外一种遍历方式:

for (vector <int> :: iterator it = v.begin() ; it != v.end() ; it++)

{

        cout <<*it <<endl;

}

打印vector 元素的函数:

void printvec (vector <int> &v ){

        for (vector <int> :: iterator it = v.begin() ; it != v.end() ; it++)

         {

                cout <<*it <<endl;

        }

}

vector 相似于数组,但是数组是静态空间,vector是动态扩展

动态扩展:
并不是在原空间之后续接新空间,而是找更大的内存空间,然后将原数据拷贝新空间,释放原空间

 vector称之为单端数组,如下图:

无参构造:

vector <int > v ;

有参构造:

vector <int > v2 (v1.begin(),v1.end()); //直接赋值迭代器中间的数据

n个elem方式:

vector <int> v3 (10,100); //10个100

拷贝构造:

vector <int > v4(v);

vector 容量和大小:

判断是否为空 v1.empty()

输出容量v1.capacity()   一般是有空余,比如创建vector空间是13,但是只插入了10个数

输出大小 v1.size() // 按照上述,容量是13,大小是10

重新指定大小v1.resize (20 , x) ; //若过长,则默认使用x值填充 ,若不指定x值,默认为0

若比原来的短,超出的部分删去

插入删除:push_back / pop_back

push_back在尾部添加

pop_back在尾部删除

insert指定位置插入 v1.insert(v1.begin() ,100) //在头部插入100

insert指定位置插入 v1.insert(v1.begin() ,2,1000) //在头部插入2个1000

v1.erase(v1.begin()) ;删除一个头部元素

v1.erase(v1.begin(),v1.end()) ;从头到尾全部删除  等于v1.clear();

at访问元素:

 v1.at(i) 等同于 v1[i] 

获取整个数组的第一个元素: v1.front() ; 最后一个元素: v1.back()

元素互换 swap():

vector<int > v1;

for (int i  = 0 ; i< 10; i++){

        v1.push_back (i );

}

vector<int > v2;

for (int i  = 10 ; i>0; i--){

        v2.push_back (i );

}

v1.swap(v2);  //实现v1与v2内容互换

用于收缩内存空间:

上述代码输出:

防止空间冗余

string容器

string 的构造函数(下列分别对应默认构造、有参构造、拷贝构造):

注意:有参构造需要传入指向const的指针变量

字符串拼接:

直接str += "需要拼接的字符";

或者str.append(” 需要拼接的字符“)

或者需要限制拼接的字符的长度:

str3.append( "LOL_APEX",3);  //第二个参数是长度,即拼接了LOL

str3.append("LOL_APEX!",4,5); //从第4个参数开始截取,取5个长度即:APEX!

查找 :find

int pos = str1.find("abc");//返回第一次出现字符的位置,若没找到返回-1

int pos1= str1.rfind ("abc"); //该函数从右往左查找, 但是下标位置还是从左往右计算

替换:replace

string str1 = "abcdefg";
str1.replace(1,3,"1111");

 返回结果a1111efg ,会把指定的字符全替换进去,而不是依据1到3的长度

字符串比较:compare

字符串比较是按字符的ASCII码进行对比

str1.compare(str2) 
=返回 0
>返回 1 //第一个字符大于第二个字符
<返回 -1

string字符串存取:

访问单个字符:at

for (int i = 0 ;i < str.size() ;i++){

        cout <<str.at(i)<<" ";   //等同于 cout <<str[i]<<" ";

}

修改单个字符也可以用at()


删除:delete  插入:insert 

string str = "hello";

str1.insert (1,"111") ; //在位置为1处插入

最后输出h111ello 

str.erase (1,3);  //从位置1删到位置3

输出hello

截取子串substr:

string str1 = "abcdef";

string subs1  = str1.substr (1,3);

输出sub1 为bcd

实用场景比如截取邮件的@前用户名

拷贝: copy

Deque 容器

 相比于vector ,deque是双端数据,可以对头端进行插入删除操作

vector对头部的插入删除效率低,操作头部速度慢,但是访问元素的速度要比deque快

// 构造函数
deque <int > d1;

for (int i = 0; i<10 ; i++ )

{

        d1.push_back(i) ;

}

deque <int > d2 (d1.begin() , d1.end()); 

deque <int> d3 (10,100) ; //10个100

deque<int > d4 (d1);


//赋值函数
deque <int > d5;
d5= d1;
deque <int > d6;
d6.assign(d1.begin() , d1.end());

判断是否为空 deque.empty()

判断元素个数 deque.size()

注意:Deque中没有查询容量的函数,没有容量的概念

重新指定大小 d1. resize (15,100) ; 超出部分使用100代替,不指定为0

首端与尾端插入和删除:

d1.push_back(10); //尾插

d1.push_back(20);

d1.push_front(100); //头插

d1.push_front(200);

/// 此时输出200 100  10 20 

d1.pop_back() ; 尾删

d1.pop _front() ; 头删

d1. insert("插入位置" ,“插入内容”);

d1. insert("插入位置" ,插入数量,“插入内容”);

删除 : d1. erase("位置")

如删除1位置的元素

deque <int > ::iterate it  = d1.begin();

i++;

d1.erase(it);

全部清空:

d1.clear();

元素访问:

使用[ ] 和at ,使用front返回第一个元素,使用back返回最后一个元素

sort排序:

sort(d.begin(),d.end()); //默认排序是从小到大

vector也可以使用sort排序

打印deque数组:

void printdeque (const deque <int>  &d){

        for (deque <int> :: const_iterator it  = d.begin() ; it != d.end(); i++)

        {

                cout <<*it << " " ;  

        } 

}

Stack容器:先进后出

入栈 push()   出栈 pop()  栈顶为top()

注意:栈不允许有遍历行为,遍历是非质变算法,栈中操作会质变

栈可以判断容器是否为空:empty

栈可以返回元素个数:size

由于栈中的数据都pop()了,则最终size为0

Queue容器:队列容器:先进先出

 

只有队头能出数据,只有队尾能进数据

队列同样不允许有遍历行为,因为只有队头和队尾能被外界访问

入队(在队尾):push()   出队(从队头): pop()

判断是否为空.empty()

判断大小:size()

访问队头元素:q.front()

访问队尾元素:q.back()

while(! q.empty){  // 队列不提供迭代器,也不支持随机访问

        ...

        q.pop(); // 循环之后 全部弹出

}

List链表容器(面试重点!)

功能:将数据进行链式存储

定义:链表list是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的

构成:由一系列的结点构成

结点组成:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域

最后一个结点的指针域指向NULL

链表的优点:动态内存分配,不会造成内存浪费或者溢出。可以对任意的位置进行快速的添加或者插入删除(删除直接变动指针域的指向即可),不需要移动大量的元素

链表的缺点:容器遍历速度没有数组快,所占用的空间比数组大

STL中的链表是一个双向循环链表, 即每个节点有两个地址,一个后向一个前向,循环代表最后一个结点地址指向第一个结点的位置,第一个结点地址指向最后一个结点的位置。

由于链表的存储方式并不是连续的内存空间,因此链表list中的迭代器只支持前移和后移,属于双向迭代器

Vector和List是两个最常被使用的容器,各有优缺点

 List构造函数:

list <T> list1;

list(beg,end) ;  //将区间内容拷贝

list (n, elem) ;    //将n个元素elem拷贝给本身

list(const list &list );  //拷贝构造函数

void printlist(const list<int> &L)
{
    for (list<int> :: const_iterator it = L.begin();it != L.end() ; i++)
    {
         cout <<*it <<" ";   
    }
    cout<<endl;
}

void test 01 (){

        list <int> L1 ; 

        L1.push_back(10);  //链表中添加数据仍然使用push_back()

        L1.push_back(20);

        L1.push_back(30);

        L1.push_back(40);

        printlsit(L1);
        //使用区间的方式拷贝
        list <int> L2 (L1.begin(),L1.end());
        //使用拷贝构造
        list <int> L3 (L2);
        //n个elem
        lsit <int> L4 (10,1000);  //10个1000        


}

List赋值和交换:

 给list容器进行赋值,以及交换

assign(beg,end);  //把beg,end 区间的数据拷贝赋值给本身

assign(n,elem);   //将n个elem拷贝赋值给本身

swap(lst); 将lst与本身的元素互换

void printList(const list<int> &L)
{
    for (list <int>::const_iterator it = L.begin(); it!= L.end();it++)
    {
        cout<<*it<<" ";
    }
    cout <<endl;
    
}

void test01(){
    List<int>  L1;
    L1.push_back(10);
    L1.push_back(20);
    L1.push_back(30);
    L1.push_back(40);


    printList(L1);

    List <int> L2;
    L2 =L1; //属于等号运算符重载赋值

    list <int> L3;
    L3.assign(L2.begin(),L2.end());

    list <int> L4;
    L4.assign(10,1000);  //10个1000

    L1.swap(L2);
}

List大小操作:

size()返回元素个数

empty()返回是否为空

rezise(num) ;重新指定容器长度

打印:
void printList (const list<int> &L){   //加上const防止误操作

        for (list<int> ::const_iterator it = L.begin() ; it != L.end() ; it ++)

        {

                cout <<*it <<" ";

        }

        cout <<endl;

}

List 插入和删除:

L.push_back()在尾部加入元素

L.pop_back()删除容器最后一个元素

L.push_front(); 在开头加入元素

L.pop_front() 删除开头的元素

L.insert(pos,elem); 在pos位置插入elem元素的拷贝,返回新数据的位置

list<int> ::iterator it = L.begin();

L.insert (++it ,1000);  //pos的位置  可以变换

L.erase (++it) ; 删除

L.remove (10000); 指定删除所有值为10000的元素

L.clear()清空

List数据存取:

只能通过.front() 和 .back()访问 首位元素和 结尾元素

无法通过[ ] 和.at()的方式来访问list中的元素,因为list本质是链表数据不是连续线性空间存储

,迭代器不支持随机访问

如果只支持单项,则it--会报错,如果支持随机访问,则可以实现it = it+n;此处不支持,则只能it ++ 或者 it-- ; 

list反转和排序:

反转链表: reverse ( );

链表排序 : sort( ); // 由于List不支持随机访问迭代器,则不可以使用一些标准算法,属于全局函数

如sort(L1.begin(),L1.end())

不支持随机访问迭代器的容器,内部会提供一些算法,属于成员函数

此处内部提供的算法也叫sort(),实现如下:

L1.sort(); //默认排序规则从小到大,升序

如果操作的是一个自定义的数据类型,如list<Person> L1,则需要指定一个回调函数来放入参数

//指定排序规则   返回值类型是bool
bool comparePerson(Person &pl, Person &p2)
{
    //按照年龄 升序
   return pl.m_Age < p2.m_Age;
}

则排序函数为 L1. sort (comparePerson);

如果想实现普通int类型的降序排列,则同样定义一个compare回调函数,传入参数int 1 ,int 2 ,返回 int 1 > int 2 即可;

Set容器:关联式容器、底层使用二叉树实现

其所有元素在插入时会被自动排序,所以称之为一种关联式容器

Set容器没有重复元素,Multiset允许有重复元素

set 容器插入数据只有一个insert的方式
s1. insert (10); 

set <int> s2 (s1) ; //拷贝构造

set <int> s3 ;

s3=s2;

了另外一些基础函数:

交换:  s1.swap(s2);

set中允许erase(直接传入元素删除) , 相当于list中的remove ()操作

打印:

void printset (const set<int> &s1 ){

        for ( set<int> :: iterator it  = s1.begin(); it != s1.end() ; it++ )

        {

                cout<< (*it ) <<" ";

        }

        cout<<endl;

}

s1.find(key) ; 查抄元素,若存在返回该元素的迭代器, 不存在返回s1,end()的迭代器

由于返回总是一个迭代器,所以使用迭代器接收:

set<int> ::iterator pos  = f1,find(30);

if (pos!= s1.end()){

        找到

}

else{ 没找到}

统计元素的个数count()

int num = s1. count (30);

一般在set容器中,返回要么1,要么0

改变set的排序规则:使用仿函数

修改规则为从大到小

class mycompare {

public :

        bool operator() (int v1 , int v2 )  //重载()运算符

        {

                return v1 >v2 ;

        }

}

set <int  , mycompare > s2 ;//此时s2内的元素按照 mycompare中的规则排序

包括对于自定义的数据类型比如 set <Person ,mycompare > s2 ,也要在仿函数mycompare中指定排序规则

Pair队组容器:

pair<string , int > p ("Tom" ,20 ); //默认构造 ,有参构造

cout << "姓名: " <<p.first <<"年龄:" <<p.second<<endl;

pair<string , int > p2 = make_pair("wade",30); //make_pair方式

Map容器(面试重点!):

map中所有的元素都是pair,第一个元素为key值(键值)(索引),第二个元素成为value,实值

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

底层使用二叉树实现,属于一种关联式容器

map同样不允许有重复的key值

可以根据key值快速找到value

map<int,int> m;

m.insert(pair<int,int>( 1 ,10) );    //内部元素都是pair

m.insert(pair<int,int>( 2 ,20) );

m.insert(pair<int,int>( 3 ,50) );

m.insert (make_pair(4,59));// 通过make_pair的方式插入

m[5] = 20;  //一般用于访问而不是插入

打印:
void printMap ( map <int,int > &m){

        for (map<int,int>:: iterator it  = m.begin() ; it ! = e.end(); i++)

        {

                cout<< (*it).first << it-> second<<endl;   // 两种访问方式都可以 (*it) .  和 it->

        }

}

拷贝构造:map<int,int> m2 <m>;

m.empty()判断是否为空

m.size() 返回元素个数

m.swap(m1); //交换

m.erase(key元素) ;  //按照元素删除

m.erase(m.begin(),m.end()); //删除等同于m.clear()

m.find(key); //若存在,返回迭代器,若无,返回m.end()

map<int,int>:: iterator pos = m.find(3);

if(pos != m.end()){}   //若找到...

m.count(key); 对于map,结果要么1要么0

利用仿函数改变排序规则:

class MyCompare {        //一种二元谓词

public : 

        bool operator () (int v1,int v2)      // 包括其他自定义类型数据,同上

        {

                return v1>v2     //按照降序排列

        }

}
map<int,int, MyCompare> m1;

// 打印时也要指定

for (map<int,int ,MyCompare> :: iterator it = m.begin() ; it != m.end() ; it++){

        cout <<it -> first << it -> second<<endl; 

        //或者也可以写为cout << (*it). first << (*it).second <<endl;

}

 sort (v1.begin(),v1.end()) ; 默认从小到大

sort (v1.begin(),v1.end() ,MyCompare()); //上述二元谓词 使用方法,改变算法策略

谓词:

 返回bool类型的仿函数叫谓词

如果operator()接受一个参数,那么叫做一元谓词

如果operator()接受两个参数,那么叫做二元谓词

class GreaterFive {    // 查看是否有大于5的元素

public: 

        bool operator () (int val )

        {

                return val >5;

        }

}

内建函数库#include <functional>

取反仿函数:negate <int>  n;

cout <<n(50) <<endl;  //输出-50

加法仿函数 puls <int> p;  //默认同等类型,直接写一个就行

cout<< p (10,20) <<endl; 

降序排列:greater<int> ()

使用:sort(v.begin(),v.end(),greater<int>());

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值