【数据结构与算法】标准模板库 STL

目录

一 vector

一 实例

二 要点补充

三 拓展 二维数组

二 迭代器

一 实例

二 要点补充

三 算法

一 实例

四 理解向量的性能

一 实例

二 要点补充

五 其它 STL 容器

一 deque

1 特性

2 实例

3 常用函数总结

二 list

1 特性

2 实例

3 插入与删除

4 list 特色

三map

1 特性

2 实例

3 基本用法


一 vector

一 实例

#include<iostream>
//1 头文件:<vector>
#include<vector>
#include<string>
using namespace std;
int main() {
    //2 语法:vector<对象类型> 向量名
    vector<string> inventory;
    
    //3 使用向量成员函数:.push_back()
     /*作用:在向量最后添加一个新元素*/
    inventory.push_back("sword");
    inventory.push_back("armor");
    inventory.push_back("shield");
    
    //4.1 使用向量成员函数:.size()
     /*作用:返回向量的大小*/
    cout<<"You have "<<inventory.size()<<" items.\n";
    
    cout<<"\nYour items:\n"<<endl;
    for(size_t i = 0; i < inventory.size(); ++i)
        cout << inventory[i] << endl;
    
    inventory[0] = "battle axe";
    //4.2 使用向量成员函数:.size()
     /*可以使用下标索引*/
    cout<<inventory[0].size()<<endl;
    
    //5 使用向量成员函数:.pop_back()
     /*作用:移除向量最后一个元素*/
    inventory.pop_back();
    
    //5 使用向量成员函数:.clear()
     /*作用:移除向量全部元素*/
    inventory.clear();
    
    cout<<"You have "<<inventory.size()<<" items.\n";
    
    //5 使用向量成员函数:.empty()
     /*作用:判断向量是否为空*/
    if(inventory.empty())
        cout<<"You have nothing."<<endl;
    else
        cout<<"You have at least one item"<<endl;
}

二 要点补充

  1. 向量可以根据需要增长

  2. 声明向量的其它方法:

    //向量初始大小为 10
    vector<string> inventory1(10);
    //向量大小为 10,且全部(10个)元素都初始化为"nothing"
    vector<string> inventory2(10, "nothing");
    //新向量 inventory3 的内容与 向量 myStuff 相同
    vector<string> inventory3(myStuff);

  3. 不可以 使用下标运算符增加向量的大小

    vector<string> inventory;
    inventory[0] = "sword";//可能出错

三 拓展 二维数组

#include<iostream>
#include<vector>
using namespace std;
int main()
{
    int row = 5;
    int col = 6;
    vector<vector<int>> myVector(row);
    for (int i = 0; i < row; i++)
    {
        myVector[i].resize(col);
    }
    //输出二维数组
    for (int i = 0; i < myVector.size(); i++)
    {
        for (int j = 0; j < myVector[i].size(); j++)
        {
            cout << myVector[i][j] << "\t";
        }
        cout << endl;
    }
}

二 迭代器

一 实例

#include<iostream>
#include<string>
#include<vector>
using namespace std;
int main() {
    vector<string> inventory;
    inventory.push_back("sword");
    inventory.push_back("armor");
    inventory.push_back("shield");
    //1 语法:vector<对象类型>::iterator 迭代器名
    vector<string>::iterator myIterator;
    //2 常量迭代器:不能修改其引用的元素,但自身可以改变
    vector<string>::const_iterator iter;
    
    //3.1 使用向量成员函数:.begin()
     /*作用:其返回的迭代器引用容器中的第一个元素*/
    myIterator = inventory.begin();
    
    //4 修改向量元素的值
    *myIterator = "battle axe";
    
    //5 迭代器的解引用
    cout << "\nThe item name '" << *myIterator << "' has";
    cout << myIterator->size() << " letter in it\n" << endl;
    
    //3.2 使用向量成员函数:.insert()
     /*作用:将新元素插入至向量中给定 迭代器引用的元素 之前*/
    inventory.insert(inventory.begin() + 1, "crossbow");
    
    //3.3 使用向量成员函数:.erase()
     /*作用:移除 迭代器引用的元素*/
    inventory.erase(inventory.begin());
    
    cout << "\nYour items:\n";
    //3.4 使用向量成员函数:.end()
     /*作用:其返回向量中❤️最后一个元素之后❤️的迭代器*/
    
    //6 循环访问向量
    for (iter = inventory.begin(); iter != inventory.end(); ++iter)
        cout << *iter << endl;
}

二 要点补充

  1. 使用 push_back( ) 可能使引用向量的所有迭代器失效

  2. vector 的成员函数 end( ) 返回的迭代器指向向量最后一个元素之后,而不是最后一个元素

  3. 对向量调用 insert( ) 成员函数会使引用了插入点之后的元素的迭代器失效,对向量调用 erase( ) 成员函数同理


三 算法

一 实例

