c++第十五天(STL库)

22 篇文章 2 订阅
6 篇文章 0 订阅

目录

一、STL库的说明

C++ STL 提供给程序员以下三类数据结构的实现:

二、STL迭代器

语法:容器类型 <容器数据类型> :: iterator  对象 ;

vector < int > :: iterator  it ;

例子:

经典遍历:for( it = p.begin() ; it != p.end() ; it++ )

三、Vectors容器

1、构造函数

2、函数接口

 使用例子:

四、Lists 链表容器

 1、构造函数

五、配置器

六、双向队列(deque)

七、栈(stacks) 

八、队列

九、Priority Queues(优先队列)

十、bitset位操作容器

十一、set容器

十二、map映射容器

十三、STL 存储自定义数据类型

总结:


一、STL库的说明

C++ STL (Standard Template Library标准模板库) 是通用类模板和算法的集合,它提供给程序员一些标准的数据结构的实现如 queues(队列), lists(链表), 和 stacks(栈)等。

C++ STL 提供给程序员以下三类数据结构的实现:

1、顺序结构 。

  C++ Vectors ,C++ Lists ,C++ Double-Ended Queues 。

2、容器适配器。

  C++ Stacks ,C++ Queues ,C++ Priority Queues 。

3、联合容器。 

  C++ Bitsets ,C++ Maps ,C++ Multimaps ,C++ Sets ,C++ Multisets 。

程序员使用复杂数据结构的最困难的部分已经由STL完成。

二、STL迭代器

迭代器就相当于每种容器的专用指针! 每一个容器都有唯一的一个迭代器。

语法:容器类型 <容器数据类型> :: iterator  对象 ;

vector < int > :: iterator  it ;

例子:

//整型容器
    vector<int> p(2,789);   //容器装了2个int型的789
    vector<int>::iterator it;  //声明迭代器it,类型必须一致
    for(it = p.begin();it!=p.end();it++){
        cout << *it << endl;
    }

经典遍历:for( it = p.begin() ; it != p.end() ; it++ )

逆迭代器 操作与迭代器是相反的!! 如:it++ 则指针向前偏移。

rbegin() 函数 

语法: 

   reverse_iterator rbegin();

例子:p.rbegin();

rend() 返回Vector起始的逆迭代器 

三、Vectors容器

Vectors 包含着一系列连续存储的元素,其行为和数组类似,特点:数据的操作都是从尾巴开始。

1、构造函数

vector();//默认构造 
vector( size_type num, const TYPE &val );	//把num 个 val 放入vector 容器中
vector( const vector &from );	//拷贝构造函数 
vector( input_iterator start, input_iterator end );	  //利用迭代器初始化区间的值

2、函数接口

TYPE back(); //获取最后一个元素

TYPE front();//获取第一个元素 

void clear();//删除所有数据 

void pop_back(); //删除最后一个元素

void push_back( const TYPE &val );//插入一个元素 

insert 函数插入函数  
语法: 
iterator insert( iterator it, const TYPE &val );//it 的位置上 插入一个 val 
void insert( iterator it, size_type num, const TYPE &val );//it 的位置上插入num个 val

void insert( iterator it, input_iterator start, input_iterator end );
//it 位置上插入 [start , end] 区间的值
 
iterator erase( iterator it ); //删除迭代器所指向的元素

iterator erase( iterator start, iterator end );//删除迭代器,所指向的区间

 使用例子:

#include<iostream>
#include <vector>   //添加向量容器的头文件
using namespace std;

//封装删除代码
void del_data(vector<int> &p,int data){
    for(auto it=p.begin();it!=p.end();it++){    //auto:自动识别数据类型并转换
        if(*it == data){
            p.erase(it);
            return;
        }
    }
}

