STL学习入门

包括算法、容器、迭代器
1、vector容器与iterator迭代器

#include "vector.h"
void main()
{
    vector<int> v;//定义vector容器
    for(vector<int>::iterator it = v.begin(); it != v.end(); it ++)//定义迭代器it(指针)
    {
    cout << *it <<" ";
    }
}

2、string
(1)构造函数

   默认构造函数:
string();      //构造一个空的字符串string s1。
   拷贝构造函数:
string(const string &str);  //构造一个与str一样的string。如string s1(s2)。
   带参数的构造函数
        string(const char *s);    //用字符串s初始化
        string(int n,char c);    //用n个字符c初始化

(2)遍历
–》通过数组的方式

for(int i = 0; i < s1.length(); i ++)
cout << s1[i] << " ";//不会提示异常,导致程序终止
cout << s1.at[i] << endl;//会提示异常

–》迭代器

for(string::iterator it = s1.begin(); it != s1.end(); it ++)
cout << *it << " ";

(3)连接两个字符串

string s1,s2;
s1 = s1 + s2;
s1.append(s2);

(4)transform(s1.begin(), s1.end(), s1.begin(), toupper/tolower);//将s1全部转换为大写/小写
3、vector容器
—》》基本操作 vector v1;
计算大小:v1.size();
插入元素:v1.push_back(1);
获取尾部元素:v1.back();
获取头部元素:v1.front();
删除尾部元素:v1.pop_back();
初始化:vector v1 = v2;

vector<int> v3(v1.begin(), v1.begin()+2);//左闭右开赋值,相当于v1[0],v1[1]赋给v3

遍历:(1)数组方式遍历时,一定要提前声明内存空间

vector<int> v1(10);//而不是v1就可以了,默认每个内存空间为0
for(int j = 0; j < 10 ; j++)
{
    v1[j] = v1[j] + 1;
}

(2) 迭代器遍历
—》正向遍历(借助正向迭代器)

for(vector<int>::iterator it = v.begin(); it != v.end(); it ++)//其中v.begin()指向第一个元素,v.end()指向最后一个元素的后一个位置
{
cout << *it << endl;
}

—》逆向遍历(借助逆向迭代器)

for(vector<int>::reverse_iterator rit = v.rbegin(); rit != v.rend(); rit ++)
{
    cout << *rit << endl;
}

(3)
区间删除v1.erase(v1.begin(), v1.begin()+3);//删除前三个元素
指定位置删除v1.erase(v1.begin());//删除第一个元素
指定的值删除

for(vector<int>::iterator it = v.begin(); it != v.end())
{
    if(*it == 2)
    {
        v.erase(it);//删除的时候会让it指针自动下移
    }    
    else
        it ++;
}

(4)插入v1.insert(v1.begin(), 100); v1.insert(v2.end(), 200);
4、双端数组deque

push_front()    push_back()//前段、后端插入
pop_front()     pop_back()//前段、后端弹出
查找某个值在数组下标的值
deque<int>::iterator it = find(d1.begin(), d1.end(), -33)
if(it != d1.end())
cout << distance(d1.begin(), it) << endl;//输出-33在队列的下标值

5、stack栈

s.push(i);//入栈
s.pop();//弹出栈顶元素
int tmp = s.top();//获取栈顶元素

6、queue队列

q.push(i);//入队
q.pop();//出列
int tmp = q.front();//获取对头元素

7、list双向链表容器
不可以随机存取元素,所以不支持at.(pos)函数与[]操作符,it++(OK) it+5(ERR)

push_back(i);
//遍历
list<int>::iterator it = l.begin();
while(it != l.end())
{
    cout << *it << endl;
    it ++;
}

在指定位置插入元素:

list<int>::iterator it = l.begin();
it++;
l.insert(it, a);//表示在1号位置插入元素a,原来的1号变2号,2号变3号……
删除元素
l.clear();//清空队列
l.erase(begin,end);//删除[begin,end)区间的元素
l.erase(pos);//删除pos位置的元素
l.remove(elem);//删除所有等于elem元素

