C++提高编程 3 STL常用容器 -list容器

3.7  list容器

3.7.1  list基本概念

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

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

链表的组成:链表由一系列结点组成;

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

STL中的链表是一个双向循环链表(下图中的第一个结点的prev其实不指向NULL,而是指向最后一个结点的data;而最后一个结点的next指向第一个结点的data)

 

     PS:单向链表:

 

     缺点:容器遍历速度没有数组快,因为得通过指针查找下一个元素;

        占用空间大,因为数据域占4字节,还有指针占4字节;

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

list的优点:

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

  链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素

list的缺点:

  链表灵活,但是空间(指针域)和时间(遍历)额外耗费较大

list有一个重要的性质,插入和删除操作都不会造成原有的list迭代器的失效(在元素中间插删数据并不会因为内存满了而影响前后的数据),这在vector容器中是不成立的(vector容器内存满了以后,要重新找一块更大内存的容器来存储,从而导致之前的迭代器更替);

 

总结:STL中list和vector是两个最常被使用的容器,各有优缺点

 

3.7.2  list构造函数

 

 

复制代码
#include<iostream>
#include<list>
using namespace std;

//list容器构造函数

void printList(const list<int>&L)
{
    for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
}

void test1()
{
    //创建链表list
    list<int>L1;        //默认构造

    //添加元素
    L1.push_back(10);
    L1.push_back(20);
    L1.push_back(30);
    L1.push_back(40);

    //遍历容器
    printList(L1);        //10 20 30 40

    //区间方式构造
    list<int>L2(L1.begin(), L1.end());
    printList(L2);        //10 20 30 40

    //拷贝构造
    list<int>L3(L2);
    printList(L3);        //10 20 30 40

    //n个elem
    list<int>L4(4, 100);
    printList(L4);        //100 100 100 100
};

int main()
{
    test1();

    system("pause");
    return 0;
}
复制代码

 

3.7.3  list赋值和交换

功能描述:

给list容器进行赋值,以及交换list容器

 

 

复制代码
#include<iostream>
#include<list>
using namespace std;

//list容器赋值和交换

void printList(const list<int>&L)
{
    for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
}

//赋值
void test1()
{
    //创建链表list
    list<int>L1;

    L1.push_back(10);
    L1.push_back(20);
    L1.push_back(30);
    L1.push_back(40);

    printList(L1);        //10 20 30 40

    list<int>L2;
    L2 = L1;    //operator=赋值
    printList(L2);        //10 20 30 40

    list<int>L3;
    L3.assign(L2.begin(), L2.end());
    printList(L3);        //10 20 30 40

    list<int>L4;
    L4.assign(10, 100);
    printList(L4);        //100 100 100 100 100 100 100 100 100 100
};

//交换
void test2()
{
    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);        //10 20 30 40
    printList(L2);        //100 100 100 100 100 100 100 100 100 100


    L1.swap(L2);
    cout << "交换后:" << endl;
    printList(L1);        //100 100 100 100 100 100 100 100 100 100
    printList(L2);        //10 20 30 40

}

int main()
{
    //test1();
    test2();

    system("pause");
    return 0;
}
复制代码

 

3.7.4  list大小操作

 

 

复制代码
#include<iostream>
#include<list>
using namespace std;

//list容器大小操作

void printList(const list<int>&L)
{
    for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
}

//赋值
void test1()
{
    //创建链表list
    list<int>L1;

    L1.push_back(10);
    L1.push_back(20);
    L1.push_back(30);
    L1.push_back(40);

    printList(L1);        //10 20 30 40

    //判断容器是否为空
    if (L1.empty())
    {
        cout << "L1为空" << endl;
    }
    else
    {
        cout << "L1不为空" << endl;
        cout << "L的元素个数为:" << L1.size() << endl;
    }

    //重新指定大小
    L1.resize(6);        
    printList(L1);        //10 20 30 40 0 0

    L1.resize(10, 1000);
    printList(L1);        //10 20 30 40 0 0 1000 1000 1000 1000

    L1.resize(2);
    printList(L1);        //10 20
};


int main()
{
    test1();
    

    system("pause");
    return 0;
}
复制代码

 

3.7.5  list插入与删除

对list容器进行数据的插入与删除

 

 

复制代码
#include<iostream>
#include<list>
using namespace std;

//list插入与删除

void printList(const list<int>&L)
{
    for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
}

void test1()
{
    list<int>L;

    //尾插
    L.push_back(10);
    L.push_back(20);
    L.push_back(30);

    //头插
    L.push_front(100);
    L.push_front(200);
    L.push_front(300);

    printList(L);        //300 200 100 10 20 30

    //尾删
    L.pop_back();
    printList(L);        //300 200 100 10 20

    //头删
    L.pop_front();
    printList(L);        //200 100 10 20

    //insert插入
    //L.insert(L.begin(), 1000);
    //printList(L);        //1000 200 100 10 20
    list<int>::iterator it = L.begin();
    L.insert(++it, 1000);
    printList(L);        //200 1000 100 10 20

    //删除
    it = L.begin();        //200 1000 100 10 20
    //L.erase(it);
    //printList(L);        //1000 100 10 20
    L.erase(++it);        
    printList(L);       //200 100 10 20

    //移除
    L.push_back(10000);
    L.push_back(10000);
    L.push_back(10000);
    printList(L);       //200 100 10 20 10000 10000 10000
    L.remove(10000);
    printList(L);       //200 100 10 20

    L.clear();
    printList(L);        //空白
};


