【C++】链表(list)的使用以及与vector的区别

这篇具有很好参考价值的文章主要介绍了【C++】链表(list)的使用以及与vector的区别。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、list 简介

在 C++ 中,std::list 是标准库提供的一个容器类,用于将数据进行链式存储。链表(list)是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的。

  • 链表的组成:链表由一系列结点组成。
  • 结点的组成:1.存储数据元素的数据域 2.存储下一个结点地址的指针域

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


二、std::list 与 std::vector的区别

  1. 底层实现:

    • list 是由双向链表实现的,每个元素包含指向前一个和后一个元素的指针。这种实现使得在列表中的任意位置插入和删除元素都是高效的,但对于随机访问元素的性能较差。
    • vector 是由动态数组实现的,元素在内存中是连续存储的。这种实现使得随机访问元素的性能非常好,但在中间或开头插入/删除元素时会涉及元素的移动,性能相对较低。
  2. 动态调整大小:

    • list 的大小可以动态增长和缩小,因为它使用链表来存储元素,插入和删除操作的性能与列表的大小无关。
    • vector 的大小也可以动态增长,但在需要重新分配内存时,可能会导致大量的元素复制和内存重分配操作。
  3. 访问效率:

    • list 不支持随机访问,只能通过迭代器进行顺序访问。对于需要频繁插入和删除操作的场景,list 的性能更好。
    • vector 支持随机访问,可以通过下标直接访问元素。对于需要频繁的随机访问操作,vector 的性能更好。
  4. 内存占用:

    • list 在存储元素时,除了元素本身的值外,还需要额外的空间存储指向前一个和后一个元素的指针。因此,它通常比 vector 使用更多的内存。
    • vector 在存储元素时,只需要存储元素的值本身和一些额外的控制信息,因此通常比 list 使用更少的内存。
  5. 插入和删除操作:

    • list 对于在任意位置插入和删除元素来说是高效的,因为它只需要修改相邻元素的指针即可,不需要移动其他元素。list 有一个重要的性质,插入操作和删除操作都不会造成原有list迭代器的失效,这在vector中是不成立的。
    • vector 对于在末尾插入和删除元素来说是高效的,因为它只需要在数组的末尾进行操作,不需要移动其他元素。但在中间或开头插入/删除元素时,需要移动其他元素。

综上所述,选择使用 list 还是 vector 取决于具体的应用场景和需求。如果需要频繁的插入和删除操作,并且不需要频繁的随机访问元素,可以选择 list。如果需要频繁的随机访问元素,而插入和删除操作较少,可以选择 vector。另外,如果需要在容器的中间位置进行插入和删除操作,并且对访问效率要求不高,可以考虑使用 list


三、list 构造函数

构造函数原型 解释
1 list<T> lt 默认构造函数, 采用模板类实现
2 list(lt.begin(), lt.end()) 将lt[begin, end)区间中的元素拷贝给本身
3 list(n, Element) 构造函数将n个Element(元素)拷贝给本身
4 list(const list &lt) 拷贝构造函数

示例:

#include <iostream>
#include <list>     //必须包含该头文件
using namespace std;

void printVec(list<int> &v)
{
	for (list<int>::iterator At = v.begin(); At != v.end(); At++)
	{
		cout << *At << " ";
	}
	cout << endl;
}
void printVec(list<double> &v)
{
	for (list<double>::iterator At = v.begin(); At != v.end(); At++)
	{
		cout << *At << " ";
	}
	cout << endl;
}

void test01()
{
	list<int> v1;
	v1.push_back(10);  //添加元素
	v1.push_back(20);
	printVec(v1);

	list<int> v2(v1.begin(), v1.end());
	printVec(v2);

	list<double> v3(5, 6.32);
	printVec(v3);

	list<double> v4(v3);
	printVec(v4);
}

int main()
{
	test01();
	system("pause");
	return 0;
}
//result
10 20
10 20
6.32 6.32 6.32 6.32 6.32
6.32 6.32 6.32 6.32 6.32

