Linux C++的list的使用总结

一、概述

list就是C++封装好的双链表,本文主要是记录其具体的使用方法,包括需要包含的头文件,如何定义,每一个成员函数的使用方法。最后以一个demo来展示如何使用list的方法。要使用list,需要包含#include

二、定义

    list<int> b;                   //创建一个空的list
    list<int> c(5);                //声明一个n个元素的列表,每个元素都是0
    list<int> d(n, m);             //声明一个n个元素的列表,每个元素都是m
    list<int>e(d.begin(),d.end()); //声明一个列表,其元素的初始值来源于由区间所指定的序列中的元素,first和last是迭代器,如他们分别是另外一个list的迭代器。
    list<int>f(e);                 //拷贝另一个list
    list<Mytype>g;                 //声明一个自定义类型的list

三、成员函数

3.1 返回迭代器类的函数

iterator begin();   //返回指向第一个元素的迭代器 
iterator end()    //返回末尾的迭代器
const reverse_iterator rbegin() //返回指向第一个元素的逆向迭代器
const reverse_iterator rend()   //指向list末尾的逆向迭代器

理解上面几个成员函数的用法,其实一张图就搞定:
list双链表迭代器
我们用遍历list时候,用到迭代器,存在一个正向遍历和逆向遍历问题,这4个成员函数就是返回不同位置的迭代器。
例如我们遍历list:

list<int> test;
for (list<int>::iterator it =test.begin(); it != test.end();){
	cout<<*it<<endl;
	it++;
}

逆向遍历:

list<int> test;
for (list<int>::reverse_iterator it =test.rbegin(); it != test.rend();){
	cout<<*it<<endl;
	it++;
}

3.2 list的容量相关的成员函数

bool empty ( ) const; //判断list是否为空,若为空返回true
size_type size() const;  //返回list个数
size_type max_size () const;  //返回list最大容量
void resize ( size_type sz, T c = T())//重新分配lsit的大小。

前面三个都比较好理解,这里重点说下第四个:
如果sz小于目前的size就将多余的值删除;如果sz大于目前的size,就在增加容量,且用c填充。T指的是当前list的类型.

list<int> test;
test.push_back(1);
test.push_back(2);
test.resize(1);        //将size定为1,会删除list中的2
test.resize(5,20);  //将size定为5,多出的用20填充

3.3 获取list中元素

reference front() noexcept//返回第一个元素,可以对该元素进行读写
const_reference front() noexcept//返回第一个元素,只读
reference back ( );//返回最后一个元素,可以对该元素进行读写
const_reference back ( ) const

3.4 操作list相关函数

void assign ( InputIterator first, InputIterator last );//根据迭代器,重新给list分配空间,并赋值
void assign ( size_type n, const T& u) // 分配n个空间,并赋值相同的元素u
void push_front(value_type&& __x);//从头插入一个元素
void push_back(value_type&& __x);//从尾插入一个元素
iterator insert ( iterator position, const T& x );//在position位置处插入元素x
void insert ( iterator position, size_type n, const T& x );//在position位置处开始插入n个x
template <class InputIterator>
void insert ( iterator position, InputIterator first, InputIterator last );//在position之后,插入迭代器fir--last范围的元素
iterator erase ( iterator position );//清除链表中position 处元素
iterator erase ( iterator first, iterator last );//清除链表中[first,last)范围内的元素
void swap ( list<T,Allocator>& lst);//交换两个list
void clear();//清空list
void splice ( iterator position, list<T,Allocator>& x );//将list x中的所有元素插入到调用该函数的position处。List x会被清空。可以理解为将list x插入到调用该函数的position位置
void splice ( iterator position, list<T,Allocator>& x, iterator i );//将x中指向i的位置处的元素插入到list2的position处。X会将i位置处的值删除。
void splice ( iterator position, list<T,Allocator>& x, iterator first, iterator last ); //将x中[first,last)位置处的元素插入到list2的position处,插入范围的list元素会被删除。
void remove ( const T& value );//清除list中的某个元素
template <class Predicate>
void remove_if ( Predicate pred );//在满足Predicate pred返回true值时,移除元素。pred可以是一个返回bool类型的函数,还可以是一个重写operator函数的类
void unique ( );//清除相同元素
template <class BinaryPredicate>
void unique ( BinaryPredicate binary_pred );按照规则binary_pred消除重复值。
void merge ( list<T,Allocator>& x );
template <class Compare>
void merge ( list<T,Allocator>& x, Compare comp );
void sort ( );
template <class Compare>
void sort ( Compare comp );
reverse()//将list中的元素逆置。