//1 头文件:<algorithm>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<vector>
#include<ctime>
using namespace std;
int main() {
    vector<int> Scores;
    Scores.push_back(7);
    Scores.push_back(8);
    Scores.push_back(1);
    Scores.push_back(6);
    vector<int>::const_iterator iter;
    int score;
    cout << "Finding score" << endl;
    cout << "Enter a score to find" << endl;
    cin >> score;
    //2.1 使用 find() 算法
    /*作用:查找目标值*/
    //语法:find(开始位置,结束位置,目标值);
    iter = find(Scores.begin(), Scores.end(), score);
    if (iter != Scores.end())
        cout << "Score found" << endl;
    else
        cout << "Score not found" << endl;
    
    //2.2 使用 random_shuffle() 算法
    /*作用:将序列中的元素进行乱序*/
    //语法:random_shuffle(开始位置,结束位置)
    srand(static_cast<unsigned int>(time(NULL)));
    random_shuffle(Scores.begin(), Scores.end());
    cout << "Your Scores:" << endl;
    for (iter = Scores.begin(); iter != Scores.end(); ++iter)   
        cout << *iter << endl;  
    
    //2.3 使用 sort() 算法
    /*作用:对序列中的元素进行升序的排列*/
    sort(Scores.begin(), Scores.end());
    cout << "Your Scores:" << endl;
    for (iter = Scores.begin(); iter != Scores.end(); ++iter)
        cout << *iter << endl;
}

四 理解向量的性能

一 实例

#include<iostream>
#include<vector>
using namespace std;
int main() {
    vector<int> scores(10, 0);
    cout << "\nScores\n";
    //使用向量成员函数 .capacity()
    /*作用:返回向量的容量*/
    cout << "Scores capacity is " << scores.capacity() << endl;//10
    cout << "Scores size is " << scores.size() << endl;//10
    scores.push_back(1);
    //使用向量成员函数 .reserve()
    /*作用:将向量的容量扩充至给定实参的大小*/
    //scores.reserve(20);
    cout << "\nScores were added\n";
    cout << "Scores capacity is " << scores.capacity() << endl;//20
    cout << "Scores size is " << scores.size() << endl;//11
}

二 要点补充

  1. 向量的容量和向量的大小(向量容纳的元素的个数)不是一个概念

  2. 使用 reserve() 将向量的容量维持在足够满足需要, 这样可以将内存的重新分配推迟到某个选定时刻发生


五 其它 STL 容器

一 deque

deque 是双向开口的连续空间

可以理解为deque是双向数组,而vector是单向的

deque在接口上和vector非常相似

1 特性

  • 头尾开放,能在头尾进行插入和删除

  • 支持随机存储

  • 在中段部分插入 删除元素的相对较慢,因为所用元素都需要移动以腾出空间

2 实例

#include<iostream>
#include<deque>
using namespace std;
​
void Show(deque<string>& Queue)
{
    //.empty()
    if (Queue.empty())
    {
        cout << "Please forget it, it has been emptied.\n";
        cout << "Now there' nothing in here.\n"
             << "But, it's good!\n" << endl;
        return;
    }
    //.size()
    if (1 == Queue.size())
    {
        cout << "All that's left is the ";
        cout << Queue[0] << endl;
        return;
    }
    //迭代器
    deque<string>::const_iterator iter;
    cout << "\nThere's something in there. Let me see.\n";
    cout << "The items have:\n";
    for (iter = Queue.begin(); iter != Queue.end(); iter++)
    {
        cout << *iter << " ";
    }
}
void useQueue()
{
    cout << "\nUse double-ended queues";
    deque<string> Queue;
    //.push_back()
    Queue.push_back("back");
    //.push_front()
    Queue.push_front("front");
    //.insert()
    Queue.insert(Queue.end() - 1, "middle");
    Show(Queue);
​
    cout << "\n\nBreak off both ended\n";
    Queue.pop_front();
    Queue.pop_back();
    Show(Queue);
​
    Queue.clear();
    Show(Queue);
}

3 常用函数总结

函数功能
operator=将 deque1 的所有元素赋值给 deque2
assign(n, element)将 n 个 element 副本赋值给 deque
assign(begin, end)将区间 [begin, end] 中的元素赋值给 deque
deque1.swap(deque2)将 deque1 和 deque2 的元素交换
swap(deque1, deque2)将 deque1 和 deque2 的元素交换,此为全局函数
insert(position, element)在迭代器 position 所指位置上插入一个 element 副本, 并返回新元素的位置
insert(position, n, element)在迭代器 position 所指位置上插入 n 个 element 副本, 无返回值
insert(position, begin, end)在迭代器 position 所指位置上插入 [beg: end) 区间 内的所有元素的副本,无返值
push_back(element)在尾部追加一个 element 副本
pop_back()删除最后一个元素(但不返回其值)
push_front(element)在头部插入一个 element 副本
pop_front()删除第一个元素(但不返回其值)
erase(position)删除迭代器 position 所指元素,返回下一个元素位置
erase(begin, end)删除区间 [beg: end) 内的所有元素,返回下一个元素位置
resize(num)将大小改为 n,如果 size() 增长了,新增元素都将从默认构造函数产生出来
resize(num, element)将大小改为 n,如果 size() 增长了,新增元素都是 element 的副本
clear()清空容器