注意:

list 作为函数的参数或者返回值时,不能缺少其中的“&”。


四、list 赋值

函数原型: = 、assign 解释
1 list& operator=(const list &lt) 重载=操作符
2 assign(begin, end) 将[begin, end)区间中的数据拷贝赋值给本身
3 assign(n, Element) 将n个Element拷贝赋值给本身

示例:

#include <iostream>
#include <list>     //必须包含该头文件
using namespace std;

void printVec(list<int> &v)
{
	for (list<int>::iterator At = v.begin(); At != v.end(); At++)
	{
		cout << *At << " ";
	}
	cout << endl;
}

void test01()
{
	list<int> v1;
	v1.push_back(10);  //添加元素
	v1.push_back(20);
	printVec(v1);

	list<int> v2 = v1;
	printVec(v2);

	list<int> v3;
	v3.assign(v1.begin(), v1.end());
	printVec(v3);

	list<int> v4;
	v4.assign(6, 1);
	printVec(v4);
}

int main()
{
	test01();
	system("pause");
	return 0;
}
//result
10 20
10 20
10 20
1 1 1 1 1 1

五、list 长度操作

函数原型:empty、size、resize 解释
1 empty() 判断容器是否为空
2 size() 返回容器中元素的个数
3 resize(int num) 重新指定容器的长度为num。若容器变长,则以默认值填充新位置; 如果容器变短,则末尾超出容器长度的元素被删除
4 resize(int num, Element) 重新指定容器的长度为num。若容器变长,则以Element值填充新位置; 如果容器变短,则末尾超出容器长度的元素被删除

示例:

#include <iostream>
#include <list>     //必须包含该头文件
using namespace std;

void printVec(list<int> &v)
{
	for (list<int>::iterator At = v.begin(); At != v.end(); At++)
	{
		cout << *At << " ";
	}
	cout << endl;
}

void test01()
{
	list<int> v1;
	if (v1.empty())     //判断是否为空
	{
		cout << "当前v1为空!" << endl;
	}

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

	if (!v1.empty())
	{
		cout << "v1中元素个数:" << v1.size() << endl;
		printVec(v1);
	}

	v1.resize(5);
	printVec(v1);

	v1.resize(10, 1);
	printVec(v1);
}

int main()
{
	test01();
	system("pause");
	return 0;
}
//result
当前v1为空!
v1中元素个数:3
10 20 30
10 20 30 0 0
10 20 30 0 0 1 1 1 1 1

六、list 插入与删除

函数原型:push_back、pop_back、insert、erase、clear 解释
1 push_back(Element) 尾部插入元素Element
2 pop_back() 删除最后一个元素
3 push_front(Element) 在容器开头插入一个元素
4 pop_front() 从容器开头移除第一个元素
5 insert(iterator p, Element) 迭代器指向位置p插入元素Element
6 insert(iterator p, int n, Element) 迭代器指向位置p插入n个元素Element
7 insert(p,iterator start, iterator end) 在p位置插入[start,end)区间的数据,无返回值
8 erase(iterator p) 删除迭代器指向的元素
9 erase(iterator start, iterator end) 删除迭代器从start到end之间的元素
10 remove(elem) 删除容器中所有与elem值匹配的元素
11 clear() 删除容器中所有元素

示例:

#include <iostream>
#include <list>     //必须包含该头文件
using namespace std;

void printVec(list<int> &v)
{
	for (list<int>::iterator At = v.begin(); At != v.end(); At++)
	{
		cout << *At << " ";
	}
	cout << endl;
}

