目录
我也从没想过STL中的list还有这么多的花样。总而言之,如果你觉得这篇文章还不错,劳烦多多支持一下!码字不易,感谢你的观看!
前言
这个栏目是对我算法学习过程的同步记录,我也希望能够通过这个专栏加深自己对编程的理解以及帮助到更多像我一样想从零学习算法并参加竞赛的同学。在这个专栏的文章中我会结合在编程过程中遇到的各种问题并提出相应的解决方案。当然,如果屏幕前的你有更好的想法或者发现的错误也欢迎交流和指出!不喜勿喷!不喜勿喷!不喜勿喷!这章的内容比较简单。那么事不宜迟,我们马上开始吧!
一、list的定义与结构
1.竞赛中的定位
list的使用频率不高,在做题时极少遇到,因此本章内容较为浅显。但事实上链式存储结构在数据结构与算法的学习过程中是非常重要的。我们可以利用链表实现多级菜单等较为复杂的项目。感兴趣的小伙伴可以自行了解,进一步学习。
2.实质与工作机制
list是一种双向链表容器,它是STL提供的一种序列容器。list容器以节点(Node)的形式存储元素,并使用指针讲这些节点链接在一起,形成链式存储结构。
这里再简要介绍一下链表。链表有单向和双向两种。对于链式存储结构,其数据元素在计算机内部是随机存储的,只能依靠指针访问数据元素(不同于以数组为代表的顺序存储结构,其数据元素存储在相邻的物理存储单元中)。对于单向链表而言,其基本组成单位节点(Node)有两部分构成:数值域和指针域。顾名思义,数值域存储数值,指针域存储指针,指向下一个节点。而双向链表还增加了一个指针域,里面存放的指针指向前一个数据元素。以下是代码示例(C语言):
#include<stdio.h>
#include<stdlib.h>
//创建节点结构体
struct Node
{
int value;
struct Node* next;
};
//创建链表的函数(创立头结点)
struct Node* list_create()
{
struct Node* list = (struct Node*)malloc(sizeof(struct Node));//在堆空间申请"永久"内存
list->next = NULL;
return list;
}
int main()
{
struct Node* list = list_create();
struct Node a;
struct Node b;
a.value = 1;
b.value = 2;
//链接各个节点
list->next = &a;//list(表头)->a
a.next = &b; //list(表头)->a->b
//访问元素
printf("value in a = %d\n", list->next->value);
printf("value in b = %d\n", list->next->next->value);
return 0;
}
输出结果为:
value in a = 1
value in b = 2
3.有关特性
list容器的特点包括:
(1)双向性:可在常数时间内在链表的任意位置进行插入、删除和访问操作。
(2)动态大小:即不需要预先指定容器的大小。
(3)不连续存储:插入和删除元素不会导致元素的移动。
list容器提供了一系列成员函数和迭代器来操作和访问链表中的元素,包括插入、删除、访问和反转操作,可以使用迭代器来遍历链表中的元素。
4.代码示例
以下是一个示例,展示怎么使用list容器。
#include<bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
list<int> mylist;
//在链表尾部插入元素
mylist.push_back(1);
mylist.push_back(2);
mylist.push_back(3);
//在链表头部插入元素
mylist.push_front(0);
//遍历链表输出元素
for (int num : mylist)cout << num << " ";
cout << endl;
return 0;
}
输出结果为0 1 2 3
二、list的常用函数
1.常用list函数及其解释
(1)push_back():将元素插入到链表的末尾
(2)push_front():将元素插入到链表的开头
(3)pop_back():移除链表末尾的元素
(4)pop_front():移除链表开头的元素
(5)size():返回链表中元素的个数
(6)empty():检查链表是否为空
(7)clear():清空链表中的所有元素
(8)front():返回链表第一个元素的引用
(9)back():返回链表最后一个元素的引用
(10)begin():返回指向链表第一个元素的迭代器
(11)end():返回指向链表末尾下一个位置的迭代器
(12)insert():在指定位置之前插入一个或多个元素
(13)erase():从链表中移除指定位置的一个或多个元素
三、综合代码示例
代码如下所示:
#include<bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
//创建一个mylist对象
list<int> mylist;
for (int i = 0; i <= 5; ++i)mylist.push_back(i);
//从头到尾输出mylist中的元素
for (const auto& i : mylist)cout << i << " ";
cout << endl;
//将mylist中的元素反转并输出
reverse(mylist.begin(), mylist.end());
for (const auto& i : mylist)cout << i << " ";
cout << endl;
//在第一个元素的后一个位置加上元素0
mylist.insert(++mylist.begin(), 0);
for (const auto& i : mylist)cout << i << " ";
cout << endl;
mylist.erase(++++mylist.begin(), --mylist.end());
//输出mylist的大小
cout << "size = " << mylist.size() << endl;
for (const auto& i : mylist)cout << i << " ";
cout << endl;
return 0;
}
输出结果为:
0 1 2 3 4 5
5 4 3 2 1 0
5 0 4 3 2 1 0
size = 3
5 0 0