C++学习 --- STL常用容器之list容器

6、list 容器

6.1、list基本概念

功能:将数据进行链式存储

链表(list)是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的 。

链表的组成链表由一些列节点组成

节点的组成:是一个存储数据元素的数据域,另一个是存储下一个节点地址的指针域

优点:可以对任意位置进行快速插入删除元素。不需要移动大量元素。

采用动态存储分配不会造成内存浪费和溢出。

缺点:容器的遍历速度(不能跳跃访问)没有数组快。时间耗费比较大。

占用的空间(数据域和指针域)比数组大

STL中的链表是一个双向循环链表。

 

由于链表的存储方式并不是连续的内存空间,因此链表list中的迭代器只支持前移和后移,属于双向迭代器

List 重要性质,插入操作和删除操作都不会造成原有list迭代器的失效,这在vector是不成立的。(vector 一旦内存不够,需要重新开辟新的空间,迭代器的位置将改变)

STL中List和vector是两个最常被使用的容器,各有优缺点。

6.2、list构造函数
功能描述:
  • 创建list容器

函数原型

  • list<T> lst; //list采用模板类实现,对象的默认构造形式

  • list(beg,end); //构造函数将[beg,end)区间中的元素拷贝给本身

  • list(n,elem); //构造函数将n个elem拷贝给本身

  • list(const list &lst);//拷贝构造函数

#include <iostream>
#include <list>
using namespace std;
​
/*
list<T> lst;          //list采用模板类实现,对象的默认构造形式
list(beg,end);        //构造函数将[beg,end)区间中的元素拷贝给本身
list(n,elem);         //构造函数将n个elem拷贝给本身
list(const list &lst);//拷贝构造函数
*/
//list 容器构造函数
void printList(const list<int> &L) {
    for (list<int>::const_iterator it = L.begin(); it != L.end(); it++) {
        cout << *it << " ";
    }
    cout << endl;
}
​
​
void test01() {
    //创建list容器
    list<int> L1;
​
    //添加数据
    L1.push_back(10);
    L1.push_back(20);
    L1.push_back(30);
    L1.push_back(40);
    
    //遍历容器
    printList(L1);
​
    //区间的方式构造
    list<int> L2(L1.begin(),L1.end());
    printList(L2);
​
    //拷贝构造的方式
    list<int> L3(L2);
    printList(L3);
​
    //n个elem
    list<int> L4(10,1000);
    printList(L4);
}
​
int main() {
    test01();
​
    system("pause");
    return 0;
}

总结:list构造方式同其他几个STL常用容器基本一样

6.3、list赋值和交换
功能描述:
  • 给list容器进行赋值,以及交换list容器

函数原型:
  • assign(beg,end); //将[beg,end)区间中的数据拷贝赋值给本身

  • assign(n,elem); //将n个elem拷贝赋值给本身

  • list& operator=(const list &lst); //重载等号操作符 swap(lst); //将lst与本身的元素互换

#include <iostream>
#include <list>
using namespace std;
/*
assign(beg,end);                  //将[beg,end)区间中的数据拷贝赋值给本身
assign(n,elem);                   //将n个elem拷贝赋值给本身
list& operator=(const list &lst); //重载等号操作符
swap(lst);                        //将lst与本身的元素互换
*/void printList(const list<int> &L) {
    for (list<int>::const_iterator it = L.begin(); it != L.end(); it++) {
        cout << *it << " ";
    }
    cout << endl;
}
​
void test01() {
    list<int> L1;
    L1.push_back(10);
    L1.push_back(20);
    L1.push_back(30);
    L1.push_back(40);
    printList(L1);
​
    list<int> L2;
    L2 = L1;
    printList(L2);
​
    list<int> L3;
    L3.assign(L2.begin(),L2.end());
    printList(L3);
​
    list<int> L4;
    L4.assign(10,1000);
    printList(L4);
}
​
//交换
void test02() {
    list<int> L1;
    L1.push_back(10);
    L1.push_back(20);
    L1.push_back(30);
    L1.push_back(40);
​
    list<int> L2;
    L2.assign(10, 100);
​
    cout << "交换前:" << endl;
    printList(L1);
    printList(L2);
​
    L1.swap(L2);
​
    cout << "交换后:" << endl;
    printList(L1);
    printList(L2);
}
​
int main() {
    test01();
    test02();
​
    system("pause");
    return 0;
}
6.4、list大小操作