void test01()
{
	list<int> v1;
	v1.push_back(1);  //尾部添加元素
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(3);
	cout << "尾部添加元素: " << endl;
	printVec(v1);

	v1.pop_back();    //尾部删除元素
	cout << "尾部删除元素: " << endl;
	printVec(v1);

	v1.push_front(100);  //头部添加元素
	v1.push_front(200);
	v1.push_front(300);
	cout << "头部添加元素: " << endl;
	printVec(v1);

	v1.pop_front();   //头部删除元素
	v1.pop_front();
	cout << "头部删除元素: " << endl;
	printVec(v1);

	v1.insert(v1.begin(), 100);      //插入元素100
	cout << "插入元素100: " << endl;
	printVec(v1);

	v1.insert(v1.begin(), 5, 100);   //插入5个元素100
	cout << "插入5个元素100: " << endl;
	printVec(v1);

	v1.erase(v1.begin());    //删除元素
	cout << "删除元素v1.begin(): " << endl;
	printVec(v1);

	v1.remove(100);
	cout << "删除所有100元素: " << endl;
	printVec(v1);

	v1.clear();				 //清空容器
	printVec(v1);
}

int main()
{
	test01();
	system("pause");
	return 0;
}
//result
尾部添加元素:
1 2 3 3
尾部删除元素:
1 2 3
头部添加元素:
300 200 100 1 2 3
头部删除元素:
100 1 2 3
插入元素100:
100 100 1 2 3
插入5个元素100:
100 100 100 100 100 100 100 1 2 3
删除元素v1.begin():
100 100 100 100 100 100 1 2 3
删除所有100元素:
1 2 3

七、list 数据获取

函数原型:front()、back 解释
1 front() 返回容器中第一个数据元素
2 back() 返回容器中最后一个数据元素

示例:

#include <iostream>
#include <list>     //必须包含该头文件
using namespace std;

void test01()
{
	list<int> v1 = { 1, 2, 3, 4, 5, 6 };
	cout << "v1.front() = " << v1.front() << endl;
	cout << "v1.back() = " << v1.back() << endl;
}

int main()
{
	test01();
	system("pause");
	return 0;
}
//result
v1.front() = 1
v1.back() = 6

八、list 互换、反转、排序

函数原型:swap、reverse、sort 解释
1 swap(list lt) 将lt中元素与本身的元素互换
2 reverse() 反转链表
3 sort() 链表排序

示例:

#include <iostream>
#include <list>     //必须包含该头文件
using namespace std;

void printVec(list<int> &v)
{
	for (list<int>::iterator At = v.begin(); At != v.end(); At++)
	{
		cout << *At << " ";
	}
	cout << endl;
}

void test01()
{
	list<int> v1 = { 9, 5, 7, 8, 6 };
	list<int> v2 = { 5, 4, 3, 2, 1 };

	v1.swap(v2);   //互换v1与v2中的元素
	cout << "list v1 : " ;
	printVec(v1);
	cout << "list v2 : " ;
	printVec(v2);

	v2.sort();  //链表排序
	cout << "v2链表排序 : ";
	printVec(v2);

	v2.reverse();  //反转链表v2
	cout << "v2反转链表 : ";
	printVec(v2);
}

int main()
{
	test01();
	system("pause");
	return 0;
}
//result
list v1 : 5 4 3 2 1
list v2 : 9 5 7 8 6
v2链表排序 : 5 6 7 8 9
v2反转链表 : 9 8 7 6 5

如果这篇文章对你有所帮助,渴望获得你的一个点赞!

c++ list和vector区别,C++,容器,c++,链表,list文章来源地址https://www.toymoban.com/news/detail-741854.html