至此,列出了所有list成员函数的定义,上面大部分函数从后面的解释,基本能明确其用法,但后面几个会比较晦涩难以理解,即:remove_if,unique,merge,sort四个成员函数。下面会主要对上面一些不太好理解的函数做详细的解释和使用demo说明:
(1) assign的使用:
功能:重新给list分配空间,并赋值。
(1)void assign ( InputIterator first, InputIterator last );//根据迭代器,重新给list分配空间,并赋值
(2)void assign ( size_type n, const T& u) // 分配n个空间,并赋值相同的元素u

list<int> test;
list<int> test2;
list<int> test3;
test.push_back(1);
test.push_back(2);
test3.push_front(2);
test2.assign(test.begin(),test.end());//用法1
for (list<int>::iterator it =test2.begin(); it != test2.end();){
    cout<<*it<<endl;
    it++;
}
test2.assign(5,4);//用法2
for (list<int>::iterator it =test2.begin(); it != test2.end();){
    cout<<*it<<endl;
    it++;
}

上面这段demo还包含了push_back和push_front的使用。
(2)insert()的使用:
(1)iterator insert ( iterator position, const T& x );//在position位置处插入元素x
(2)void insert ( iterator position, size_type n, const T& x );//在position位置处开始插入n个x
(3)template
void insert ( iterator position, InputIterator first, InputIterator last );//在position之
功能:从字面意思来看,就是忘list中特定位置插入元素,实施也是如此。

iterator insert ( iterator position, const T& x );//在position位置处插入元素x
void insert ( iterator position, size_type n, const T& x );//在position位置处开始插入n个x
template <class InputIterator>
void insert ( iterator position, InputIterator first, InputIterator last );//在position之后,插入迭代器fir--last范围的元素

使用demo:

list<int>::iterator it2 =test2.begin();
list<int>::iterator it1 =test1.begin();
test1.insert(it1,0);//方式1
test1.insert(it1,5,0);//方式2
test2.insert(it2,test1.begin(),test1.end());//方式2

这里只贴出了关键的代码,详细的代码可以在我上传的文件中得到,这里给出文件链接:
传送门
(3) remove_if
(1)void remove ( const T& value );//清除list中的某个元素
(2)template
void remove_if ( Predicate pred );//在满足Predicate pred返回true值时,移除元素。pred可以是一个返
功能:删除符合自定义规则的元素。该函数实际上是遍历整个list,一一比较每个元素,若元素符合删除的规则,就删除,所以说,我们需要自定义符合删除规则的函数:

struct Student{
    int age;
    string name;
};
bool delete_rule(const Student& student)
{
    return student.age <= 12;
}
int main(){
    list<Student> test1;
    Student temp;
    temp.age = 11;
    temp.name = "张三";
    test1.push_back(temp);
    temp.age = 12;
    temp.name = "王五";
    test1.push_back(temp);
    temp.age = 13;
    temp.name = "李四";
    test1.emplace_back(temp);//c++11新增的函数,提升效率,如果编译不过,可以换成push_back;
    for (list<Student>::iterator it =test1.begin(); it != test1.end();){
        cout<<"name:"<<(*it).name<<"age: "<<(*it).age<<endl;
        it++;
    }
    cout<<endl;
    test1.remove_if(delete_rule);
    for (list<Student>::iterator it =test1.begin(); it != test1.end();){
        cout<<"name:"<<(*it).name<<"age: "<<(*it).age<<endl;
        it++;
    }
}

这里我们根据自己定义的规则删除掉所有年龄小于12的学生。

(4)unique
(1)void unique ( );//清除相同元素
(2)template
void unique ( BinaryPredicate binary_pred );按照规则binary_pred消除重复值。
功能:删除列表中重复的元素,unique会遍历整个list,并对比相邻的元素是否重复。当然“重复”是 可以自定义的,也就是说我们可以自定义所谓重复的规则,如下面这个例子:
有了remove_if的经验,理解unique会容易很多。
注意:再执行unique之前,要先进行排序,因为该函数是对比相邻两个元素是否“重复”;

#include <iostream>
#include <cmath>
#include <list>
// a binary predicate implemented as a function:
bool my_type (double first, double second)
{ return ( int(first)==int(second) ); }