#include <iostream>
#include <list>
using namespace std;
​
/*
size();     //返回容器中元素的个数
empty();    //判断容器是否为空
resize(num);      //重新指定容器的长度为num,容容器变长,则以默认值0填充新位置。
    //若容器变短,则末尾超出容器长度的元素被删除
resize(num,elem); //重新指定容器的长度为num,若容器变长,则以elem值填充新位置。
    //若容器变短,则末尾超出容器长度的元素被删除
*/void printList(const list<int> &L) {
    for (list<int>::const_iterator it = L.begin(); it != L.end(); it++) {
        cout << *it << " ";
    }
    cout << endl;
}
​
void test01() {
    list<int> L1;
    L1.push_back(10);
    L1.push_back(20);
    L1.push_back(30);
    L1.push_back(40);
​
    printList(L1);
​
    //判断容器是否为空
    if (L1.empty()) {
        cout << "L1为空" << endl;
    }
    else {
        cout << "L1不为空" << endl;
        cout << "L1的元素个数是:" << L1.size() << endl;
    }
​
    //重新指定大小,默认用0 填充
    L1.resize(10);
    printList(L1);
​
    //重新指定大小,按指定的值填充
    L1.resize(11,100);
    printList(L1);
​
    //重新指定大小,多余的部分被删除
    L1.resize(2);
    printList(L1);
}
​
int main() {
    test01();
​
    system("pause");
    return 0;
}
6.5、list插入和删除

#include <iostream>
#include <list>
using namespace std;
​
/*
push_back(elem);    //在容器尾部加入一个元素
pop_back();         //删除容器中最后一个元素
push_front(elem);   //在容器开头插入一个元素
pop_front();        //从容器开头移除第一个元素
insert(pos,elem);   //在pos位置插elem元素的拷贝,返回新数据的位置
insert(pos,n,elem); //在pos位置插入n个elem数据,无返回值
insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值
clear();        //移除容器的所有数据
erase(beg,end); //删除[beg,end)区间的数据,返回下一个数据的位置
erase(pos);     //删除pos位置的数据,返回下一个数据的位置
remove(elem);   //删除容器中所有与elem值匹配的元素
*/void printList(const list<int> &L) {
    for (list<int>::const_iterator it = L.begin(); it != L.end(); it++) {
        cout << *it << " ";
    }
    cout << endl;
}
​
void test01() {
    list<int> L1;
    //尾插
    L1.push_back(10);
    L1.push_back(20);
    L1.push_back(30);
    
    //头插
    L1.push_front(100);
    L1.push_front(200);
    L1.push_front(300);
    //300 200 100 10 20 30      
    printList(L1);
​
    //尾删
    L1.pop_back();  
    //300 200 100 10 20 
    printList(L1);
​
    //头删
    L1.pop_front();
    //200 100 10 20
    printList(L1);
​
    //insert插入
    list<int>::iterator it = L1.begin();
    L1.insert(++it,1000);
    // 200 1000 100 10 20
    printList(L1);
​
    //删除
    it = L1.begin();
    L1.erase(++it);
    // 200 100 10 20
    printList(L1);
​
    //移除
    L1.push_back(200);
    //200 100 10 20 200
    printList(L1);
    L1.remove(200);
    //100 10 20
    printList(L1);
​
    //清空
    L1.clear();
    printList(L1);
}
​
int main() {
    test01();
​
    system("pause");
    return 0;
}
6.6、list数据存取

list 不一定是用连续的线性空间存储数据,所以不能用at和 []的方式访问容器中的元素。

迭代器也不支持随机(跳跃式 it = it+1)访问,可以移动(it++,it--)访问。