到了这里,关于【C++】链表(list)的使用以及与vector的区别的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C++】反向迭代器的模拟实现通用(可运用于vector,string,list等模拟容器)

    🌏博客主页: 主页 🔖系列专栏: C++ ❤️感谢大家点赞👍收藏⭐评论✍️ 😍期待与大家一起进步! 我们要写出一个通用的反向迭代器模拟而且在保证代码简介不繁琐的的情况下,一定程度上使用我们自己模拟的已经封装好的iterator迭代器可以简化许多步骤,首先我们要知

    2024年02月14日
    浏览(56)
  • 【C++】容器篇(一)—— vector 的基本概述以及模拟实现

    前言: 在之前,我们已经对 string类进行了基本的概述,并且手动的实现了string类中常用的接口函数。本期,我将带领大家学习的是STL库中的一个容器 -- vector 的学习。相比于之前的string类,本期的 vector 相对来说实现起来略微难一点,难点就在于要考虑关于 “ 迭代器失效 ”

    2024年02月07日
    浏览(45)
  • 【C++ STL容器】:vector存放数据以及存放自定义的数据类型

    时不可以苟遇,道不可以虚行。 STL 中最常用的容器为: vector ,暂且把它理解为我们之前学过的数组 Array 。 添加头文件: #include vector 利用内置函数: push_back() 先声明两个迭代器, 一个指向容器中的第一元素 , 一个指向容器中的最后一个元素的下一个位置 然后利用一层

    2024年02月15日
    浏览(55)
  • 【C++】容器篇(二)——List的基本概述以及模拟实现

    前言: 在上期,我们学习了STL库中的第一个容器--vector ,今天我将给大家介绍的是 库中的另外一个容器--List。其实,有了之前学习 vector 的知识,对于List 的学习成本就很低了。 目录 (一)基本介绍 1、基本概念 2、list 与 forward_list 的比较 3、特点 (二)list的使用 1、list的

    2024年02月06日
    浏览(45)
  • list和vector容器的插入与访问操作区别

    std::list 和 std::vector 是C++中的两种常见数据结构,它们在不同的使用场景下各有优势。 std::vector 的内部实现是动态数组,它在连续的内存块中存储数据。这使得 std::vector 在 访问元素时具有非常高的效率,因为可以直接通过索引来访问元素,时间复杂度为O(1) 。然而, std::ve

    2024年02月13日
    浏览(44)
  • C++中vector、list和deque的选择:什么时候使用它们?

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 在C++中,vector、list和deque是STL(标准模板库)提供的三种常见的容器。每种容器都有其特点和适用场景。本文将详

    2024年02月13日
    浏览(39)
  • C++:vector使用以及模拟实现

    和我们原来讲的string不同, vector并不是类,是一个类模板,加类型实例化以后才是类。 vector是表示 可变大小数组 的序列容器。 像数组一样 ,vector也采用的连续存储空间来存储元素,但是容量可以动态改变。 和其它容器相比,vector访问元素、尾插、尾删较高效,但不在尾部

    2024年02月11日
    浏览(43)
  • 【C++庖丁解牛】STL之vector容器的介绍及使用 | vector迭代器的使用 | vector空间增长问题

    🍁你好,我是 RO-BERRY 📗 致力于C、C++、数据结构、TCP/IP、数据库等等一系列知识 🎄感谢你的陪伴与支持 ,故事既有了开头,就要画上一个完美的句号,让我们一起加油 vector的文档介绍 vector是表示可变大小数组的序列容器。 就像数组一样,vector也采用的连续存储空间来存

    2024年03月14日
    浏览(79)
  • 【数据结构与算法】C++的STL模板(迭代器iterator、容器vector、队列queue、集合set、映射map)以及算法例题

    更多算法例题链接: 【数据结构与算法】递推法和递归法解题(递归递推算法典型例题) 什么是迭代器(iterator) 迭代器(iterator)的定义: 迭代器是一种检查容器内元素并遍历元素的数据类型。 迭代器提供对一个容器中的对象的访问方法,并且定义了容器中对象的范围。 容器

    2024年04月14日
    浏览(50)
  • 【C++】vector的使用 以及 迭代器失效问题

    前言 经过前面string的学习,我们已经掌握了许多string的类函数,vector中许多类函数与string中的类函数使用起来相似,例如迭代器的使用在所有的容器中使用都一样,这里我们不再介绍,下面我们学习一些vector类的一些常用的函数。 1.vector的文档介绍 2. vector在C++中表示可变大

    2023年04月24日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包