STL容器(1)

1 pair

1)pair的定义和结构

在C++中,pair是一个模板类,用于表示一对值的组合。

它位于<utility>头文件中。

pair类的定义如下:

template<class T1,class T2>

struct pair {

T1 first;//第一个值

T2 second;//第二个值

//构造函数

pair();

pair( const T1& x, const T2& y);

//比较运算符重载

bool operator==(const pair& rhs) const;

bool operator!=(const pair& rhs) const;

//其他成员函数和特性

...

};

pair类模板有两个模板参数, T1和T2,分别表示第一个值和第二个值的类型。

pair类有两个成员变量,first和lsecond,分别表示第一个值和第二个值。

pair类还有一些成员函数和特性例如默认构造函数、带参数的构造函数、比较运算符重载等。

使用pair类,你可以方便地将两个值组合在一起,并进行传递、存储和操作。

例如,可以将两个整数组合在一起作为函数的返回值,或者将一对值存储在容器中。

例1.1下面是一些使用pair的示例

#include <iostream>

#include <utility>

int main()

{

        std::pair<int,double> p1(1,3.14);

        std::pair<char,std::string> p2('a',"hello");

        std::cout <<p1.first <<"," <<p1.second <<std::endl;

        std::cout<<p2.first <<"," <<p2.second <<std::endl;

        return 0;

}

以上代码创建了两个pair对象,分别包含不同类型的值。

然后,通过访问first和second成员变量,输出了这些值。

2)pair的嵌套

pair可以进行嵌套,也就是说可以将一个pair对象作为另一个pair对象的成员。通过嵌套pair,你可以方便地组合多个值,并形成更复杂的数据结构。

例如,你可以创建一个三维坐标系的点,其中第1个维度由一个整数表示,第2、3个维度由一个pair表示。

例1.2 下面是一个示例代码,演示了如何嵌套使用pair

#include <iostream>

#include <utility>

int main()

{

        std::pair<int,int> p1(1,2);

        std::pair<int,std::pair<int,int>> p2(3,std::make_pair(4,5));

        std::pair<std::pair<int,int>,std::pair<int,int>> p3(std::make_pair(6,7),std::make_pair(8,9));

        std::cout<<p1.first<<","<<p1.second<<std::endl;

        std::cout<<p2.first<<","<<p2.second.first <<","<< p2.second.second <<std::endl;

        std::cout<<p3.first.first<<","<<p3.first.second<<","<<p3.second.first <<","<<p3.second.second<<std::endl;

        return 0;

}

在这个示例中,我们创建了三个pair对象: p1、p2和p3。

p1是一个简单的pair,包含两个整数值。

p2是一个嵌套的pair,其中第一个值是一个整数,第二个值是一个pair,其中包含两个整数值。

p3是一个嵌套的pair,其中每个值都是一个pair,每个pair包含两个整数值。

通过访问嵌套的pair对象的成员变量,我们可以获取到相应的值。

3)pair自带排序规则

pair自带的排序规则是按照first成员进行升序排序。

如果first成员相等,则按照second成员进行升序排序。

这意味着当你使用标准库中的排序算法(如std::sort)对包含pair对象的容器进行排序时,会根据pair对象的first成员进行排序。

例1.3 下面是一个示例代码,演示了如何使用pair进行排序

#include <iostream>

#include <utility>

#include <vector>

#include <algorithm>



int main()

{

        std::vector<std::pair<int, int>> vec;

        vec.push_back(std::make_pair(3,2));

        vec.push_back(std::make_pair(1,4));

        vec.push_back(std::make_pair(2,1));

        std::sort(vec.begin(),vec.end());

        for(const auto& p:vec)

        {

                std::cout<<p.first<< "," <<p.second<<std::endl;

        }

        return 0;

}

在这个示例中,我们创建了一个存储pair对象的向量vec,其中包含三个pair对象。

然后,我们使用stdsort函数对vec进行排序。由于pair对象的排序规则是按照first成员进行升序排序,

所以排序后的结果是:

1,4

2,1

3,2

最后,我们通过遍历vec并输出每个pair对象的成员,验证了排序结果。

需要注意的是,如果你想按照其他排序规则对pair进行排序,可以自定义比较函数或使用lambda表达式来传递给排序算法。这样,你可以根据自己的需求定义排序规则。

例1.4 代码示例

#include <iostream>

#include <utility>

#include <vector>

//定义一个结构体,表示一个人的信息

struct Person{

        std::string name;

        int age;

};

int main()

{

        //创建一个存储Person对象的向量

        std::vector<Person> people;

        //添加一些Person对象到向量中

        people.push_back({"Alice",25});

        people.push_back({"Bob",30});

        people.push_back({"Charlie",20});

        //创建一个存储pain的向量,每个pair包含一个Person对象和一个评分

        std::vector<std::pair<Person,int>> scores;

        //添加一些pair到向量中

        scores.push_back({people[0],9});

        scores.push_back({people[1],85});

        scores.push_back({people[2],95});

        //遍历pair向量,并输出每个人的姓名、年龄和评分

        for(const auto pair:scores)

        {

                std::cout<<"Name:"<< pair.first.name<<std::endl;

                std::cout<<"Age:"<< pair.first.age<< std::endl;

                std::cout<<"Score:"<<pair.second<<std::endl;

                std::cout<<std::endl;

        }

        return 0;

}

