悲剧的文本-STL链表详解
STL链表详解
1.基础操作
定义
list<int>l;//定义一个int类型的链表
list<int>l={......}//定义一个含有......元素的链表
list<int>l(n);//定义一个长度为n并且全部初始化为0的int型的链表
list<int>l(n,m);//定义一个长度为n并且全部初始化为m的int型的链表
插入
l.push_front();//在l的前面插入一个数据
l.push_back();//在l的后面插入一个数据
l.emplace();//在l的某个位置插入某个数据
l.emplace_front();//在l的前面插入一个数据,但是更快
l.emplace_back();//在l的后面插入一个数据,但是更快
查找
l.front();//l的第一个元素
l.back();//l的最后一个元素
l.empty();//判断l是否为空
l.size();//l的大小
删除
l.clear();//清空l
l.pop_front();//删除l的第一个元素
l.pop_back();//删除l的最后一个元素
l.remove();//删除l的指定元素(值)
l.erase();//删除l的指定元素(迭代器)
l.erase(first,last);//删除l的指定区间的元素,first,last是迭代器,不包括last
l.remove_if();//按条件删除元素
修改
l.reverse();//倒转l
其他
l.begin();//返回l第一个元素的迭代器
l.end();//返回l最后一个元素的后一个的迭代器
l.sort();//给l排序
l.rbegin();//返回l最后一个元素的迭代器(相当于l.begin()的逆操作)
l.rend();//返回l第一个元素的前一个元素的迭代器(相当于l.end()的逆操作)
l.swap();//交换两个链表
l.splice();//合并两个链表,合并后第2个为空
l.merge();//合并两个有序的链表,并保持新链表有序
具体代码实现
#include<bits/stdc++.h>
using namespace std;
int main() {
list<int>l {1,2,3,4,5};
//auto关键字是可以根据后面变量的值来自动确定数据类型,C++11之后有用(应该吧
auto first=l.begin();
auto last=l.end();
/*
first为第一个元素的迭代器
last为最后一个元素的迭代器
其类型为int指针
*/
cout<<*first<<' '<<*last;//"1 5"输出第一个和最后一个元素 (*first为解引用,表示指针对应的值)
printf("\n");
l.push_front(0);//在l开头添加一个0
l.push_back(6);//在l末尾添加一个6
for(auto p=l.begin(); p!=l.end(); p++) { //从开头遍历到结尾,注意l.end()是最后一个元素的后一个位置,所以是!=l.end();
cout<<*p<<' ';
}
//"0 1 2 3 4 5 6"
printf("\n");
auto it=l.begin();
it++;//表示第二个位置
l.emplace(it,1);//在第二个位置插入1
for(auto p=l.begin(); p!=l.end(); p++) { //从开头遍历到结尾,注意l.end()是最后一个元素的后一个位置,所以是!=l.end();
cout<<*p<<' ';
}
//"0 1 1 2 3 4 5 6"
printf("\n");
l.remove(0);//删除0
for(auto p=l.begin(); p!=l.end(); p++) { //从开头遍历到结尾,注意l.end()是最后一个元素的后一个位置,所以是!=l.end();
cout<<*p<<' ';
}
printf("\n");
auto first1=l.begin();
auto last1=l.end();
first1++;//第二个元素
last1--;//倒数第一个元素
l.erase(first1,last1);//删除第二个到倒数第二个(链表的函数的末迭代器都不包括本身)
for(auto p=l.begin(); p!=l.end(); p++) { //从开头遍历到结尾,注意l.end()是最后一个元素的后一个位置,所以是!=l.end();
cout<<*p<<' ';
}
//"1 6"
printf("\n");
printf("%d %d",l.front(),l.back());
//"1 6"
return 0;
}
2.迭代器
什么是迭代器
在看了刚刚的代码后,相信大家都会发现“迭代器”这个词语反复出现,它是什么意思呢?我们不妨先想一想静态链表。
在静态链表中我们一般会用两个数组存储(如下图)
其中的“指针域”就可以理解为迭代器,它是指向下一个数据的指针,如这个链表
其中l.begin()就是nex[0] l.end()就是nex[5]
怎么表示迭代器
在基本操作的一下函数中,有许多的参数都需要迭代器,那么我们又该如何表示?
STL链表是动态双向链表,所以迭代器在表示时,我们需要用指针来表示
指针的基本概念
指针是一个地址,指向一个数据,一般在定义时需要在原本的数据后加一个'*'
int * p
指针的输出
指针是一个地址,所以不能直接输出,我们要找到它指向的数据,就需要一个操作,这个操作就叫“解引用”
int a=13;
int * p=&a;
printf("%d",*p);
//13
了解了指针我们就可以用变量表示迭代器了
具体的定义可以用一个关键字auto表示
auto关键字是可以根据后面变量的值来自动确定数据类型,C++11之后有用(应该吧
list<int>l{1,2,3};
auto p=l.begin();
printf("%d",*p);
//1
实际应用
例:悲剧的文本
你有一个破损的键盘。键盘上所有的键都能正常工作,但有时Home键或者End键会自动按下(注意:按下home键光标会跳到一行的开头,按下end键,光标会跳到一行的结尾。你并不知道键盘存在这一问题,而是专心地打稿子,甚至连屏幕都没有打开。当你打开显示器之后,展现在你面前的是一段悲剧的文本。你的任务是打开显示器之前计算出这段悲剧的文本。
输入
包括多组数据。每组数据一行,包含不超过100000个字母、下划线、字符“[”或者“]”。其中字符“[”表示HOME键,“]”表示END键。输入结束标志为文件结束符EOF。
输出
每输入一行,对应输出的一行,即屏幕上的悲剧文本。
样例
样例输入1
This_is_a_[Beiju]_text
[[]][][]Happy_Birthday_to_Tsinghua_University
样例输出1
BeijuThis_is_a__text
Happy_Birthday_to_Tsinghua_University
\(Code\)
#include<bits/stdc++.h>
using namespace std;
list<char> l;
string s;
int main() {
auto it=l.begin();//默认指向开头
while(cin>>s) {
for(int i=0; i<s.size(); i++) {
if(s[i]=='[') {
it=l.begin();//遇到'['时指向开头
} else if(s[i]==']') {
it=l.end();//遇到']'时指向结尾
} else {
l.emplace(it,s[i]);//在 it 指向的位置(开头/结尾)插入
}
}
// for(auto p=l.begin(); p!=l.end(); p++) {
// printf("%c",*p);
// }错误代码,改了好久 T^T(新定义指针的会溢出)
for(it=l.begin();it!=l.end();it++){
printf("%c",*it);
}
l.clear();
printf("\n");
}
return 0;
}

浙公网安备 33010602011771号