#include <iostream>
#include <list>
using namespace std;
​
/*
front(); //返回第一个元素
back();  //返回最后一个元素
*///list容器中的数据存取
void printList(const list<int> &L) {
    for (list<int>::const_iterator it = L.begin(); it != L.end(); it++) {
        cout << *it << " ";
    }
    cout << endl;
}
​
void test01() {
    list<int> L1;
    //尾插
    L1.push_back(10);
    L1.push_back(20);
    L1.push_back(30);
    L1.push_back(40);
    
    cout << "第一个元素为:" << L1.front() << endl;
    cout << "最后一个元素为:" << L1.back() << endl;
​
    //L1[0] 不可以用[]访问list容器中的元素
    //L1.at(0) 不可以用at的方式访问list容器中的元素
    //原因是list本质链表,不是用连续性空间存储数据,迭代器也是不支持随机访问的
//验证迭代器是不支持随机访问的
    list<int>::iterator it = L1.begin();
    //支持双向
    it++; //向后
    it--; //向前
    //it = it + 1; //不支持随机访问
}
​
int main() {
    test01();
​
    system("pause");
    return 0;
}
6.7、list反转和排序

#include <iostream>
#include <list>
using namespace std;
​
/*
reverse(); //反转链表
sort();    //链表排序
*///list反转和排序
void printList(const list<int> &L) {
    for (list<int>::const_iterator it = L.begin(); it != L.end(); it++) {
        cout << *it << " ";
    }
    cout << endl;
}
​
void test01() {
    list<int> L1;
    //尾插
    L1.push_back(10);
    L1.push_back(20);
    L1.push_back(30);
    L1.push_back(40);
    printList(L1);
​
    //反转
    L1.reverse();
    printList(L1);
}
​
//回调函数
bool myCompare(int v1,int v2) {
    //降序 就让第一个数 > 第二个数
    return v1 > v2;
}
​
void test02() {
    list<int> L1;
    //尾插
    L1.push_back(40);
    L1.push_back(80);
    L1.push_back(30);
    L1.push_back(10);
​
    //排序
    cout << "排序前:" << endl;
    printList(L1);
    //所有不支持随机访问迭代器的容器不支持用标准算法
    //sort(L1.begin(),L1.end());
    //而容器内部会提供相应的算法
//默认排序规则 升序
    L1.sort();
    cout << "排序后:" << endl;
    printList(L1);
​
    //降序的写法 仿函数或回调函数
    L1.sort(myCompare);
    printList(L1);
}
​
int main() {
    test01();
    test02();
    system("pause");
    return 0;
}
6.8、排序案例

#include <list>
#include <string>
#include <iostream>
using namespace std;
​
/*
    list 容器 排序案例 对于自定义数据类型 做排序
    按照年龄进行升序,如果年龄相同按照身高进行降序
*/class Person {
public:
    Person(string name, int age, int height) {
        this->m_Name = name;
        this->m_Age = age;
        this->m_Height = height;
    }
    string m_Name;//姓名
    int m_Age;//年龄
    int m_Height; //身高
​
};
​
void ptintList(const list<Person> &L) {
    for (list<Person>::const_iterator it = L.begin(); it != L.end(); it++) {
        cout << "姓名:" << it->m_Name <<
            " 年龄:" << it->m_Age <<
            " 身高:" << it->m_Height << endl;
    }
}
​
//回调函数,指定排序规则
bool comparePerson(Person &p1,Person &p2) {
    //年龄相同
    if (p1.m_Age == p2.m_Age) 
        //按照身高降序
        return p1.m_Height > p2.m_Height;       
    else
        return p1.m_Age < p2.m_Age;
}
​
void test01() {
    list<Person> L;
    //准备数据
    Person p1("刘备",35,175);
    Person p2("曹操",45,180);
    Person p3("孙权",45,170);
    Person p4("赵云",25,190);
    Person p5("张飞",35,160);
    Person p6("关羽",35,200);
​
    //尾插
    L.push_back(p1);
    L.push_back(p2);
    L.push_back(p3);
    L.push_back(p4);
    L.push_back(p5);
    L.push_back(p6);
​
    ptintList(L);
​
    //排序后
    cout << endl << "排序后:" << endl;
    //自定义数据类型排序需要指定规则,写回调函数或者是仿函数
    L.sort(comparePerson);
    ptintList(L);
}
​
int main() {
    test01();
    system("pause");
    return 0;
}

 

 

 

posted @ 2021-10-12 18:36  yiwenzhang  阅读(152)  评论(0编辑  收藏  举报