二 list

使用一个双向链表来管理元素

1 特性

  • 不支持随机存储

  • 任何位置上,插入与删除元素都很快

  • 插入和删除元素的动作不会使其它元素的迭代器、指针、引用失效

2 实例

#include<iostream>
#include<list>
using namespace std;
​
void Show(list<string>& List)
{
    if (List.empty())
    {
        cout << "Please forget it, it has been emptied.\n";
        cout << "Now there' nothing in here.\n"
             << "But, it's good!\n" << endl;
        return;
    }
    if (1 == List.size())
    {
        cout << "\nAll that's left is the ";
        cout << List.back() << endl;
        return;
    }
    list<string>::const_iterator iter;
    cout << "\nThere's something in there. Let me see.\n";
    cout << "The items have:\n";
    for (iter = List.begin(); iter != List.end(); iter++)
    {
        cout << *iter << " ";
    }
}
bool isValue(string& temp)
{
    return (temp == "back");
}
void Init(list<string>& List)
{
    List.push_back("back");
    List.push_front("middle");
    List.insert(List.begin(), "front");
    List.push_front("front");
    List.push_back("back");
}
void useList()
{
    //use list
    list<string> List;
    Init(List);
    Show(List);
​
    List.unique();
    Show(List);
​
    List.clear();
    Init(List);
    List.remove_if(isValue);
    Show(List);
}

3 插入与删除

函数作用
list.insert(pos, elem)在迭代器pos所指位置上插入一个elem副本,并返回新元素的位置
list.insert(pos, n, elem)在迭代器pos所指位置上插入n个elem 副本,无返回值
list.insert(pos, beg, end)在迭代器pos所指位置上插入 [beg: end) 区间内的所有元素的副本,无返值
list.push_back(elem)在尾部追加一个elem副本
list.pop_back()删除最后一个元素(但不返回其值)
list.push_front(elem)在头部插入一个elem副本
list.pop_front()删除第一个元素(但不返回其值)
list.remove(val)删除所有值为val的元素
list.remove_if(op)删除所有“造成op(elem)结果为true”的元素
list.erase(pos)删除迭代器pos所指元素,返回下一个元素位置
list.erase(beg,end)删除区间 [beg: end) 内的所有元素,返回下一个元素位置
list.resize(num)将元素容量变为num。如果size()变大,则以默认构造函数构造所有新增元素
list.resize(num,elem)将元素容量变为num。如果size()变大,则以elem副本作为新增元素的初值
list.clear()删除全部元素,将整个容器清空特殊变动性操作

4 list 特色

函数作用
list.unique()如果存在若干相邻而数值相同的元素, 就删除重复元素,只留下一个
list.unique(op)如果存在若干相邻元素,都使op()的结果为true, 则删除重复元素,只留下一个
list1.splice(pos, list2)将list2内的所有元素转移到list1之内、迭代器pos之前
list1.splice(pos, list2, list2pos)将list2内的list2pos所指元素转移到 list1内的pos所指位置上(list1 和list2可相同)
list1.splice(pos,list2,list2beg,list2end)将 list2 内的[list2beg: list2end)区间内所有元素转移到 list1内的pos之前(list1和list2可相同)
list.sort()以operator< 为准则,对所有元素排序
list1.merge(list2)假设list1和list2容器都包含已排序元素, 将list2的全部元素转移到list1,并保证合并后的list仍为已排序
list1.merge(list2,op)假设list1和list2容器都包含op()原则下的已排序元素, 将list2的全部元素转移到list1,并保证合并后的list在op()原则下仍为已排序

三map

二叉树查找树

map将key/value当作元素(pair),进行管理,可根据key的排序准则自动将元素排序

1 特性

  • key/value 必须可赋值和可复制

  • 如若排序,key必须能比较

  • map根据元素key自动对元素进行排序

2 实例

#include<iostream>
#include<map>
using namespace std;
​
void useMap()
{
    map<int, double> Map;
    //存储简单易操作
    Map[0] = 9.01;
    Map[8] = 8.21;
    Map.insert(std::pair<int, double>(1, 6.22));
    {
        cout << Map[1] << endl;
    }
    cout << endl;
    map<int, double>::const_iterator iter;
    for (iter = Map.begin(); iter != Map.end(); iter++)
    {
        cout << iter->second << " ";
    }
}
int main()
{
    useMap();
    return 0;
}

3 基本用法

1 定义>排序

//#include<functional>
map<int, string, std::greater<int>> Mymap;

2 插入

//1
Mymap.insert(std::pair<int, double>(1, 3.14));
//2
Mymap.insert(map<int, double>::value_type(6, 2.333));
//3
Mymap.insert(std::make_pair(4, 8.848));

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

维他命C++

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值