C++总结7——STL基本原理和用法

1.STL的三种类型容器
顺序容器:
vector 向量容器
deque 双端队列
list 链表

容器适配器:
stack 栈
queue 队列
priority_queue 优先级队列

关联容器:
set/multiset 集合
map/multimap 映射表

2.各容器的底层实现
具体实现请参考侯捷的《STL源码剖析》,此处不贴源码,只是对底层实现做简单介绍。

顺序容器:
<1>vector 向量容器

vector底层是动态开辟的可2倍自增长的一维数组,默认不申请空间。
第一次向vector中增加元素时,开辟一个格子,以后如果内存不足,每次扩大2倍。因此,这种数据结构在刚开始内存增长时的效率很低。vector底层内存连续

<2>deque 双端队列容器

deque底层时动态开辟的一维可2倍自增长的二维数组,默认部申请空间。deque底层内存不连续

第一次向deque中增加元素时,一维开辟两个格子,二维开辟的元素个数遵守以下规则:如果变量的类型<4096,开辟4096/sizeof(_Ty)个格子;否则开辟一个格子,格子大小为sizeof(_Ty)。size=sizeof(_Ty) < 4096 ? 4096/sizeof(_Ty) : sizeof(_Ty);

因为是双端队列,所以底层有两个指针(_start和_finish)。_start和_finish都向最中间。头插时,_start向上移动,尾插时,_finish向下移动。二维数组不够用时,再开辟二维空间。如果二维已经开辟满了,则一维成2倍增长(cur *= 2),并将二维空间移动到新的一维空间的最中间,减少push_front和push_back时,开辟内存和移动的次数(pos = cur/2 -1)。

<3>list
list的底层是双向链表。对list的操作就是对链表的操作,所以list容器的添加和修改效率很高。list默认分配一个头节点,在插入值的时候,动态的申请节点,挂在链表中。

容器适配器:
容器适配器底层没有自己的数据结构,他们是对某种容器的代理。

<1>stack默认的底层数据结构是deque
<2>queue默认的底层结构是queue
<3>priority_queue默认的底层结构是用vector实现的大根堆

关联容器:
关联容器的底层是RBtree,key有序排列。对关联容器的操作都是对红黑树的操作。插入元素时,最多调整2次;删除元素时,最多调整3次。

set/multiset只保存key,set中key不能重复,multiset中key可以重复
map/multimap保存的是key-value,map中key不能重复,multimap中key可以重复

Boost库中实现了hash_map和multimap,是用链地址法实现的哈希表,链表的每个元素保存的都是键值对。

3.各类型容器的操作接口函数

<1>vector
定义:vector vec;
插入:vec.push_back(value); vec.insert(it, value);
删除:vec.erase(it); vec.erase(vec.begin(), vec.end());
获取首元素:vector::itreator it = vec.begin();
vector末尾后一个元素:vector::iterator it = vec.end();
迭代器运算:it++; it–; ++it; –it;

vector的reserver方法和resize的区别:
vec.reserver(size);//只开辟内存
vec.resize(size);//开辟空间并构建size个对象

C++总结7——STL基本原理和用法_第1张图片

<2>deque
定义:deque dq;
插入:dq.push_front(value); dq.push_back(value); dq.insert(it,value);
删除:dq.erase(it); dq.erase(dq.begin(), dq.end());
获取首元素:deque::itreator it = dq.begin();
deque末尾后一个元素:deque:;iterator it = dq.end();
迭代器运算:it++; it–; ++it; –it;

<3>list
定义:list list1;
插入:list1.push_front(value); list1.push_front(value); list1.insert(it, value);
删除:list1.erase(it); list1.erase(list1.begin(), list2.end());
切片函数:list.splice(list.begin(), list.end(), list2, list2.end());
//将list1从begin到end的节点都拼接到list2的最后面

<4>stack
定义:stack st;
添加元素:st.push(value);
获取栈顶元素:st.top();
删除栈顶元素:st.pop();
判断栈是否空:st.empty();
求栈的元素个数:st.size();

<5>queue
定义:queue qu;
添加元素:qu.push(value);
获取队列首元素:qu.front();
获取队列尾元素:qu.back();
删除对头元素:qu.pop();
判断队列是否空:qu.empty();
求队列元素个数:qu.size();

<6>priority_queue
定义:priority_queue> queue; 大根堆
priority_queue, greater> queue; 小根堆
添加元素:queue.push(value);
获取首元素:queue.top();
删除首元素:queue.pop();
判断队列是否空:queue.empty();
求队列的元素个数:queue.size();

<7>set/multiset
定义:set myset;
插入:myset.insert(key);
删除:myset.erase(it); myset.erase(key);
查找:myset.find(key);

<8>map/multimap
定义:map mymap;
插入:mymap.insert(makepair(key, value));
mymap[key] = value;
删除:mymap.erase(it); mymap.erase(key);
访问:map ::iterator it = mymap.begin();
cout