int main()
{
    test1();
    

    system("pause");
    return 0;
}
复制代码

 

3.7.6 list数据存取

函数原型:

front();    //返回第一个元素

back();    //返回最后一个元素

 

复制代码
#include<iostream>
#include<list>
using namespace std;

//list数据存取void test1()
{
    list<int>L1;
    L1.push_back(10);
    L1.push_back(20);
    L1.push_back(30);
    L1.push_back(40);
    
    //L1[0];    // 不可以用[]访问list容器中的元素
    
    //L1.at(0);    // 不可以用at方式访list容器中的元素

    //原因是list本质链表,不是用连续连续线性空间存储数据,迭代器也是不支持随机访问的

    cout << "第一个元素是:" << L1.front() << endl;        //10
    cout << "最后一个元素是:" << L1.back() << endl;    //40

    //验证迭代器是不支持随机访问的
    list<int>::iterator it = L1.begin();
    it++;        //支持双向
    it--;        //如果 -- 报错,说明这个迭代器只支持向前走,是单向的
    //it = it + 1;    //不支持随机访问  因为可以+1的话,也可以+2、+3 迭代器不允许这样的操作
    //it = it - 3;

};


int main()
{
    test1();

    system("pause");
    return 0;
}
复制代码

 

 3.7.7  list反转和排序

功能描述:将list容器中的元素反转,以及将容器中的数据进行排序

函数原型:

reverse();    //反转链表

sort();      //链表排序

 

复制代码
#include<iostream>
#include<list>
using namespace std;
#include<algorithm>

//list数据存取

void printList(const list<int>&L)
{
    for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
}

void test1()
{
    list<int>L1;
    L1.push_back(50);
    L1.push_back(20);
    L1.push_back(40);
    L1.push_back(10);
    L1.push_back(30);

    cout << "反转前:" << endl;
    printList(L1);        //50 20 40 10 30

    //反转
    cout << "反转后:" << endl;
    L1.reverse();
    printList(L1);        //30 10 40 20 50

};

bool myCompare(int v1, int v2)
{
    //降序  就让第一个数 > 第二个数
    return v1 > v2;
}

//排序:
void test2()
{
    list<int>L1;
    L1.push_back(50);
    L1.push_back(20);
    L1.push_back(40);
    L1.push_back(10);
    L1.push_back(30);

    cout << "排序前:" << endl;
    printList(L1);        //50 20 40 10 30

    cout << "排序后:" << endl;
    //sort(L1.begin(), L1.end());    //所有不支持随机访问迭代器的容器,不可以使用标准算法,但内部会提供对应的一些算法
    L1.sort();            //默认排序规则  从小到大  升序
    printList(L1);        //10 20 30 40 50

    //反转
    //L1.reverse();        //50 40 30 20 10    /way1    

    L1.sort(myCompare);
    printList(L1);        //50 40 30 20 10
}

int main()
{
    //test1();
    test2();
    system("pause");
    return 0;
}
复制代码

 

3.7.8  排序案例

 

 

 

复制代码
#include<iostream>
#include<list>
using namespace std;
#include<string>

//list案例
class Person
{
public:
    Person(string name, int age,int height)
    {
        this->m_Name = name;
        this->m_Age = age;
        this->m_Height = height;
    }
public:
    string m_Name;
    int m_Age;
    int m_Height;
};

//指定排序规则
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 test1()
{
    list<Person>L;        //创建容器

    //准备数据
    Person p1("刘备", 35, 160);
    Person p2("曹操", 42, 170);
    Person p3("孙权", 39, 180);
    Person p4("赵云", 26, 179);
    Person p5("张飞", 35, 175);
    Person p6("关羽", 36, 183);

    //插入数据
    L.push_back(p1);
    L.push_back(p2);
    L.push_back(p3);
    L.push_back(p4);
    L.push_back(p5);
    L.push_back(p6);

    for (list<Person>::iterator it = L.begin(); it != L.end(); it++)
    {
        cout << "姓名:" << (*it).m_Name << "年龄:" << it->m_Age << "身高:" << (*it).m_Height << endl;
    }

    //排序
    cout << "--------------------------------" << endl;
    cout << "排序后: " << endl;

    L.sort(comparePerson);
    for (list<Person>::iterator it = L.begin(); it != L.end(); it++)
    {
        cout << "姓名:" << (*it).m_Name << "年龄:" << it->m_Age << "身高:" << (*it).m_Height << endl;
    }
}

int main()
{
    test1();
    
    system("pause");
    return 0;
}
复制代码
posted @   大白不会敲代码  阅读(69)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示