//迭代器遍历
int main()
{
    //整型容器
    vector<int> p(2,789);   //容器装了2个int型的789
    vector<int>::iterator it;  //声明迭代器it,类型必须一致
    for(it = p.begin();it!=p.end();it++){
        cout << *it << endl;
    }

    //向p里面插入三个数据
    p.push_back(11);
    p.push_back(22);
    p.push_back(33);

    vector<int>::iterator it2;  //声明迭代器it2
    it2 = p.end();   //迭代器指向p末尾的下一个地址
    cout << *(it2-1) << endl;   //获取容器p的末尾数值,打印元素33
    p.erase(it2-1);  //删掉末尾的元素,剩下元素(789,789,11,22)
    it2 = p.begin(); //指向开头元素
    p.erase(it2);    //删除开头元素,剩下(789,11,22)
    cout << "删除后剩下" << endl;
    for(it2 = p.begin();it2!=p.end();it2++){    //打印剩下的(789,11,22)
        cout << *it2 << endl;
    }
    //调用封装函数
    del_data(p,789);
    cout << "调用封装函数删除789" << endl;
    for(it2 = p.begin();it2!=p.end();it2++){    //打印剩下的(789,11,22)
        cout << *it2 << endl;
    }

    //字符串容器
    vector<string> v1(2,"helloworld2");
    vector<string>::iterator it3;
    // for(it3=v1.begin();it3!=v1.end();it3++){}
        // cout << *it3 << endl;
    it3 = v1.begin();
    cout << *it3 << endl;

    // v1.push_back("good");

}

四、Lists 链表容器

 1、构造函数

  list<int> first;                                // 定义一个空链表 
  list<int> second (4,100);                       // 往链表中放入4个100  
  list<int> third (second.begin(),second.end());  // 利用迭代器初始化
  list<int> fourth (third);                       // 拷贝构造函数 
  支持的运算符  
  =,==,!=,>=,<=,> ,<

注意:list容器不支持下标操作 [ ]

2、函数接口

void push_back( const TYPE &val ); //尾插法
void push_front( const TYPE &val );//头插法
void pop_back(); //尾插 
void pop_front();//头删

iterator erase( iterator loc ); //删除 loc 位置上的数据 

iterator insert( iterator pos, const TYPE &val );//在pos的位置插入 val 

//直接删除数据 
void remove( const TYPE &val );

//链表翻转 
void reverse();

//排序
void sort();
void sort( Comp compfunction );

//在pos位置插入lst链表 
void splice( iterator pos, list &lst );

//合并链表 
void merge( list &lst );
void merge( list &lst, Comp compfunction );
//compfunction 指定合并的算法 
bool mycomparison (int first, int second)
{return first<second;}
//demo: 
merge(lst,mycomparison);

demo

#include<iostream>
#include<list>
using namespace std;

//设计通用模板,传递任何数据都能打印,返回值要是void型,不然会段错误!!!

template <class T>
void show(T &f0){
    for(auto p=f0.begin();p!=f0.end();p++){
        cout << *p << endl;
    }
}


int main()
{
   
    list<string> t; //创建一个链表容器
    t.push_back("你好");
    t.push_back("我好");
    t.push_front("大家好");
   
    list<string>::iterator lt=t.begin();    
    lt++;
    t.insert(lt,"hello");   //在指定位置插入字符串
    lt++;
    t.insert(lt,"well");  //在指定位置插入字符串
    t.insert(lt,"well2");  //在指定位置插入字符串
    // t.erase(lt);    //删除迭代器lt上的数据
    t.insert(lt,t.begin(),t.end()); //插入开始到结束的值(可自定义区间,用t指向)
    t.erase(t.begin(),t.end());   //删除开始到结束的区间(可自定义区间,用t指向)
    t.push_front("嗯");
    t.pop_front();  //头删法
    t.reverse();  //链表翻转.niu
    t.sort();  //链表排序
    t.remove("hello");    //直接删除数据
    t.clear();  //清空所有的值
    show(t);
}

五、配置器

作用:作类型的转换。 例如: 电压 220V ->(电源适配器,转换) 手机的充电电压5V-1A 。

// list::get_allocator
#include <iostream>
#include <list>
using namespace std;

