List类详解【c++】

在这里插入图片描述
博主码云
博主主页

目录

  • list简介
  • list使用
    • list构造函数
    • list迭代器
    • list capacity
    • list element access
    • list modifiers
    • list的迭代器失效
  • 总结


list简介

list是C++ STL中的一个双向链表容器,可以存储任何类型的元素。它提供了一组成员函数,可以在链表的任何位置插入和删除元素,也可以在链表的任何位置访问元素。与数组不同,list不需要连续的内存空间,因此可以动态地分配和释放内存。在插入和删除元素时,不会影响其他元素的位置,因此可以保持链表中元素的相对顺序。list支持双向迭代器,可以在正向和反向方向遍历链表。list是STL中的一个标准容器,可以在头文件中找到。它的常用操作包括创建list、插入元素、删除元素、访问元素、遍历std::list和其他常用函数等。

总的来说,list具有如下几个特性:

  • 元素按照它们在链表中的顺序存储,因此可以高效地在任何位置插入和删除元素。
  • 不支持随机访问,只能通过遍历链表来访问元素。
  • 支持双向迭代器,可以在正向和反向方向遍历链表。
  • 与数组不同,list不需要连续的内存空间,因此可以动态地分配和释放内存。
  • 在插入和删除元素时,不会影响其他元素的位置,因此可以保持链表中元素的相对顺序。

list使用

list构造函数

函数名 特性
默认构造函数:list() 该构造函数创建一个空的list对象。
拷贝构造函数:list(const list& l) 该构造函数创建一个与l相同的list对象。
带有元素数量和元素值的构造函数:list(size_type n, const value_type& val = value_type()) 该构造函数创建一个包含n个元素,每个元素的值都为val的list对象。
带有迭代器范围的构造函数:list(InputIterator first, InputIterator last) 该构造函数创建一个包含[first, last)范围内的元素的list对象。其中,first和last是迭代器,用于指定要复制到新list中的元素范围。

示例代码:

#include 
#include  
using namespace std;

void print(list<int> ls)
{
	for (auto e : ls)
	{
		cout << e << ' ';
	}
	cout << endl;
}

int main()
{
	list<int> ls;
	print(ls);
	
	list<int> ls2(10, 6);
	print(ls2);
	
	list<int> ls3(ls2);
	print(ls3);
	
	list<int> ls4(ls2.begin(), ls2.end());
	print(ls4);	
	return 0;
}

运行结果:
List类详解【c++】_第1张图片
List类详解【c++】_第2张图片

注意:

  1. 在使用带有元素数量和元素值的构造函数时,如果元素类型是自定义类型,则必须提供接受一个值的构造函数,否则会导致编译错误。
  2. 在使用带有迭代器范围的构造函数时,迭代器的类型必须与list的元素类型相同,否则会导致编译错误。

list迭代器

list提供了双向迭代器(bidirectional iterator),可以用于遍历list中的元素。list的迭代器定义在头文件中,可以使用list::iterator和list::const_iterator来表示可变和不可变的迭代器。

list的迭代器支持以下操作:

++it:将迭代器it移动到下一个元素。
–it:将迭代器it移动到上一个元素。
*it:返回迭代器it所指向的元素。
it->member:返回迭代器it所指向元素的成员member。
it == it2:比较两个迭代器是否相等。
it != it2:比较两个迭代器是否不相等。

函数声明 特性
begin()和end() 分别返回指向list首元素和尾元素下一个位置的迭代器。
rbegin()和rend() 分别返回指向list尾元素和首元素前一个位置的逆向迭代器。

示例代码:

#include 
#include  
using namespace std;

int main()
{
	string arr = "abcdefg";
	list<char> ls(arr.begin(), arr.end());
	list<char>::iterator it = ls.begin();
	list<char>::reverse_iterator rit = ls.rbegin();
	while (it != ls.end())
	{
		cout << *it << ' ';
		it++;
	}
	cout << endl;
	while (rit != ls.rend())
	{
		cout << *rit << ' ';
		rit++;
	}
	cout << endl;
	return 0;
}

运行结果:
List类详解【c++】_第3张图片

注意:

  1. list的迭代器不支持随机访问,因此不能使用it[n]来访问迭代器中的元素,也不能使用+和-运算符来移动迭代器。
  2. begin与end为正向迭代器,对迭代器执行++操作,迭代器向后移动
  3. rbegin(end)与rend(begin)为反向迭代器,对迭代器执行++操作,迭代器向前移动

list capacity

list的容量是动态变化的,因此并没有capacity()函数来返回list的容量。以下是list的容量相关函数:

函数 说明
size() 返回list中元素的数量。
max_size() 返回list最多可以容纳的元素数量,这个数量取决于系统的限制。
empty() 判断list是否为空,如果list为空,则返回true,否则返回false。

示例代码:

#include 
#include  
using namespace std;

int main()
{
	string arr = "abcdefg";
	list<char> ls(arr.begin(), arr.end());
	cout << "是否为空:" << ls.empty() << endl;
	cout << "最大存储数量:" << ls.max_size() << endl;
	cout << "当前存储数量:" << ls.size() << endl;
	return 0;
}

运行结果:
List类详解【c++】_第4张图片

注意

  1. list的容量是动态变化的,因此在插入或删除元素时,list的容量可能会发生变化。

list element access

list提供了一些用于访问元素的函数,如下