// a binary predicate implemented as a class:
struct is_near {
  bool operator() (double first, double second)
  { return (fabs(first-second)<5.0); }
};
int main ()
{
    double mydoubles[]={ 12.15,  2.72, 73.0,  12.77,  3.14,
                       12.77, 73.35, 72.25, 15.3,  72.25 };
    std::list<double> mylist (mydoubles,mydoubles+10);
    mylist.sort();             //  2.72,  3.14, 12.15, 12.77, 12.77,
                             // 15.3,  72.25, 72.25, 73.0,  73.35
    cout<<"before unique of type1:";
    for (std::list<double>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
    std::cout << ' ' << *it;
    std::cout <<std::endl;
    mylist.unique();           //  2.72,  3.14, 12.15, 12.77
                             // 15.3,  72.25, 73.0,  73.35
    cout<<"after unique of type1:";
    for (std::list<double>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
        std::cout << ' ' << *it;
    cout<<endl;
    mylist.unique (my_type);  //  2.72,  3.14, 12.15
                            // 15.3,  72.25, 73.0
    cout<<"after unique of type2:";
    for (std::list<double>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
        std::cout << ' ' << *it;
    cout<<endl;
    mylist.unique (is_near());           //  2.72, 12.15, 72.25
    cout<<"after unique of type3:";
    for (std::list<double>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
        std::cout << ' ' << *it;
    cout<<endl;
    std::cout << "mylist contains:";
    for (std::list<double>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
        std::cout << ' ' << *it;
    cout<<endl;


    return 0;
}

上面这段demo使用了三种去除重复方式。
(6)merge
(1)void merge ( list<T,Allocator>& x );
(2)template
void merge ( list<T,Allocator>& x, Compare comp );
功能:合并其他list到当前list

void merge ( list<T,Allocator>& x );
template <class Compare>
void merge ( list<T,Allocator>& x, Compare comp );

demo:

#include <iostream>
#include <list>

// compare only integral part:
bool mycomparison (double first, double second)
{ return ( int(first)<int(second) ); }

int main ()
{
    std::list<double> first, second;
    first.push_back (3.1);
    first.push_back (2.2);
    first.push_back (2.9);
    second.push_back (3.7);
    second.push_back (7.1);
    second.push_back (1.4);
    first.sort();
    std::cout << "first sort:";
    for (std::list<double>::iterator it=first.begin(); it!=first.end(); ++it)
        std::cout << ' ' << *it;
    cout<<endl;
    second.sort();
    std::cout << "second sort:";
    for (std::list<double>::iterator it=second.begin(); it!=second.end(); ++it)
        std::cout << ' ' << *it;
    cout<<endl;
    first.merge(second);
    // (second is now empty)
    std::cout << "after merge the  first is:";
    for (std::list<double>::iterator it=first.begin(); it!=first.end(); ++it)
        std::cout << ' ' << *it;
    cout<<endl;
    std::cout << "after merge the  second is:";
    for (std::list<double>::iterator it=second.begin(); it!=second.end(); ++it)
        std::cout << ' ' << *it;
    cout<<endl;
    second.push_back (2.1);
    first.merge(second,mycomparison);
    std::cout << "after merge  type2 the  first is::";
    for (std::list<double>::iterator it=first.begin(); it!=first.end(); ++it)
        std::cout << ' ' << *it;
    std::cout << '\n';
  return 0;
}

运行结果:
first sort: 2.2 2.9 3.1
second sort: 1.4 3.7 7.1
after merge the first is: 1.4 2.2 2.9 3.1 3.7 7.1
after merge the second is:
after merge type2 the first is:: 1.4 2.2 2.9 2.1 3.1 3.7 7.1
从结果来看,merge自动给合并完的list排序了,默认是比较大小,在合适位置插入,但这个所谓的合适位置,其实也是我们可以自定义的,上述demo即自定义了规则:mycomparison:即当整数位小于,才插入。可以看到,新插入的数据是在3.1之前插入,因为待插入的数据是2.1,它只比较整数位。

(7)sort
(1)void sort();
(2)template
void sort (Compare comp);
功能:给list排序,默认是使用升序排序。我们也可以自定义比较的规则:

struct Student{
    int age;
    string name;
    bool operator < (Student& b) {
       return age < b.age;
    }
 // 重新定义小于,因为默认的sort函数调用的操作符是<,所以我们只需要重载 < 就好了
};
int main(){
    std::list<Student> student;
    Student stu;
    std::list<Student>::iterator iter;
    stu.name ="李";
    stu.age = 5;
    student.push_back (stu);
    stu.name ="张";
    stu.age = 9;
    student.push_back (stu);
    stu.name ="罗";
    stu.age = 7;
    student.push_back (stu);
    stu.name ="王";
    stu.age = 25;
    student.push_back (stu);
    std::cout << "before sort the list is:";
    for (std::list<Student>::iterator it=student.begin(); it!=student.end(); ++it)
        cout<<(*it).name << ":"<<(*it).age<<endl;;
    cout<<endl;
    student.sort();
    std::cout << "after sort the list is:";
    for (std::list<Student>::iterator it=student.begin(); it!=student.end(); ++it)
        cout<<(*it).name << ":"<<(*it).age<<endl;;
    cout<<endl;

    return 0;
}

这里介绍了升序的方法,其实降序,可以直接sort()之后,使用reverse()完成。当然这样会影响速度,后续会继续介绍降序的方法。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值