int main ()
{
   //链表容器
  list<int> mylist;
  int * p;
  unsigned int i;

  //利用适配器提取,链表的5个空间
  p=mylist.get_allocator().allocate(5);
  // assign some values to array
  for (i=0; i<5; i++) p[i]=i;
  cout << "The allocated array contains:";

  for (i=0; i<5; i++) cout << " " << p[i];
  cout << endl;
  //利用适配器提,释放刚刚提取的 5 个空间 
  mylist.get_allocator().deallocate(p,5);

  return 0;
}

六、双向队列(deque)

双向队列:与vectors向量一样,但是支持头尾操作(双向的可++和--)。

构造函数:其实就是重载。

deque();
deque( size_type size );
deque( size_type num, const TYPE &val );
deque( const deque &from );
deque( input_iterator start, input_iterator end );

七、栈(stacks) 

C++ Stack(堆栈) 是一个容器类的改编,为程序员提供了堆栈的全部功能。

函数语法:

void pop();
pop() 函数移除堆栈中最顶层元素。
   
void push( const TYPE &val );
push() 函数将 val 值压栈,使其成为栈顶的第一个元素
  
size_type size();
size() 函数返当前堆栈中的元素数目。
  
TYPE &top();
top() 函数返回对栈顶元素的引用.   

 例子:

#include <iostream>
using namespace std;
//添加栈的头文件
#include <stack>

int main()
{
   stack<int>  s; 
   //入栈 
    s.push(10);
    s.push(20);
    s.push(30);
    s.push(40);

    //出栈 
    while (!s.empty())
    {
       cout << s.top() << endl; //访问栈的元素 
       s.pop(); //出元素
    }  
}

八、队列

C++队列是一种容器适配器,它给予程序员一种先进先出(FIFO)的数据结构。

#include<iostream>

//添加队列头文件
#include<queue>

using namespace std;

int main(int argc, char const *argv[])
{
    //定义一个队列
    queue<int> l1;
    //入队
    for(int i = 10; i < 80; i+=10)
        l1.push(i);

    //判断队列是否为空
    while(!l1.empty())
    {
        cout << l1.front() << endl;  //访问队头元素
        l1.pop(); //出队
    }
    return 0;
}

九、Priority Queues(优先队列)

C++优先队列类似队列,特点:插入的数据会自动排序。

栈和队列和优先队列的例子:

#include<iostream>
#include<queue>
#include<stack>
using namespace std;

int main()
{
    cout << "队列:先进先出" << endl;
    queue<int> q;
    q.push(11);  //入队
    q.push(21);
    q.push(3);
    q.push(7);

    while(!q.empty()){
        cout << q.front() << endl;  //打印队头元素
        q.pop();    //出队
    }

    cout << "****************" << endl;
    cout << "栈:先进后出" << endl;
    stack<int> s;
    s.push(233);    //入栈
    s.push(111);
    s.push(444);
    s.push(777);
    while(!s.empty()){
        cout << s.top() << endl; //打印栈顶元素
        s.pop();    //出栈
    }

    cout << "****************" << endl;
    cout << "优先队列:由大到小排序" << endl;  //可以自动排序,存储在堆空间
    priority_queue<int> pq;     //默认由大到小排序
    pq.push(456);
    pq.push(123);
    pq.push(888);
    while(!pq.empty()){
        cout << pq.top() << endl;  //打印队头元素
        pq.pop();    //出队
    }

}

十、bitset位操作容器

C++ Bitsets给程序员提供一种位集合的数据结构。Bitsets使用许多二元操作符,比如逻辑和,或等。

构造函数:

bitset(); //默认构造函数 
bitset( unsigned long val ); //把val转换为二进制数,存储到bitset中

函数接口和例子:将131转换成123

#include<iostream>
#include<bitset>
using namespace std;