2 vector

1)vector的定义和特性

在C++中, vector是一个动态数组容器,可以存储一系列相同类型的元素。

它是标准库<vector>中定义的模板类。

vector的定义和结构非常简单,它由以下几个重要的部分组成:

模板类声明: vector是一个模板类,因此在使用之前需要包含头文件<vector>。

声明一个vector对象的通用语法如下:

std::vector<T> vec;

这里的T是要存储在vector中的元素类型。

容器大小:vector是一个动态数组,可以根据需要自动调整大小。

它会根据元素的数量动态分配内存空间。

元素访问:可以通过索引来访问vector中的元素。索引从0开始,最后一个元素的索引是size()-1,可以使用[]运算符或at()函数来访问元素。

元素添加和删除:可以使用push_back()函数在vector的末尾添加元素,使用pop_back()函数删除末尾的元素。还可以使用insert()函数在指定位置插人元素,使用erase()函数删除指定位置的元素.

容器大小管理:可以使用size()函数获取vector中元素的数量,使用empty()函数检查vector是否为空。还可以使用resize()函数调整vector的大小。

迭代器:vector提供了迭代器,可以用于遍历容器中的元素。可以使用begin()函数获取指向第一个元素的迭代器,使用end()函数获取指向最后一个元素之后位置的迭代器。

2)vector的常用函数

push back():将元素添加到vector的末尾。

void push_back( const T& value);



pop_back():删除vector末尾的元素.

void pop_back();  //一定保证vector非空



begin()和end():返回指向vector第一个元素和最后一个元素之后位置的迭代器。

iterator begin();

const_iterator begin() const;

iterator end();

const_iterator end() const;

例2.1

#include <iostream>

#include <utility>

#include <vector>

int main()

{

        std::vector<int> vec = {10,20,30};

        for (auto it=vec.begin();it!=vec.end();++it){ //迭代器不能比较,只有相等或不等

        std::cout<<*it<<" ";

        }

        return 0;

}

3)vector排序去重

排序:

要对vector进行排序,可以使用标准库中的std:sort函数。

该函数位于头文件<algorithm>中。

#include <algorithm>

std::vector<T> vec={...};

std::sort(vec.begin(),vec.end());

这里的T是vector中元素的类型。

std:sort函数接受两个迭代器参数,表示要排序的范围。

vec.begin()返回指向vector第一个元素的迭代器

vec.end()返回指向最后一个元素之后位置的迭代器。

例2.2

#include <iostream>

#include <vector>

#include <algorithm>

int main()

{

        std::vector<int> vec = {5,2,8,1,9};

        std::sort(vec.begin(),vec.end());

        for(const auto& num:vec)

        {

                std::cout<<num<<" ";

        }

        return 0;

}

去重:

要去除vector中的重复元素,可以使用std:unique函数。

该函数位于头文件<algorithm>中。

#include <algorithm>

std::vector<T> vec={...};

std::sort(vec.begin(),vec.end());

auto last=std::unique(vec.begin(),vec.end());

vec.erase(last,vec.end());

首先,需要对vector进行排序,以便相同的元素相邻。

然后,std::unique函数将重复的元素移动到vector的末尾,并返回一个指向重复元素的迭代器。

最后,可以使用vec.erase函数将重复元素从vector中删除。

例2.3

#include <iostream>

#include <vector>

#include <algorithm>

int main()

{

        std::vector<int> vec = {2,1,3,2,4,1,5,4};

        std::sort(vec.begin(),vec.end());

        auto last=std::unique(vec.begin(),vec.end());

        vec.erase(last,vec.end());

        for(const auto& num:vec)

        {

                std::cout<<num<<"";

        }

        return 0;

}

这样,vector中的重复元素被去除,只保留了不重复的元素。

例2.4

#include <iostream>

#include <vector>

#include <algorithm>

int main() {

        //创建一个空的std::vector对象

        std::vector<int> numbers;

        //向向量中添加元素

        numbers.push_back(5);

        numbers.push_back(2);

        numbers.push_back(8);

        numbers.push_back(5);

        numbers.push_back(1);

        numbers.push_back(2);

        numbers.push_back(9);

        numbers.push_back(8);

        //打印向量中的元素

        std::cout<<"原始向量中的元素:";

        for(const auto& number:numbers) {

                std::cout<<number<<" ";

        }

        std::cout<<std::endl;

       

        //对向量进行排序

        std::sort(numbers.begin(), numbers.end());

        //打印排序后的向量

        std::cout<<"排序后的向量:";

        for(const auto& number:numbers) {

                std::cout<<number<<" ";

        }

        std::cout<<std::endl;

       

        //去除重复元素

        numbers.erase(std::unique(numbers.begin(),numbers.end()),numbers.end());

        //打印去重后的向量

        std::cout<<"去重后的向量:";

        for(const auto& number:numbers) {

                std::cout<<number<<" ";

        }

        std::cout<<std::endl;

        //向向量中插入元素

        numbers.insert(numbers.begin()+2,3);

        //打印插入元素后的向量

        std::cout<<"插入元素后的向量:";

        for(const auto& number:numbers) {

                std::cout<<number<< " ";

        }

        std::cout<<std::endl;

        //删除向量中的某个元素

        numbers.erase(numbers.begin() +4);

        std::cout <<"删除元素后的向量:";

        for (const auto& number:numbers) {

                std::cout<<number<<"";

        }

        std::cout<<std::endl;

        //检查向量是否为空

        if(numbers.empty()){

        std:: cout<<"向量为空"<<std::endl;}

        else {

        std::cout<<"向量不为空"<< std::endl;

        }

        //获取向量的大小

        std::cout <<"向量的大小:"<<numbers.size()<<std::endl;

        //清空向量

        numbers.clear();

        //检查向量是否为空

        if(numbers.empty()) {

        std::cout<<"向量为空"<<std::endl;}

        else{

        std::cout<<"向量不为空"<<std::endl;

        }

        return 0;

}

