C++ list 使用

C++ list的使用

整理自博客:老樊Lu码 的一篇文章 和洛谷一题解里面的

list定义

List是stl实现的双向链表,与向量(vector)相比, 它允许快速的插入和删除,但是随机访问却比较慢。

使用时需要添加头文件#include

list<int>lst1;          //创建空list

list<int> lst2(5);       //创建含有5个元素的list

list<int>lst3(3,1);  //创建含有1个元素的list

list<int>lst4(lst2);    //使用lst2初始化lst4

list<int>lst5(lst2.begin(),lst2.end());  //同lst4

list常用方法

Lst1.assign() 给list赋值 
Lst1.back() 返回最后一个元素 
Lst1.begin() 返回指向第一个元素的迭代器 
Lst1.clear() 删除所有元素 
Lst1.empty() 如果list是空的则返回true 
Lst1.end() 返回末尾的迭代器 
Lst1.erase() 删除一个元素 
Lst1.front() 返回第一个元素 
Lst1.insert() 插入一个元素到list中 
Lst1.merge() 合并两个list 
Lst1.pop_back() 删除最后一个元素 
Lst1.pop_front() 删除第一个元素 
Lst1.push_back() 在list的末尾添加一个元素 
Lst1.push_front() 在list的头部添加一个元素 
Lst1.remove() 从list删除元素 
Lst1.reverse() 把list的元素倒转 
Lst1.size() 返回list中的元素个数 
Lst1.sort() 给list排序 
Lst1.unique() 删除list中重复的元素
    
下面是用得相对较少的:
		Lst1.get_allocator() 返回list的配置器 
		Lst1.max_size() 返回list能容纳的最大元素数量 
		Lst1.rbegin() 返回指向第一个元素的逆向迭代器 
		Lst1.remove_if() 按指定条件删除元素 
		Lst1.rend() 指向list末尾的逆向迭代器 
		Lst1.resize() 改变list的大小 
		Lst1.splice() 合并两个list 
		Lst1.swap() 交换两个list 

假如定义了list myList;

myList.push_front(1); //前面插入元素1
myList.push_back(2);  //后面插入元素2
//遍历
typedef list<int>::iterator Iter;
Iter itBegin = myList.begin();
Iter itEnd = myList.end();
for (; itBegin != itEnd; ++itBegin)
	printf(" %d", *itBegin);

//最原始的遍历
for ( list<int>::iterator it = myList.begin(); it != myList.end(); it++ ) {
    cout << *it << ' ';
}
迭代器的用法和指针有些像,可以用*运算符访问内部的元素,
++--运算符可以将它后移或前移一位,用==!=运算符进判断两个迭代器所指的位置是否一致。
但要注意:list的迭代器不支持it += x或it1 - it2这样的运算,也不支持<<=等运算符。

begin()成员函数返回指向头部元素的迭代器。
end()成员函数返回指向末尾位置的迭代器。这个“末尾位置”指的是最后一个元素再往后一位,
也就是说end()所指的位置不包含有效元素,它相当于一个虚设的节点。
Iter it = myList.end();
--it;
//C++11中可以直接写成it = prev(myList.end());
//这里prev是头文件<iterator>提供的函数,用于返回将某个迭代器前移一位的结果
Iter it2 = myList.insert(it, 3);
//myList的内容:1,3,2

这段代码首先定义了一个迭代器it,然后在end()的基础上左移一位,让它指向链表中最后一个元素。
insert(it, val)成员函数用于在链表中插入元素。it为该链表的一个迭代器,val为待插入的值,
插入后val位于it所指位置的前一位。返回值为一个迭代器,表示val插入到了哪个位置。

在这里插入图片描述

insert(it,6) : ↓

在这里插入图片描述

插入后it的位置是不变的, insert成功后会返回插入元素的位置的迭代器!!!

来个题目玩玩:(洛谷的题目)

题目描述

一个学校里老师要将班上N个同学排成一列,同学被编号为1∼N,他采取如下的方法:

  1. 先将1号同学安排进队列,这时队列中只有他一个人;
  2. 2−N号同学依次入列,编号为i的同学入列方式为:老师指定编号为i的同学站在编号为1∼(i−1)中某位同学(即之前已经入列的同学)的左边或右边;
  3. 从队列中去掉M(M<N)个同学,其他同学位置顺序不变。

在所有同学按照上述方法队列排列完毕后,老师想知道从左到右所有同学的编号。

输入格式

第1行为一个正整数N,表示了有N个同学。

第2−N行,第i行包含两个整数k,p,其中k为小于i的正整数,p为0或者1。若p为0,则表示将i号同学插入到k号同学的左边,p为1则表示插入到右边。

第N+1行为一个正整数M,表示去掉的同学数目。

接下来M行,每行一个正整数x,表示将x号同学从队列中移去,如果x号同学已经不在队列中则忽略这一条指令。

输出格式

1行,包含最多N个空格隔开的正整数,表示了队列从左到右所有同学的编号,行末换行且无空格。

输入输出样例

输入 #1

4
1 0
2 1
1 0
2
3
3

输出 #1

2 4 1

样例解释:

将同学2插入至同学1左边,此时队列为:

21

将同学3插入至同学2右边,此时队列为:

231

将同学4插入至同学1左边,此时队列为:

2341

将同学3从队列中移出,此时队列为:

241

同学3已经不在队列中,忽略最后一条指令

最终队列:

241

#include <iostream>
#include <cstdio>
#include <list>
using namespace std;

const int N = 1e5+5;
//给list<int>::iterator来个别名,太长了
typedef list<int>::iterator Iter;
//队列
list<int> myque;
/*
插入的话需要知道插入的位置,
这里用一个数组把所有位置给存起来,
这样插入的话就不用循环去找了
*/
Iter pos[N];
//查看删了没有的
bool book[N];

int n, m;
int main()
{
	scanf("%d", &n);
	myque.push_front(1);
	pos[1] = myque.begin();
	//插入
	int no, lr;//插入到第no号同学的左或右
	for ( int i = 2; i <= n; ++i ) {
		scanf("%d %d", &no, &lr);
		//右边
		if ( lr ) {
			Iter temp = pos[no];
			temp++;//插入的是右边,所以加加
			pos[i] = myque.insert(temp, i);
		}
		//左边
		else {
			pos[i] = myque.insert(pos[no], i);
		}
	}
	
	//删除同学
	scanf("%d", &m);
	for ( int i = 1; i <= m; ++i ) {
		scanf("%d", &no);
		//如果没有删过,那就删
		if ( !book[no] ) {
			myque.erase(pos[no]);
			//myque.remove(no);超时!!!!!!
			book[no] = true;//标记为删过了
		}
	}
	
	//打印出来
	for ( Iter it = myque.begin(); it != myque.end(); it++ ) {
    	printf("%d ", *it);
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值