int main()
{
    bitset<8> bs((long) 131);  //通过位操作修改为123
    for(int i=(int)bs.size()-1; i>=0; i--){  //0-7,从最高位开始打印,最低位是0
        cout << bs[i] ; //输出 1000 0011
    }
    cout<<endl<< "--------------"<<endl;
    //将 131 转换成 123 , 即,1000 0011(131) -> 0111 1011(123)
    //取反,全部取反,如果指定位,就从右到左第几位取反,最开始是0
    bs.flip(3);    //第4位取反,即0111 1011
    //清0,全部清0,如果指定位,就从右往左数第几位清0
    bs.reset(7);  //第8位清0
    //置1,全部置1,如果指定位,就从右往左数第几位置1
    bs.set(4);
    bs.set(5);
    bs.set(6);
    // for(int i=(int)bs.size()-1; i>=0; i--)
    //     cout << bs[i] ; //输出  0111 1011
    cout << bs.to_string();  //直接字符串输出  0111 1011
    cout << endl;
    //转换为无符号整形输出
    cout << bs.to_ulong() << endl;
}

运算符:

语法: 
  !=, ==, &=, ^=, |=, ~, <<=, >>=, []

这些操作符都可以和bitsets一起工作。它们被这样定义: 
!= 返回真如果两个bitset不相等。 
== 返回真如果两个bitset相等。 
&= 完成两个bitset间的与运算。 
^= 完成两个bitset间的异或运算。 
|= 完成两个 
~ 反置bitset (和调用 flip()类似) 
<<= 把bitset向左移动 
>>= 把bitset向右移动 
[x] 返回第x个位的引用 

十一、set容器

set:集合是一种关联容器,它存储唯一的元素,其中元素本身就是键key。其实内部的数据结构是二叉搜索树 BST。

特点:不允许插入相同的数据,快速查找!。

构造函数 ( 重载 ):

set<int> first;                           // 默认构造
set<int> third (second);                  // 拷贝构造函数
set<int> fourth (second.begin(), second.end());  // 利用迭代器赋值
set<int,classcomp> fifth;                 //默认构造,并设置比较函数 

//比较方法的设计 
struct classcomp {
  bool operator() (const int& lhs, const int& rhs) const
  {return lhs<rhs;}
};

函数接口:

//插入数据 
pair insert( const TYPE &val );
返回值:是一个pair 对组,数据是成对存在。
//直接删除 
size_type erase( const key_type &key );
//直接查找
iterator find( const key_type &key );

MultiSets:多元集合(MultiSets)和集合(Sets)相像,支持重复对象!。

set和Multisets例子(不支持重复和支持重复数据):

#include<iostream>
#include<set>
using namespace std;

int main()
{
    set<int> s;     //set联合容器,可自动排序,由小到大
    set<int>::iterator it;
    s.insert(11);   //插入
    s.insert(15);
    s.insert(21);
    s.insert(566);
    s.insert(1);
    s.insert(5);

    // s.insert(5);    //不支持重复对象
    for(it=s.begin();it!=s.end();it++){
        cout << *it << " " ;    //遍历
    }
    cout << endl;

    it = s.find(15);    //查找数据
    cout << "find:" <<*it << endl;

    s.erase(11);    //删除数据
    cout << "erase:11"  << endl;

    for(it=s.begin();it!=s.end();it++){
        cout << *it << " " ;    //遍历
    }
    cout << endl;

    //MultiSets:多元集合(MultiSets)和集合(Sets)相似,支持重复对象。
    multiset<string> m;
    multiset<string>::iterator it2;
    m.insert("33");
    m.insert("32");
    m.insert("32");

    for(it2=m.begin();it2!=m.end();it2++){
        cout << *it2 << endl;
    }

}

十二、map映射容器

C++ Maps是一种关联式容器,包含“关键字/值”对,利用一个key 映射一个 value ,map 容器中所有数据都是 pair ,不允许出现重复的KEY数据!

pair对组:

#include <iostream>
using namespace std;