3 list

1)list的定义和结构

list的使用频率不高,在做题时极少遇到需要使用list的情景。

list是一种双向链表容器,它是标准模板库(STL)_提供的一种序列容器。

list容器以节点(node)的形式存储元素,并使用指针将这些节点链接在一起,形成一个链表结构。

list容器结构如下:

list容器的定义和结构如下:

template <class T,class Allocator = std::allocator<T>>

class list;

list容器模板接受两个参数:

1.T:指定容器中存储的元素类型。

2.Allocator(可选):指定用于分配内存的分配器类型,默认为std::allocator<T>。表示怎么分配内存,可以不管。

list容器的特点包括:

·双向性:每个节点都包含指向前一个节点和后一个节点的指针,因此可以在常数时间内在链表中的任意位置(要记录地址)进行插入、删除和访问操作。

·动态大小:链表的大小可以根据需要动态扩展或收缩,不需要预先指定容器的大小。

·不连续存储:链表中的节点可以在内存中的任意位置分布,不要求连续存储,因此插入和删除操作不会导致元素的移动。

list容器提供了一系列成员函数和迭代器来操作和访问链表中的元素,包括插入、删除、访问、反转等操作。可以使用迭代器来遍历链表中的元素。

例3.1 展示如何使用list容器:

#include <iostream>

#include <list>

int main(){

        std::list<int> myList;

        //在链表尾部插入元素

        myList.push_back(1);

        myList.push_back(2);

        myList.push_back(3);

        //在链表头部插入元素

        myList.push_front(0);

        //遍历链表并输出元素

        for (int num:myList){  //可迭代容器中元素的遍历

        std::cout<<num<<" ";

        }

        std::cout<<std::endl;

        return 0;

}

在上述示例中,我们首先创建了一个list容器myList,然后使用push_back()和push_front()函数分别在链表尾部和头部插入元素。最后,使用范围基于范围的for循环遍历链表并输出元素。

需要注意的是,由于list是双向链表,因此插入和删除操作的时间复杂度是常量时间O(1),但访问和查找操作的时间复杂度是线性时间O(n),其中n是链表的大小。

因此,如果需要频繁进行随机访问操作,可能更适合使用支持随机访问的容器,如vector或deque(双端队列)。

2)list的常用函数

list容器提供了多个常用的成员函数来操作和访问链表中的元素。

以下是一些常用的list函数的解释:

push back():将元素插入到链表的末尾。

push front():将元素插人到链表的开头。//双向

pop_back():移除链表末尾的元素。

pop_front():移除链表开头的元素。

size():返回链表中元素的个数。

empty():检查链表是否为空。

clear():清空链表中的所有元素。

front():返回链表中第一个元素的引用。//引用可以直接修改元素

back():返回链表中最后一个元素的引用。

begin():返回指向链表第一个元素的迭代器。

end():返回指向链表末尾的下一个位置的迭代器。

insert():在指定位置之前插入一个或多个元素。

erase():从链表中移除指定位置的一个或多个元素。

例3.2

#include <iostream>

#include <list>

#include <algorithm>

using namespace std;

int main(){

        //创建一个list<int>对象myList

        list<int> mylist;

        //向mylist尾部添加元素

        for(int i=1;i<=5;++i){

        mylist.push_back(i);

        }

        //从头到尾输出myList中的元亲

        for(const auto &i:mylist)cout<<i<<' ';

        cout<<'\n';

        //将mylist中元素反转

        reverse(mylist.begin(),mylist.end());

        for(const auto &i:mylist)cout<<i<<' ';

        cout<<'\n';

        //在第一个元素的后一个位置加上元素0

        mylist.insert(++mylist.begin(),0);

        for(const auto &i:mylist)cout<<i<<' ';

        cout<<'\n';

       

        mylist.erase(++ ++mylist.begin(),--mylist.end());

        //输出myList的大小

        cout<<"链表大小为:" <<mylist.size()<<'\n';

        //从头到尾输出myList中的元素

        for(const auto &i:mylist)cout<<i<<' ';

        cout<<'\n';

        return 0;

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值