C++ List知识点
List 是标准类库中的一个类,可以简单视之为双向链表,以线性列的方式管理物件集合。list 的特色是在集合的任何位置增加或删除元素都很快,但是不支持随机存取。双向链表的每个元素中都有一个指针指向后一个元素,也有一个指针指向前一个元素。
如图所示:
List与vector的区别
vector随机访问快,即下标运算;同时vector可以在尾部添加,不申请空间的情况下,非常快;缺点:不支持快速插入和删除,操作比较慢。List的内存空间是不连续的,是通过指针进行访问的,因此他的随机存取非常麻烦,没有效率,因此没有提供[ ]操做符的重载。但是它在集合的任意位置增加或删除元素都很快。
头文件
#include<iostream>
#include<list>
#include<algorithm>
using namespace std;
定义
list<结构体>ls;
list< int>ls;
list< sting>ls;
list< char>ls;
struct Node{
int a;
char c;
};
void ListDefine()
{
list<int> ls1;
list<Node> ls ;
list<char>ls2;
}
构造函数
list();
list(size_type_Count); 多个元素,均为0
list(size_type_Count, const Type&_Val); 多个指定的值
list(const_list&_Right); 用一个list初始化当前的list
list(Inputlterator _First, Inputlterator _Last ); 另一个对象中间的一段
下列用结构体构造:
struct Node{
int a;
char c;
};
void fun(Node& d)
{
cout << d.a << " " << d.c << "\n";
}
void ListConstructor()
{
list<Node> ls(3) ;//三个元素均为0
Node a1 = { 12 ,'a'};
list<Node> ls1(3, a1); //三个a1,
list<Node> ls2(ls1); // 用ls1初始化ls2
list<Node> ls3( ls1.begin(),ls1.end()); //同上
for_each(ls.begin(),ls.end(),fun);
cout << endl;
for_each(ls1.begin(),ls1.end(),fun);
cout << endl;
for_each(ls2.begin(),ls2.end(),fun);
cout << endl;
for_each(ls3.begin(),ls3.end(),fun);
cout << endl;
list <Node>::iterator ite = ls1.begin();
ite++; //不能直接ite+2,会造成位置的偏移
list<Node> ls4(ite,ls1.end()); //取ls1中间第2到最后个初始化为ls4
for_each(ls4.begin(),ls4.end(),fun);
}
输出结果:
属性
1.容量
链表不同于string,vector,不需要提前提供一定大小的空间,因其结构是链式的,可以自由的进行添加和删除。因此不存在容量的概念。
2.大小
语法:
size_type size();
语法:
void resize( size_type num, TYPE val );
语法:
bool empty();
- 如果list是空的则返回true
- empty()函数返回真(true)如果链表为空,否则返回假。
struct Node{
int a;
char c;
};
void fun(Node& d)
{
cout << d.a << " " << d.c << "\n";
}
void ListSize()
{
Node a= {12, 'a'};
list<Node> ls(3,a);
cout << ls.size() << endl;
for_each(ls.begin(),ls.end(),fun);
ls.resize(5);
cout << ls.size() << endl;
cout << ls.empty() << endl;
for_each(ls.begin(),ls.end(),fun);
}
操作
1.查
- 输出
1.输出全部- 循环,迭代器
struct Node{
int a;
char c;
};
void ListCout()
{
Node a= {12, 'a'};
list<Node> ls(3,a);
for(list<Node>::iterator ite = ls.begin(); ite != ls.end(); ite++)
{
cout << ite->a << " " << ite->c << endl;
}
}
* for_each()
2.输出单个元素
语法:
reference back();
语法:
reference front();
struct Node{
int a;
char c;
};
void ListCout()
{
Node a= {12, 'a'};
list<Node> ls(3,a);
cout << ls.back().a << " " << ls.back().c <<endl;
cout << ls.front().a << " " << ls.front().c << endl;
}
2.增
语法:
void push_back( const TYPE &val );
语法:
void push_front( const TYPE &val );
- 在list的头部添加一个元素
- push_front()函数将val连接到链表的头部。
#include<iostream>
#include<list>
#include<algorithm>
using namespace std;
struct Node{
int a;
char c;
Node(int b,char d)
{
a = b;
c = d;
}
};
void fun(Node& d)
{
cout << d.a << " " << d.c << "\n";
}
void ListAdd()
{
Node a(12, 'a');
list<Node> ls(3,a);
ls.push_front(Node (11,'b'));
ls.push_back(Node (13,'b'));
for_each(ls.begin(),ls.end(),fun);
}
int main()
{
ListAdd();
system("pause");
return 0;
}
语法:
iterator insert( iterator pos, const TYPE &val );
void insert( iterator pos, size_type num, const TYPE &val );
void insert( iterator pos, input_iterator start, input_iterator end );
- 插入一个元素到list中
- insert()插入元素val到位置pos,或者插入num个元素val到pos之前,或者插入start到end之间的元素到pos的位置。返回值是一个迭代器,指向被插入的元素。
#include<iostream>
#include<list>
#include<algorithm>
using namespace std;
struct Node{
int a;
char c;
Node(int b,char d)
{
a = b;
c = d;
}
};
void fun(Node& d)
{
cout << d.a << " " << d.c << "\n";
}
void ListAdd()
{
Node a(12, 'a');
list<Node> ls(3,a);
list<Node>::iterator ite = ls.begin();
ite++;
ite++; //第三个位置
ls.insert(ite,Node (15,'d'));
ls.insert(ite,3,Node (16,'e'));//插入三个相同的结构元素
for_each(ls.begin(),ls.end(),fun);
}
输出结果:
3.删
语法:
void pop_back();
pop_back()函数删除链表的最后一个元素
语法:
void push_front( const TYPE &val );
push_front()函数将val连接到链表的头部
语法:
iterator erase( iterator pos );
iterator erase( iterator start, iterator end );
erase()函数删除以pos指示位置的元素, 或者删除start和end之间的元素。 返回值是一个迭代器,指向最后一个被删除元素的下一个元素。
void ListDel()
{
list<Node> ls;
ls.push_back(Node(1,'a'));
ls.push_back(Node(2,'b'));
ls.push_back(Node(3,'c'));
ls.push_back(Node(4,'d'));
ls.push_back(Node(5,'e'));
ls.push_back(Node(6,'f'));
list<Node>::iterator ite = ls.begin();
ite++;
ite++; //指向第三个
ls.pop_back(); //删除最后一个
// 或ls.erase(--ls.end()); 效果一样
ls.pop_front(); //删除第一个
ls.erase(ite); //删除第三个
for_each(ls.begin(),ls.end(),fun);
}
输出结果:
语法:
void clear();
clear()函数删除list的所有元素
ls.clear();
语法:
void remove( const TYPE &val );
remove()函数删除链表中所有值为val的元素。
// 创建一个链表,元素是字母表的前10个元素
list<char> charList;
for( int i=0; i < 10; i++ )
charList.push_front( i + 65 );
// 删除所有'E'的实例
charList.remove( 'E' );
语法:
void unique();
void unique( BinPred pr );
unique()函数删除链表中所有重复的元素。如果指定pr,则使用pr来判定是否删除。
4.改
语法:
void assign( input_iterator start, input_iterator end );
void assign( size_type num, const TYPE &val );
assign()函数以迭代器start和end指示的范围为list赋值或者为list赋值num个以val为值的元素。
void ListChange()
{
list<Node> ls;
ls.push_back(Node(1,'a'));
ls.push_back(Node(2,'b'));
ls.push_back(Node(3,'c'));
ls.push_back(Node(4,'d'));
ls.push_back(Node(5,'e'));
ls.assign(3,Node(2,'b')); //将原ls改为三个 2b
list<Node> ls1;
ls1 = ls;
list<Node>::iterator ite = ls1.begin();
ite++;
ls1.assign(ite,ls1.end());
for_each(ls.begin(),ls.end(),fun);
cout << endl;
for_each(ls1.begin(),ls1.end(),fun);
}
结果:
5.其他
语法:
void swap( list &lst );
swap()函数交换lst和现链表中的元素。
list<Node> ls;
ls.push_back(Node(1,'a'));
ls.push_back(Node(2,'b'));
ls.push_back(Node(3,'c'));
ls.push_back(Node(4,'d'));
ls.push_back(Node(5,'e'));
list<Node> ls1;
ls1.push_back(Node(123,'a'));
ls1.swap(ls);
for_each(ls.begin(),ls.end(),fun);
for_each(ls1.begin(),ls1.end(),fun);
输出结果:
语法:
void reverse();
reverse()函数把list所有元素倒转
list<Node> ls;
ls.push_back(Node(1,'a'));
ls.push_back(Node(2,'b'));
ls.push_back(Node(3,'c'));
ls.push_back(Node(4,'d'));
ls.push_back(Node(5,'e'));
ls.reverse();
for_each(ls.begin(),ls.end(),fun);
输出结果:
语法:
void sort();
void sort( Comp compfunction );
sort()函数为链表排序,默认是升序。如果指定compfunction的话,就采用指定函数来判定两个元素的大小。
如果容器本身自带排序,那么使用的时候,就可以不用选择算法的排序
语法:
void merge( list &lst );
void merge( list &lst, Comp compfunction );
merge()函数把自己和lst链表连接在一起,产生一个整齐排列的组合链表。如果指定compfunction,则将指定函数作为比较的依据。
语法:
void splice( iterator pos, list &lst );
void splice( iterator pos, list &lst, iterator del );
void splice( iterator pos, list &lst, iterator start, iterator end );
splice()函数把lst连接到pos的位置。如果指定其他参数,则插入lst中del所指元素到现链表的pos上,或者用start和end指定范围。
运算符重载
Operators
语法:
v1 == v2
v1 != v2
v1 <= v2
v1 >= v2
v1 < v2
v1 > v2
若使用的是结构体的话,进行排序、合并需要重载运算符
= 赋值运算符
用到的两个算法
需要的头文件:#include < algorithm>
遍历:for_each
查找函数:
Inputlterator find( Inputlterator _First ,Inputlterator _Last,const Type& _val );
在一个容器中查找一个成员,返回这个成员的迭代器
list<int>::iterator ite = find(ls.begin(),ls.end(),3); //查找3返回给ite
cout << ite << endl;
上面的程序如下:
#include<iostream>
#include<list>
#include<algorithm>
using namespace std;
struct Node{
int a;
char c;
};
void fun(Node& d)
{
cout << d.a << " " << d.c << "\n";
}
//定义
void ListDefine()
{
//list<int> ls1;
list<Node> ls(3) ;//三个元素均为0
for_each(ls.begin(),ls.end(),fun);
}
//构造函数
void ListConstructor()
{
list<Node> ls(5);
Node a1 = { 12 ,'a'};
list<Node> ls1(3, a1); //三个a1,
list<Node> ls2(ls1); // 用ls1初始化ls2
list<Node> ls3( ls1.begin(),ls1.end()); //同上
for_each(ls.begin(),ls.end(),fun);
cout << endl;
for_each(ls1.begin(),ls1.end(),fun);
cout << endl;
for_each(ls2.begin(),ls2.end(),fun);
cout << endl;
for_each(ls3.begin(),ls3.end(),fun);
cout << endl;
list <Node>::iterator ite = ls1.begin();
ite++; //不能直接ite+2,会造成位置的偏移
list<Node> ls4(ite,ls1.end()); //取ls1中间第2到最后个初始化为ls4
for_each(ls4.begin(),ls4.end(),fun);
}
//大小
void ListSize()
{
Node a= {12, 'a'};
list<Node> ls(3,a);
cout << ls.size() << endl;
for_each(ls.begin(),ls.end(),fun);
ls.resize(5);
cout << ls.size() << endl;
cout << ls.empty() << endl;
for_each(ls.begin(),ls.end(),fun);
}
//查
void ListCout()
{
Node a= {12, 'a'};
list<Node> ls(3,a);
for(list<Node>::iterator ite = ls.begin(); ite != ls.end(); ite++)
{
cout << ite->a << " " << ite->c << endl;
}
cout << ls.back().a << " " << ls.back().c <<endl;
cout << ls.front().a << " " << ls.front().c << endl;
}
int main()
{
//ListDefine();
//ListConstructor();
//ListSize();
//ListCout();
//ListAdd();
system("pause");
return 0;
}
#include<iostream>
#include<list>
#include<algorithm>
using namespace std;
struct Node{
int a;
char c;
Node(int b,char d)
{
a = b;
c = d;
}
};
void fun(Node& d)
{
cout << d.a << " " << d.c << "\n";
}
void ListAdd()
{
Node a(12, 'a');
list<Node> ls(3,a);
// ls.push_front(Node (11,'b'));
// ls.push_back(Node (13,'b'));
// for_each(ls.begin(),ls.end(),fun);
//
// cout << endl;
list<Node>::iterator ite = ls.begin();
ite++;
ite++;
ls.insert(ite,Node (15,'d'));
ls.insert(ite,3,Node (16,'e'));
for_each(ls.begin(),ls.end(),fun);
}
void ListDel()
{
list<Node> ls;
ls.push_back(Node(1,'a'));
ls.push_back(Node(2,'b'));
ls.push_back(Node(3,'c'));
ls.push_back(Node(4,'d'));
ls.push_back(Node(5,'e'));
ls.push_back(Node(6,'f'));
list<Node>::iterator ite = ls.begin();
ite++;
ite++; //指向第三个
ls.pop_back(); //删除最后一个
// 或ls.erase(--ls.end()); 效果一样
ls.pop_front(); //删除第一个
ls.erase(ite); //删除第三个
// ls.clear();
for_each(ls.begin(),ls.end(),fun);
}
void ListChange()
{
list<Node> ls;
ls.push_back(Node(1,'a'));
ls.push_back(Node(2,'b'));
ls.push_back(Node(3,'c'));
ls.push_back(Node(4,'d'));
ls.push_back(Node(5,'e'));
ls.assign(3,Node(2,'b')); //将原ls改为三个 2b
list<Node> ls1;
ls1 = ls;
list<Node>::iterator ite = ls1.begin();
ite++;
ls1.assign(ite,ls1.end());
for_each(ls.begin(),ls.end(),fun);
cout << endl;
for_each(ls1.begin(),ls1.end(),fun);
}
void ListDo()
{
list<Node> ls;
ls.push_back(Node(1,'a'));
ls.push_back(Node(2,'b'));
ls.push_back(Node(3,'c'));
ls.push_back(Node(4,'d'));
ls.push_back(Node(5,'e'));
list<Node> ls1;
ls1.push_back(Node(123,'a'));
// ls1.swap(ls);
// ls.reverse();
list<Node>::iterator ite = find(ls.begin(),ls.end(),Node(3,'c'));
cout << ite->a << " " << ite->c << endl;
for_each(ls.begin(),ls.end(),fun);
// for_each(ls1.begin(),ls1.end(),fun);
}
int main()
{
//ListAdd();
//ListDel();
//ListChange();
ListDo();
system("pause");
return 0;
}