int main()
{
    //定义一个对组,姓名+学号 
    pair<string,int>  a;

    a.first = "小明"; //第一项数据 = 小明 
    a.second = 123;  //第二项数据  = 123  

    cout << a.first   << endl; 
    cout << a.second  << endl; 

}

函数接口:

//在pos 位置插入 
iterator insert( iterator pos, const pair<KEY_TYPE,VALUE_TYPE> &val );
//插入区间
void insert( input_iterator start, input_iterator end );
//插入一个 pair 
pair<iterator, bool> insert( const pair<KEY_TYPE,VALUE_TYPE> &val );
//通过 key 快删除数据 
size_type erase( const KEY_TYPE &key );
//通过key 快速查找 value  
iterator find( const KEY_TYPE &key );

例子:

// C++ Maps是一种关联式容器,包含“关键字/值”对,利用一个key 映射一个 value 
// map 容器中所有数据都是pair ,不允许出现重复的**KEY**数据!  
#include<iostream>
#include<map>
using namespace std;

int main()
{
    //定义一个对组pair,姓名+学号
    pair<string,int> p; //第一个是字符串型,第二个是int型
    p.first = "小花";  //first代表第一项数据key键 = 小花
    p.second = 10086;  //second代表第二项数据value值 = 10086
    cout << p.first ;    //打印
    cout << p.second << endl;
    //map容器储存对组的三种方法
    //定义一个map容器存放对组
    map<string,int> fir;
    //1、定义一个对组
    pair<string,int> p1("小东",10088);
    //插入数据
    fir.insert(p1);
    //2、生成一个对组
    fir.insert(make_pair<string,int>("小妹",10011));
    //3、创建一个对组,强烈推荐,方便实用
    fir["小芳"] = 10000;
    //[key] = value;
    //键值是唯一的,但值可以多个。
    // fir["小芳"] = 10001;    //同名键值会覆盖前面的键值和值。
    fir["小贝"] = 10000;     //相同的值不会覆盖前面的键值。
    //遍历
    for(auto it2=fir.begin();it2!=fir.end();it2++){
        cout << "key:" << it2->first << " value:" << it2->second << endl;
    }
}

C++ Multimaps和maps很相似,但是MultiMaps允许重复的元素。

十三、STL 存储自定义数据类型

注意: 需要重载定义了类中的运算符操作 。

//利用STL 库封装一个背包类,管理材料,药水,和装备。
#include<iostream>
#include<list>
#include<string.h>
using namespace std;

class Back{
private:
    string mat;   //材料
    string lq_med; //药水
    string equip;  //装备
public:
    Back(string mat,string lq_med,string equip):mat(mat),lq_med(lq_med),equip(equip){ }
    void show(){
        cout << "材料:" << this->mat << endl;
        cout << "药水:" << this->lq_med << endl;
        cout << "装备:" << this->equip << endl;
    }
friend ostream &operator<<(ostream &o,Back B); //重载运算符
};

//1.创建对象链表
//2.插入有参构造函数(可顺便初始化)
//3.重载<<运算符
//4.利用迭代器遍历
//重载<<,其实就是显示接口,在里面打印,参数传入一个o,一个类对象,只不过返回一个o作为<<运算符。

ostream &operator<<(ostream &o,Back B){
    B.show();    //调用接口函数显示
    return o;    //返回<<运算符
}

int main()
{
    list<Back> B;    //创建对象类链表
    B.push_back(Back("红宝石","红药水","无尽之刃"));
    B.push_back(Back("蓝宝石","蓝药水","泣血之刃"));
    B.push_back(Back("黄宝石","黄药水","暴风之刃"));
    // list<Back>::iterator By;
    //遍历
    for (auto By = B.begin(); By!=B.end(); By++){
        cout << *By << endl;
    }
}

总结:

1、STL库很多,set,list,优先队列都是可以自动排序的,vector,deque支持下标操作set和list是等不支持下标操作的,要会使用迭代器进行操作。

2、map支持两个类型,第一个是key,第二个是value,可以存放类。

3、auto是自动类型转换,方便了操作。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值