1.基础操作
1.1 遍历+正反顺序打印
(1)C++11遍历的方法
for(auto n:l){ // (1)C++11遍历的方法
cout << n << " ";
}
cout << endl;
(2)不支持下标访问
for(int i=0;i<l.size();++i){
// cout << l[i] << " "; // (2)不支持下标访问
}
(3)正序打印
list<int>::iterator it = l.begin(); //(3)正序打印
while(it != l.end()){
cout << *it << " ";
++it;
}
cout << endl;
(4)逆序打印
list<int>::reverse_iterator rit = l.rbegin();//(4)逆序打印
while(rit != l.rend()){
cout << *rit << " ";
++rit;
}
cout << endl;
- 完整案例
#include <iostream>
#include <list>
#include <vector>
using namespace std;
void Travesal(const list<int>& l){
list<int>::const_iterator it = l.cbegin();//cbegin() C++11
while(it != l.cend()){ //cend() C++11
cout << *it << " ";
++it;
}
cout << endl;
}
void TravesalReverse(const list<int>& l){
list<int>::const_reverse_iterator rit = l.crbegin();
while(rit != l.crend()){
cout << *rit << " ";
++rit;
}
cout << endl;
}
int main()
{
list<int> l = {1,2,3,4,5};// C++11
for(auto n:l){ // (1)C++11遍历的方法
cout << n << " ";
}
cout << endl;
for(int i=0;i<l.size();++i){
// cout << l[i] << " "; // (2)不支持下标访问
}
list<int>::iterator it = l.begin(); //(3)正序打印
while(it != l.end()){
cout << *it << " ";
++it;
}
cout << endl;
list<int>::reverse_iterator rit = l.rbegin();//(4)逆序打印
while(rit != l.rend()){
cout << *rit << " ";
++rit;
}
cout << endl;
Travesal(l);
TravesalReverse(l);
}
1.2 添加,删除
(1)尾添加
l.push_back(6);
(2)尾删除
l.pop_back();
(3) 首添加
l.push_front(-2);
(4) 首删除
l.pop_front();
- 完整案例
#include <iostream>
#include <list>
#include <vector>
using namespace std;
void Travesal(const list<int>& l){
list<int>::const_iterator it = l.cbegin();//cbegin() C++11
while(it != l.cend()){ //cend() C++11
cout << *it << " ";
++it;
}
cout << endl;
}
void TravesalReverse(const list<int>& l){
list<int>::const_reverse_iterator rit = l.crbegin();
while(rit != l.crend()){
cout << *rit << " ";
++rit;
}
cout << endl;
}
int main()
{
list<int> l = {1,2,3,4,5};// C++11
Travesal(l);
// 尾添加
l.push_back(6);
l.push_back(7);
l.push_back(8);
Travesal(l);
// 尾删除
l.pop_back();
l.pop_back();
l.pop_back();
Travesal(l);
// 首添加
l.push_front(-2);
l.push_front(-1);
l.push_front(0);
Travesal(l);
// 首删除
l.pop_front();
l.pop_front();
l.pop_front();
Travesal(l);
}
1.3 任意位置添加、删除
(1)insert():list的迭代器不能做算术运算,没有算术运算符重载,但是可以自增自减(左闭右开的区间)
// 插入
auto it = l.begin();
++it;
// it = it + 1; // (1)list的迭代器不能做算术运算,没有算术运算符重载,但是可以自增自减
l.insert(it,100); //表示在begin()+1的内存插入100,内存发生改变;此时it指针指向100的后面;(左闭又开的区间)
(2) erase():想要删除100,必须指向100的内存;必须先自减
// 删除
--it;
l.erase(it); //(2)想要删除100,必须指向100的内存;必须先自减
Travesal(l);
(3) 批量插入: 插入多个相同的元素,此时指向index=5的后面;
// 批量插入
it = l.begin();
++it;
l.insert(it,5,100); //插入多个相同的元素,此时指向index=5的后面;
Travesal(l);
(4) 批量删除
list<int>::iterator first = l.begin();
++first;
l.erase(first,it);// 删除的部分[1,6)
Travesal(l);
(5) 插入数组
int arr[] = {11,12,13,14};
l.insert(it,arr,arr+4);
Travesal(l);
(6) 插入向量
vector<int> vec = {21,22,23,24};
l.insert(l.end(),vec.begin(),vec.end());
Travesal(l);
(7) 随机访问,只能遍历
next() :C++11,begin()往后数4个元素;ndex = 4;
prev() : 往前数三个元素,index=end()-3,即倒数第三个数,首尾的差异
auto it = next(l.begin(),4); //C++11,begin()往后数4个元素;ndex = 4;
//prev() 往前数三个元素,index=end()-3,即倒数第三个数,首尾的差异
*it = 10000;
Travesal(l);
- 完整案例
#include <iostream>
#include <list>
#include <vector>
using namespace std;
void Travesal(const list<int>& l){
list<int>::const_iterator it = l.cbegin();//cbegin() C++11
while(it != l.cend()){ //cend() C++11
cout << *it << " ";
++it;
}
cout << endl;
}
void TravesalReverse(const list<int>& l){
list<int>::const_reverse_iterator rit = l.crbegin();
while(rit != l.crend()){
cout << *rit << " ";
++rit;
}
cout << endl;
}
int main()
{
list<int> l = {1,2,3,4,5};// C++11
Travesal(l);
// 插入
auto it = l.begin();
++it;
// it = it + 1; // (1)list的迭代器不能做算术运算,没有算术运算符重载,但是可以自增自减
l.insert(it,100); //表示在begin()+1的内存插入100,内存发生改变;此时it指针指向100的后面;(左闭又开的区间)
Travesal(l);
// 删除
--it;
l.erase(it); //(2)想要删除100,必须指向100的内存;必须先自减
Travesal(l);
// 批量插入
it = l.begin();
++it;
l.insert(it,5,100); //插入多个相同的元素,此时指向index=5的后面;
Travesal(l);
// 批量删除
list<int>::iterator first = l.begin();
++first;
l.erase(first,it);// 删除的部分[1,6)
Travesal(l);
// 插入数组
int arr[] = {11,12,13,14};
l.insert(it,arr,arr+4);
Travesal(l);
// 插入向量
vector<int> vec = {21,22,23,24};
l.insert(l.end(),vec.begin(),vec.end());
Travesal(l);
auto it = next(l.begin(),4); //C++11,begin()往后数4个元素;ndex = 4;
//prev() 往前数三个元素,index=end()-3,即倒数第三个数,首尾的差异
*it = 10000;
Travesal(l);
}
1.4 list特有的函数
(1) reverse: 逆序
l.reverse();
Travesal(l);
(2) sort:排序
l.sort();
Travesal(l);
(3) merge():按大小顺序插入
list<int> l2={3,6,9,10,13};
l.merge(l2);
(4) remove(): 删除值
l.remove(1);
Travesal(l);
(5) 删除某个条件的值
a.普通函数
bool condition(int n){
return n/10 == 1;
}
l.remove_if(condition);(1)普通函数
b. 仿函数
Condition cond;
l.remove_if(cond); //(2)仿函数
l.remove_if(Condition());
c. lamabda表达式
l.remove_if([](int n){return n/10==1;}); //(3)lamabda表达式
- 完整案例
#include <iostream>
#include <list>
#include <vector>
using namespace std;
void Travesal(const list<int>& l){
list<int>::const_iterator it = l.cbegin();//cbegin() C++11
while(it != l.cend()){ //cend() C++11
cout << *it << " ";
++it;
}
cout << endl;
}
void TravesalReverse(const list<int>& l){
list<int>::const_reverse_iterator rit = l.crbegin();
while(rit != l.crend()){
cout << *rit << " ";
++rit;
}
cout << endl;
}
bool condition(int n){
return n/10 == 1;
}
int main()
{
list<int> l = {1,2,3,4,5};// C++11
Travesal(l);
// list特有的成员函数
// 逆序
l.reverse();
Travesal(l);
// 排序
l.sort();
Travesal(l);
list<int> l2={3,6,9,10,13};
l.merge(l2);
Travesal(l);
// 删除值
l.remove(1);
Travesal(l);
// 删除某个条件的值
// l.remove_if(condition);(1)普通函数
// Condition cond;
// l.remove_if(cond); //(2)仿函数
// l.remove_if(Condition());
l.remove_if([](int n){return n/10==1;}); //(3)amabda表达式
Travesal(l);
}
(***)2 面试操作(vector.list之间的转化)
2.1 (88)合并两个有序数组
(1)vector转化为list
list<int> list1(nums1.begin(),nums1.begin()+m); //(1)vector转化为list
(2)将list2融入到list1
list1.merge(list2);//(2)将list2融入到list1
(3)list,vector之间的转化
nums1.assign(list1.begin(),list1.end()); //(3)list,vector之间的转化
- 完整代码
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
list<int> list1(nums1.begin(),nums1.begin()+m); //(1)vector转化为list
list<int> list2(nums2.begin(),nums2.begin()+n);
list1.merge(list2);//(2)将list2融入到list1
nums1.assign(list1.begin(),list1.end()); //(3)list,vector之间的转化
}
};
3 实现list(miniSTL)
3.1 利用链表简单的构造
(1.1) 节点初始化链表,list初始化链表
Node(const T& val):val(val),prev(NULL),next(NULL){} //(1.1)节点初始化链表
list():head(NULL),tail(NULL),_size(0){} //(1.2)list初始化链表
(1.2) 实现尾插法:
void push_back(const T& val){ //(1.2)尾插法插入元素
++_size;
Node* node = new Node(val);
if(NULL == head){
head = tail = node;
}else{
tail->next = node;
node->prev = tail;
tail = node;
}
}
(1.3)重载 [] 运算符;
T& operator[](int index){ //(1.3)重载 [] 运算符;
// if(index<0 || index >=_size) throw exception(string("invalid index"));
int count = 0;
Node* p = head;
while(NULL != p){
if(count++ == index) break;
p = p->next;
}
return p->val;
}
(1.4)c语言的方式进行打印
for(int i=0;i<li.size();++i){
cout << li[i] << endl;
}
(1.5)注意list类的大小与嵌套的struct无关;
3.2 迭代器的加入+运算符重载+通用算法
(2.1)加入迭代器
class iterator{
Node* p;
public:
iterator(Node* p):p(p){}
T& operator*(){return p->val;}
T* operator->(){return &(p->val);}
iterator operator++(){
p=p->next;
return *this;
}
iterator operator++(int){
iterator tmp(*this);
p=p->next;
return tmp;
}
iterator operator--(){
p = p->prev;
return *this;
}
iterator operator--(int){
iterator tmp(*this);
p=p->prev;
return tmp;
}
bool operator==(const iterator& it)const{
return p == it.p;
}
bool operator!=(const iterator& it)const{
return p != it.p;
}
};
iterator begin(){return iterator(head);}
iterator end(){return iterator(NULL);}
};
(2.2)通用算法(for_each()+ accumulate())
template <typename IT,typename FUNC>
void for_each(IT first,IT last,FUNC func){
while(first!=last){
func(*first++);
}
}
template <typename IT,typename VAL>
VAL accumulate(IT first,IT last,VAL val){
while(first!=last){
val+=*first++;
}
return val;
}
3.3 list特有算法(首尾(插删))
(3.1)首尾插删
//尾插法
void push_back(const T& val){
++_size;
Node* node = new Node(val); //(1)先创建数据节点
if(NULL == head){
head = tail = node; //(2)头结点判空操作
}else{ //(3)先考虑现在:
tail->next = node; //(3.1)尾节点的下一个是node;
node->prev = tail; //(3.2)node的上一个是尾节点
tail = node; //(3.3)refresh
}
tail -> next =NULL;
}
//头插法
void push_front(const T& val){
++_size;
Node* node = new Node(val); //(1)先创建数据节点;
if(NULL == head){ //(2)头结点判空;
head = tail = node;
}else{ //(3)先考虑现在:
node->next = head; //(3.1)数据的下一个节点是头结点;
head->prev = node; //(3.2)头结点的上一个节点是数据结点;
head = node; //(3.3)refresh;
}
tail ->next =NULL;
}
//尾删法
void pop_back(){
--_size;
Node* prev = tail->prev; //(1)创建新的尾部结点(即taild的前一个结点)
if(NULL == prev){ //(2)新的尾节点的判空操作
head = NULL;
}else{ //(3)先考虑现在:
prev->next = NULL; //(3.1)新的尾节点的下一个节点是NULL;
}
delete tail; //(3.2)释放尾节点
tail = prev; //refresh
}
//头删法
void pop_front(){
--_size;
Node* next = head->next; //(1)创建新的头部节点
if(NULL == next){ //(2)新的头结点的判空操作;
tail = NULL;
}else{ //(3)先考虑现在:
next->prev = NULL; //(3.1)清空原来的头指针
}
delete head; //(3.2)删除原来的头指针
head = next; //(3.3) refresh
}
(3.2)注意:考虑到创建,释放内存 ,必须要有析构函数
~list(){
while(NULL != head){
Node* next = head->next; //(1)一直析构头结点;
delete head; //(2)清空头结点
head = next; //(3)refresh
}
head = tail = NULL; //(4)指针清空
_size = 0; //——size归0
}
3.4 完整代码
#include <iostream>
// #include <algorithm>
// #include <list>
#include <exception>
using namespace std;
namespace miniSTL{
template<typename T>
class list{
struct Node{
T val;
Node* prev;
Node* next;
Node(const T& val):val(val),prev(NULL),next(NULL){}
};
Node* head,*tail;
size_t _size;
public:
list():head(NULL),tail(NULL),_size(0){}
// 拷贝构造/赋值运算符重载函数
~list(){
while(NULL != head){
Node* next = head->next; //(1)一直析构头结点;
delete head; //(2)清空头结点
head = next; //(3)refresh
}
head = tail = NULL; //(4)指针清空
_size = 0; //——size归0
}
//w尾插法
void push_back(const T& val){
++_size;
Node* node = new Node(val); //(1)先创建数据节点
if(NULL == head){
head = tail = node; //(2)头结点判空操作
}else{ //(3)先考虑现在:
tail->next = node; //(3.1)尾节点的下一个是node;
node->prev = tail; //(3.2)node的上一个是尾节点
tail = node; //(3.3)refresh
}
tail -> next =NULL;
}
//头插法
void push_front(const T& val){
++_size;
Node* node = new Node(val); //(1)先创建数据节点;
if(NULL == head){ //(2)头结点判空;
head = tail = node;
}else{ //(3)先考虑现在:
node->next = head; //(3.1)数据的下一个节点是头结点;
head->prev = node; //(3.2)头结点的上一个节点是数据结点;
head = node; //(3.3)refresh;
}
tail ->next =NULL;
}
//尾删法
void pop_back(){
--_size;
Node* prev = tail->prev; //(1)创建新的尾部结点(即taild的前一个结点)
if(NULL == prev){ //(2)新的尾节点的判空操作
head = NULL;
}else{ //(3)先考虑现在:
prev->next = NULL; //(3.1)新的尾节点的下一个节点是NULL;
}
delete tail; //(3.2)释放尾节点
tail = prev; //refresh
}
//头删法
void pop_front(){
--_size;
Node* next = head->next; //(1)创建新的头部节点
if(NULL == next){ //(2)新的头结点的判空操作;
tail = NULL;
}else{ //(3)先考虑现在:
next->prev = NULL; //(3.1)清空原来的头指针
}
delete head; //(3.2)删除原来的头指针
head = next; //(3.3) refresh
}
size_t size()const{
return _size;
}
T& operator[](int index){
// if(index<0 || index >=_size) throw exception(string("invalid index"));
int count = 0;
Node* p = head;
while(NULL != p){
if(count++ == index) break;
p = p->next;
}
return p->val;
}
class iterator{
Node* p;
public:
iterator(Node* p):p(p){}
T& operator*(){return p->val;}
T* operator->(){return &(p->val);}
iterator operator++(){
p=p->next;
return *this;
}
iterator operator++(int){
iterator tmp(*this);
p=p->next;
return tmp;
}
iterator operator--(){
p = p->prev;
return *this;
}
iterator operator--(int){
iterator tmp(*this);
p=p->prev;
return tmp;
}
bool operator==(const iterator& it)const{
return p == it.p;
}
bool operator!=(const iterator& it)const{
return p != it.p;
}
};
iterator begin(){return iterator(head);}
iterator end(){return iterator(NULL);}
};
template <typename IT,typename FUNC>
void for_each(IT first,IT last,FUNC func){
while(first!=last){
func(*first++);
}
}
template <typename IT,typename VAL>
VAL accumulate(IT first,IT last,VAL val){
while(first!=last){
val+=*first++;
}
return val;
}
}
using namespace miniSTL;
int main(){
list<int> li;
li.push_back(1);
li.push_back(2);
li.push_back(3);
cout << sizeof(li) << endl;
cout << li.size() << endl;
for(int i=0;i<li.size();++i){
// cout << li[i] << endl;
}
list<int>::iterator it = li.begin();
while(it!=li.end()){
cout << *it++ << endl;
//++it;
}
for(auto n:li){
cout << n << endl;
}
li.push_front(0);
li.push_front(-1);
li.push_front(-2);
li.pop_back();
li.pop_back();
li.pop_back();
li.pop_back();
li.pop_back();
li.pop_back();
li.push_front(-1);
li.push_front(-2);
li.pop_front();
li.pop_front();
for_each(li.begin(),li.end(),[](int n){cout << n << endl;});
cout<< accumulate(li.begin(),li.end(),0) << endl;
}