函数名 说明
front() 返回list中第一个元素的引用。
back() 返回list中最后一个元素的引用。

示例代码:

#include 
#include  
using namespace std;

int main()
{
	string arr = "abcdefg";
	list<char> ls(arr.begin(), arr.end());
	char front = ls.front();
	char back = ls.back();
	cout << front << "  " << back << endl;
	return 0;
}

运行结果:
List类详解【c++】_第5张图片

注意

  1. 当容器为空时,调用front()和back()可能导致未定义行为,因此在使用这些方法之前最好检查容器是否为空。

list modifiers

在C++中,list提供了多种操作函数来方便地对链表进行操作。其中,list中的modifiers函数主要用于修改链表中的元素,包括插入、删除和替换等操作。

以下是常用的list modifiers函数:

函数 说明
push_back 在链表的末尾插入一个元素。
push_front 在链表的头部插入一个元素。
insert 在指定位置插入一个元素。
erase 删除指定位置的元素。
clear 清空链表中的所有元素。
pop_back 删除链表末尾的元素。
pop_front 删除链表头部的元素。
swap 用于交换两个链表的内容

示例代码:

#include 
#include  
using namespace std;

template<typename T>
void Print(list<T> ls)
{
	for (const auto& e : ls)
	{
		cout << e << ' ';
	}
	cout << endl;
}

int main()
{
	list<char> ls;
	ls.push_back('A');
	ls.push_back('B');
	ls.push_back('C');
	Print(ls);

	ls.push_front('1');
	ls.push_front('2');
	ls.push_front('3');
	Print(ls);

	ls.pop_back();
	ls.pop_front();
	Print(ls);

	string arr = "abcd";
	ls.insert(ls.begin(), 'M');
	ls.insert(ls.end(), arr.begin(), arr.end());
	ls.insert(ls.begin(), 3, 'O');
	Print(ls);

	list<char> ls2(ls);
	ls.erase(ls.begin());
	Print(ls);

	ls.swap(ls2);
	Print(ls);
	Print(ls2);

	ls2.clear();
	ls.erase(ls.begin(), ls.end());
	Print(ls);
	Print(ls2);
	return 0;
}

运行结果:
List类详解【c++】_第6张图片
List类详解【c++】_第7张图片

注意:

  1. 在插入或删除元素时,要确保链表中已有足够的元素或者已经分配了足够的内存空间,否则可能会导致程序崩溃。
  2. 在使用insert函数时,需要注意插入位置的有效性,如果插入到了一个无效的位置,可能会导致程序出错。
  3. 在使用erase函数时,需要注意被删除元素的有效性,如果删除了一个无效的元素,可能会导致程序出错。
  4. 在使用clear函数时,需要注意清空链表后,链表中的所有元素都会被删除,因此需要确保不再需要这些元素的情况下才能使用该函数。
  5. swap函数只是交换了两个链表中的元素,而不是交换了它们的内存空间,因此不会对链表的容量和内存使用产生影响。

list的迭代器失效

在使用list容器时,需要注意到删除节点会导致迭代器失效的问题。因为list容器的底层实现是双向链表,当我们删除某个节点时,该节点的前后节点会重新建立连接,而被删除节点的迭代器就会失效,指向该节点的迭代器将无法访问该节点,也无法访问其后继节点。

示例代码

#include 
#include  
using namespace std;

int main()
{
	list<char> ls = {'a', 'b', 'c', 'd'};
	list<char>::iterator it = ls.begin();
	while (it != ls.end())
	{
		if (*it == 'b')
		{
			ls.erase(it);
		}
		cout << *it << ' ';
		it++;
	}
	return 0;
}

运行结果:
List类详解【c++】_第8张图片
我们可以先保存指向要删除的节点的迭代器,然后将迭代器指向下一个节点,在进行删除操作。

int main()
{
	list<char> ls = {'a', 'b', 'c', 'd'};
	list<char>::iterator it = ls.begin();
	while (it != ls.end())
	{
		if (*it == 'b')
		{
			auto tmp = it++;
			ls.erase(tmp);
		}
		else
		{
			cout << *it << ' ';
			it++;
		}
	}
	return 0;
}

另外,当我们将迭代器保存到外部使用时也会导致迭代器失效。

#include 
#include  
using namespace std;

int main() {
    std::list<int> mylist = { 1, 2, 3, 4, 5 };
    auto it = mylist.begin();

    // 将迭代器保存到外部使用
    auto outside_it = it;

    // 对list容器进行删除操作
    mylist.erase(mylist.begin());

    // 使用保存在外部的迭代器访问list容器
    std::cout << *outside_it << std::endl;

    return 0;
}

注意:

  1. 在使用迭代器遍历list容器时,不要在遍历过程中删除节点,因为删除节点会导致迭代器失效。如果需要在遍历过程中删除节点,可以先将迭代器指向下一个节点,再删除当前节点。
  2. 在使用迭代器遍历list容器时,不要将迭代器保存到容器外部使用,因为当我们对list容器进行插入或删除操作时,迭代器会失效,可能会导致程序崩溃或出现未定义行为。

总结

list是C++ STL中的一个双向链表容器,可以在任意位置高效地插入和删除元素,不需要像vector那样移动其他元素。总之,list容器是一个高效的双向链表容器,可以在任意位置高效地插入和删除元素,是一个非常实用的容器。
List类详解【c++】_第9张图片

你可能感兴趣的:(C++,list,c++,数据结构)