删除0号到2号之间所有元素的操作
list<int>::iterator it1 = l.begin();
list<int>::iterator it2 = l.begin();
it2 ++;
it2 ++;
it2 ++;
l.erase(it1, it2);//删除0、1、2号元素

8、优先级队列priority_queue
按照值的大小放在队头、队尾
最大值优先级队列(默认)、最小值优先级队列

priority_queue<int> p1;
等同于
priority_queue<int, vector<int>, less<int> > p2;//最大值优先级队列

priority_queue<int, vector<int>, greater<int>> p3;//最小值优先级队列

9、set
一个集合容器,所包含的元素是唯一的,集合中的元素是按照一定的顺序排列(默认情况下是从小到大),元素插入是按排序规则插入的。

insert,erase
set<int> set1;等同于set<int, less<int>> set1;//默认从小到大
set<int, greater<int>> set2;//从大到小
//当插入的元素是一个类时,要制定按照类的那个元素的大小进行排序,可以通过建立仿函数的形式进行
struct FuncStudent//仿函数
{
bool operator()(const Student &left, const Student &right)
{
    if(left.age < right.age)
    {
    return true;
    }
    else
    {
    return false;
    }
}

main()
{
set set;
Student s1("s1", 31);
Student s2("s2", 32);
set.insert(s1);
set.insert(s2);//自动按照年龄大小进行排序
}
如何知道插入的结果:进入底层函数,查看返回值
pair(set::iterator, bool) pair1 =set.insert(s1);
if(pair1.second == true)
{
    cout <<"插入成功"<< endl;
}
set的查找(迭代器set<int>::iterator是指针)
set.find(elem)//查找elem元素,返回elem元素的迭代器
set.count(elem)//返回值等于elem元素的个数
set.lower_bound(elem)//返回第一个>=elem的迭代器
set.upper_bound(elem)//返回第一个>elem的迭代器
set.equal_range(elem)//返回大于等于和大于的迭代器

pair<set<int>::iterator, set<int>iterator> mypair = set.equal_range(elem);
set<int>::iterator it3 = mypair.first;//大于等于
set<int>::iterator it4 = mypair.second;//大于

10、multiset:同一个值可以出现多次
11、map、multimap
标准的关联式容器,一个map是一个键值对序列,即(key,value)对。他提供基于key的快速索引能力。
key是唯一的,元素是按照一定的顺序排列的。
multimap唯一的区别是相同键可以出现多次,而map每个键只能够出现一次。map支持map[key]=value,而multimap不支持[]操作符。

默认构造:map<int, string> map1;
map.count(key)//返回键值为key的个数,用于multimap
插入元素
map1.insert(pair<int, string>(1, "teacher01"));

map1.insert(make_pair(2, "teacher02"));

map1.insert(map<int, string>::value_type(3, "teacher03"));

map1[4] = "teacher04";
//前三种插入 若key已经存在 则报错
    方法四  若key已经存在 则修改
//前三种插入方法返回值为pair判断是否插入失败
pair<map<int, string>::iterator, bool> mypair = map1.insert(make_pair(2, "teacher02"));
if(mypair.second != true)
    cout << "error" << endl;
else//输出序号和值
    cout << mypair.first->first << "\t" <second << endl;
遍历
for(map<int, string>::iterator it = map1.begin(); it != map1.end(); it ++)
{
cout << it->first << "\t" << it->second << endl;
}
删除
map<int, string>::iterator it = map1.begin();
map1.erase(it);
查找
map<int,string>::itrator it = map.find(key);//查找键key是否存在,若存在,返回该元素的迭代器;否则返回map.end()
map.equal_range(key);//返回两个迭代器的位置,第一个是大于等于key的迭代器的位置,第二个是大于key的迭代器的位置

mutimap的最重要的特性就是:一个key可以对应多个value,常用于分组,一个组下面有多个成员。
12、容器的共性(C++模板是容器的概念)
STL学习入门_第1张图片
13、各个容器的使用时机
STL学习入门_第2张图片
(1) deque的使用场景:比如排队购票系统
(2)list的使用场景:比如公交车乘客的存储,随时可能有乘客下车,支持频繁的不确实位置元素的移除插入。
(3)set的使用场景:比如对手机游戏的个人得分记录的存储,存储要求从高分到低分的顺序排列。
(4)map的使用场景:比如按ID号存储十万个用户,想要快速要通过ID查找对应的用户。
14、函数对象
一个函数对象,即一个重载了括号操作符“()”的对象,即为这个对象的操作符()进行重载

class A{
public:
int operator()(int x){return x;}
};
A a;
a(5);

这里的a就是一个函数对象
15、算法
入门:分清返回值是迭代器还是谓词(函数对象)。
常用的算法:
for_each: 用指定函数依次对指定范围内所有元素进行迭代访问。该函数不得修改序列中的元素。

for_each(vecInt.begin(), vecInt.end(), show);

transform: 与for_each类似,遍历所有元素,但可对容器的元素进行修改

int increase (int i)  
{  
    return i+1;   
}  

main()
        {
            vector<int> vecIntA;
            vecIntA.push_back(1);
            vecIntA.push_back(3);
            vecIntA.push_back(5);
            vecIntA.push_back(7);
            vecIntA.push_back(9);


            transform(vecIntA.begin(),vecIntA.end(),vecIntA.begin(),increase);      //vecIntA : {2,4,6,8,10}
        }

for_each和transform比较:for_each所使用的函数对象,参数是引用,没有返回值;transform所使用的函数对象,参数一般不使用引用,而且还有返回值。
查找相关算法:
在iterator对标识元素范围内,查找一对相邻重复元素,找到则返回指向这对元素的第一个元素的迭代器adjacent_find(v1.begin(), v1.end())
在有序序列中查找value,找到则返回truebinary_seach(v1.begin(), v1.end(), 7)
利用等于操作符,把标志范围内的元素与输入值比较,返回相等的个数int iCount = count(vecInt.begin(),vecInt.end(),2);
返回满足条件的元素的个数

bool GreaterThree(int iNum)
{
        if(iNum>=3)
        {
            return true;
        }
        else
        {
            return false;
        }
}

int iCount = count_if(vecIntA.begin(), vecIntA.end(), GreaterThree);

利用底层元素的等于操作符,对指定范围内的元素与输入值进行比较。当匹配时,结束搜索,返回该元素的迭代器。

vector<int>::iterator it = find(vecInt.begin(), vecInt.end(), 5);

equal_range: 返回一对iterator,第一个表示lower_bound,第二个表示upper_bound。