4.泛型算法
需要头文件#include

常用泛型算法:
find(vec.begin(), vec.end(), value);
find_if(vec.begin(), vec.end(), bind1st(greater(), num));

sort(vec.begin(), vec.end()); 即:sort(vec.begin(), vec.end(), less());//从小到大
sort(vec.begin(), vec.end(), greater);//从大到小

copy(vec1.begin(), vec1.end(), back_inserter(vec2));
copy(vec1.begin(), vec1.end(), inserter(vec2, vec2.end()));

unique(it.begin(), it.end()); ///删除相邻重复的元素,实则是将重复的元素挪到后面,返回值是指向重复的第一个元素的迭代器

5.STL和泛型算法的实际应用

#include 
#include 
#include 
#include 
#include 
using namespace std;

int main()
{
    //默认构造一个int vector vec;
    vector<int> vec;

    //随机添加10个1-100整数
    for(int i=0;i<10; ++i)
    {
        vec.push_back(rand()%100+1);
    }

    //从小到大排序
    sort(vec.begin(), vec.end());

    //打印容器
    vector<int>::iterator it1;
    for(it1=vec.begin(); it1!=vec.end(); ++it1)
    {
        cout<<*it1<<" ";
    }
    cout<//从大到小排序
    sort(vec.begin(), vec.end(), greater<int>());

    //打印容器
    for(it1=vec.begin(); it1!=vec.end(); ++it1)
    {
        cout<<*it1<<" ";
    }
    cout<//找到第一个小于50的数字,并打印出来,并删除掉
    vector<int>::iterator it2 = find_if(vec.begin(), vec.end(), bind1st(greater<int>(), 50));
    cout<<*it2<//找容器里面有没有60这个元素,找到的话打印出来,没找到打印失败信息
    vector<int>::iterator it3 = find(vec.begin(), vec.end(), 60);
    if(it3 == vec.end())
    {
        cout<<"don't find 60"<else
    {
        vec.erase(it3);
    }

    //生成一个新的vector容器
    vector<int> vec2;

    //把vec1容器里面的所有元素拷贝到新容器当中
    copy(vec2.begin(), vec2.end(), vec.begin());

    //打印新容器
    vector<int>::iterator it4;
    for(it4=vec.begin(); it4!=vec.end(); ++it4)
    {
        cout<<*it4<<" ";
    }

    cout<//清空旧容器里面所有的元素
    vec.clear();

    return 0;
}

C++总结7——STL基本原理和用法_第2张图片

#include 
#include 
#include 
#include 
#include 
using namespace std;

int main()
{
    //新建一个vector int实例化,默认构造
    vector<int> vec;

    //随机100个0-10之间的数字
    for(int i=0; i<100; ++i)
    {
        vec.push_back(rand()%10);
    }

    vector<int>::iterator it1;
    for(it1=vec.begin(); it1!=vec.end(); ++it1)
    {
        cout<<*it1<<" ";
    }
    cout<//给容器去重复的数字
    sort(vec.begin(), vec.end());
    vector<int>::iterator it2 = unique(vec.begin(), vec.end());

    for(it1=vec.begin(); it1!=it2; ++it1)
    {
        cout<<*it1<<" ";
    }
    cout<return 0;
}

C++总结7——STL基本原理和用法_第3张图片

6.迭代器

迭代器的类型:
<1>正向迭代器 iterator
<2>逆向迭代器 reserver_oterator
<3>插入型迭代器
back_insert_iterator /back_inserter push_back(value)
front_insert_iterator /front_inserter push_front(value)
isert_iterator /inserter insert(it,value)

插入型迭代器的使用

#include 
#include 
#include 
#include 
#include 
using namespace std;

int main()
{
    vector<int> v1;
    vector<int> v2;
    vector<int> v3;

    for(int i=0;i<10;++i)
    {
        v1.push_back(i);
    }

    for(int i=0;i<10;++i)
    {
        v2.push_back(i+10);
    }

    for(int i=0;i<10;++i)
    {
        v3.push_back(i+20);
    }

    copy(v2.begin(), v2.end(),back_inserter(v1));

    vector<int>::iterator it1 = v1.begin();
    for(; it1!=v1.end(); ++it1)
    {
        cout<<*it1<<" ";
    }
    cout<for(it1 = v1.begin(); it1!=v1.end(); ++it1)
    {
        cout<<*it1<<" ";
    }
    cout<return 0;
}

这里写图片描述

<4>流迭代器
istream_iterator
ostream_iterator

#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;


int main()
{
    set<int> myset;
    copy(istream_iterator<int>(cin), 
         istream_iterator<int>(), 
         inserter(myset, myset.begin()));
    copy(myset.begin(), myset.end(), 
         ostream_iterator<int>(cout, " "));
 }

C++总结7——STL基本原理和用法_第4张图片

你可能感兴趣的:(C/C++)