 map<char,int> mymap;
  pair<map<char,int>::iterator,map<char,int>::iterator> ret;

  mymap['a']=10;
  mymap['b']=20;
  mymap['c']=30;

  ret = mymap.equal_range('b');

  cout << "lower bound points to: ";
  cout << ret.first->first << " => " << ret.first->second << endl;

  cout << "upper bound points to: ";
  cout << ret.second->first << " => " << ret.second->second << endl;
  运行结果:
lower bound points to: 'b' => 20
upper bound points to: 'c' => 30

find_if: 使用输入的函数代替等于操作符执行find。返回被找到的元素的迭代器。
假设vector vecIntA,vecIntA包含1,3,5,3,9元素
vector::it = find_if(vecInt.begin(),vecInt.end(),GreaterThree);

 merge: 合并两个有序序列,存放到另一个序列。
例如:vecIntA,vecIntB,vecIntC是用vector声明的容器,vecIntA已包含1,3,5,7,9元素,vecIntB已包含2,4,6,8元素
vecIntC.resize(9); //扩大容量
merge(vecIntA.begin(),vecIntA.end(),vecIntB.begin(),vecIntB.end(),vecIntC.begin());

   sort:  以默认升序的方式重新排列指定范围内的元素。若要改排序规则,可以输入比较函数。
//学生类
Class CStudent:
{
public:
        CStudent(int iID, string strName)
        {
m_iID=iID;  
m_strName=strName; 
}
public:            
    int m_iID;
    string m_strName;
}

//学号比较函数
bool Compare(const CStudent &stuA,const CStudent &stuB)
{
         return (stuA.m_iIDvoid main()
{
vector vecStu;
vecStu.push_back(CStudent(2,"老二"));
vecStu.push_back(CStudent(1,"老大"));
vecStu.push_back(CStudent(3,"老三"));
vecStu.push_back(CStudent(4,"老四"));

sort(vecStu.begin(),vecStu.end(),Compare);

//  此时,vecStu容器包含了按顺序的"老大对象","老二对象","老三对象","老四对象"
}
reverse(vecInt.begin(), vecInt.end());//反转容器
copy(vecIntA.begin(), vecIntA.end(), vecIntB.begin());  //vecIntB: {1,3,5,7,9}拷贝容器
replace(beg,end,oldValue,newValue):   // 将指定范围内的所有等于oldValue的元素替换成newValue。
replace_if : 将指定范围内所有操作结果为true的元素用新值替换。
用法举例:
replace_if(vecIntA.begin(),vecIntA.end(),GreaterThree,newVal)
其中 vecIntA是用vector<int>声明的容器
GreaterThree 函数的原型是 bool GreaterThree(int iNum)
   swap:   交换两个容器的元素
        vector<int> vecIntA;
        vecIntA.push_back(1);
        vecIntA.push_back(3);
        vecIntA.push_back(5);

        vector<int> vecIntB;
        vecIntB.push_back(2);
        vecIntB.push_back(4);

        swap(vecIntA, vecIntB);  //交换
   accumulate:  对指定范围内的元素求和,然后结果再加上一个由val指定的初始值。
   #include
        vector<int> vecIntA;
        vecIntA.push_back(1);
        vecIntA.push_back(3);
        vecIntA.push_back(5);
        vecIntA.push_back(7);
        vecIntA.push_back(9);
        int iSum = accumulate(vecIntA.begin(), vecIntA.end(), 100);     //iSum==125
   fill:   将输入值赋给标志范围内的所有元素。
        vector<int> vecIntA;
        vecIntA.push_back(1);
        vecIntA.push_back(3);
        vecIntA.push_back(5);
        vecIntA.push_back(7);
        vecIntA.push_back(9);
        fill(vecIntA.begin(), vecIntA.end(), 8);        //8, 8, 8, 8, 8

16、算法应用–演讲比赛
先搭建基本框架,然后完善业务函数。


#include 
using namespace std;

#include "string"
#include 
#include 
#include "set"
#include 
#include "functional"
#include "iterator"  //输出流迭代器的头文件
#include
#include "map"
#include "deque"

class Speaker
{
public:
    string  m_name;
    int     m_score[3];
};

//产生选手
int GenSpeaker(map<int, Speaker> &mapSpeaker, vector<int> &v)
{
    string str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    random_shuffle(str.begin(), str.end());//随机排序

    for (int i=0; i<24; i++)
    {
        Speaker tmp;
        tmp.m_name = "选手";
        tmp.m_name = tmp.m_name + str[i];
        mapSpeaker.insert(pair<int, Speaker>(100+i, tmp) );
    }

    for (int i=0; i<24; i++)
    {
        v.push_back(100+i); //参加比赛的人员
    }
    return 0;
}

//选手抽签
int speech_contest_draw(vector<int> &v)
{
    random_shuffle(v.begin(), v.end());
    return 0;
}


//选手比赛
int speech_contest(int index, vector<int> &v1, map<int, Speaker> &mapSpeaker, vector<int> &v2 )//index表示第几轮 v1表示传入的选手编号 v2表示晋级的选手编号
{
    //小组的比赛得分 记录下来;求出前三名 后3名
    multimap<int, int, greater<int>> multmapGroup; //小组成绩
    int tmpCount = 0;

    for (vector<int>::iterator it=v1.begin(); it!=v1.end(); it++ )
    {
        tmpCount ++;
        //打分
        {
            deque<int> dscore;
            for (int j=0; j<10; j++) //10个评委打分
            {
                int score = 50+rand()%50;
                dscore.push_back(score);
            }
            sort(dscore.begin(), dscore.end());
            dscore.pop_back();
            dscore.pop_front(); //去除最低分 最高分

            //求平均分
            int scoresum = accumulate(dscore.begin(), dscore.end(), 0);
            int scoreavg = scoresum/dscore.size();
            mapSpeaker[*it].m_score[index] = scoreavg; //选手得分 存入容器中
            multmapGroup.insert(pair<int ,int>(scoreavg, *it ) );
        }

        //处理分组
        if (tmpCount % 6 == 0)
        {
            cout << "小组的比赛成绩" << endl;
            for (multimap<int, int, greater<int>>::iterator mit=multmapGroup.begin(); mit!=multmapGroup.end(); mit++ )
            {
                //编号  姓名  得分
                cout << mit->second << "\t" << mapSpeaker[mit->second].m_name << "\t" << mit->first << endl; 
            }

            //前三名晋级
            while (multmapGroup.size() > 3)
            {
                multimap<int, int, greater<int>>::iterator it1 = multmapGroup.begin();
                v2.push_back(it1->second); //把前三名 放到v2 晋级名单 中
                multmapGroup.erase(it1);
            }

            multmapGroup.clear(); //情况本小组 比赛成绩
        }

    }
    return 0;
};

//查看比赛结果
int speech_contest_print(int index, vector<int> &v, map<int, Speaker> &mapSpeaker)
{
    printf("第%d轮 晋级名单\n", index+1);
    for (vector<int>::iterator it=v.begin(); it!=v.end(); it++)
    {
        cout << "参赛编号: " << *it << "\t" << mapSpeaker[*it].m_name << "\t" << mapSpeaker[*it].m_score[index] << endl;
    }
    return 0;
};

void main()
{
    //容器的设计 
    map<int, Speaker>   mapSpeaker; //参加比赛的选手
    vector<int>         v1; //第1轮 演讲比赛 名单
    vector<int>         v2; //第2轮 演讲比赛 名单
    vector<int>         v3; //第3轮 演讲比赛 名单
    vector<int>         v4; //最后前三名 演讲比赛 名单

    //产生选手 得到第一轮选手的比赛名单
    GenSpeaker(mapSpeaker, v1);

    //第1轮 选手抽签 选手比赛 查看比赛结果
    cout << "\n\n\n任意键,开始第1轮比赛" << endl;
    cin.get();
    speech_contest_draw(v1);
    speech_contest(0, v1, mapSpeaker, v2);
    speech_contest_print(0, v2, mapSpeaker);

    //第2轮 选手抽签 选手比赛 查看比赛结果
    cout << "\n\n\n任意键,开始第2轮比赛" << endl;
    cin.get();
    speech_contest_draw(v2);
    speech_contest(1, v2, mapSpeaker, v3);
    speech_contest_print(1, v3, mapSpeaker);

    //第3轮 选手抽签 选手比赛 查看比赛结果
    cout << "\n\n\n任意键,开始第3轮比赛" << endl;
    cin.get();
    speech_contest_draw(v3);
    speech_contest(2, v3, mapSpeaker, v4);
    speech_contest_print(2, v4, mapSpeaker);

    cout<<"hello..."<"pause");
    return ;
}

你可能感兴趣的:(STL)