您的位置:首页 > 科技 > IT业 > 成都广告公司招聘_阿里巴巴网页版登录入口_seo黑帽技术工具_免费自助建站平台

成都广告公司招聘_阿里巴巴网页版登录入口_seo黑帽技术工具_免费自助建站平台

2024/11/16 5:21:23 来源:https://blog.csdn.net/Mr_Xuhhh/article/details/143007371  浏览:    关键词:成都广告公司招聘_阿里巴巴网页版登录入口_seo黑帽技术工具_免费自助建站平台
成都广告公司招聘_阿里巴巴网页版登录入口_seo黑帽技术工具_免费自助建站平台

list

在这里插入图片描述

大体上与之前学的string,vector类似,list不支持[]访问,擅长头插,头删,尾插,尾删,中间元素插入删除,因为list底层是双向循环带头链表

一段代码演示:

#include <iostream>
#include <list>
using namespace std;int main()
{//尾插list<int> lt1;lt1.push_back(1);lt1.push_back(1);lt1.push_back(1);lt1.push_back(1);list<int> lt2 = { 1,2,3,4,5 };//迭代器list<int>::iterator it1 = lt1.begin();//迭代器进行访问while (it1 != lt1.end()){cout << *it1 << " ";++it1;}cout << endl;//支持迭代器也就支持范围forfor (auto e : lt2){cout << e << " ";}cout << endl;
}

代码结果如下:

在这里插入图片描述

这里list的迭代器会有所不同

在这里插入图片描述

用原生指针解决不了

push_back和emplace_back

先来看一段代码:

class Pos
{int _row;int _col;public:Pos(int row, int col):_row(row),_col(col){cout << "Pos(int row, int col)" << endl;}//拷贝构造Pos(const Pos& p):_row(p._row), _col(p._col){cout << "Pos(const Pos&p)" << endl;}
};int main()
{//构造+拷贝构造//push_backlist<Pos> lt;//有名对象Pos p1(1, 1);lt.push_back(p1);//匿名对象lt.push_back(Pos(2, 2));//隐式类型转换lt.push_back({ 3,3 });//emplace_back,可以看作模板lt.emplace_back(p1);lt.emplace_back(Pos(2, 2));//lt.emplace_back({3,3});不可以,因为形参类型未知//可以传递多个参数,相当于直接构造了Pos//直接构造lt.emplace_back(3, 3);return 0;
}

splice

一个应用的地方在于可以提高修改元素内容的效率:

int main()
{list<int> lt1 = { 1,2,3,4,5 };//LRU//这里可以理解为转移链表里面的元素int x;while (cin >> x){auto pos = find(lt1.begin(), lt1.end(), x);if (pos != lt1.end()){//这里的含义是把lt1里的pos转移到开头位置lt1.splice(lt1.begin(), lt1, pos);}}return 0;
}

sort–排序

示例代码如下:

int main()
{list<int> lt1 = { 1,20,3,-4,5 };for (auto e : lt1){cout << e << " ";}cout << endl;//默认是升序lt1.sort();for (auto e : lt1){cout << e << " ";}cout << endl;//如果需要降序,要用到仿函数greater//有名对象的写法//greater<int> gt;//lt1.sort(gt);//匿名对象的写法,更推荐lt1.sort(greater<int>());//vector的方式也可以写vector<int> v1 = { 1,20,3,-4,5 };for (auto e : v1){cout << e << " ";}cout << endl;//这里同样也是默认升序sort(v1.begin(), v1.end());for (auto e : v1){cout << e << " ";}cout << endl;//降序也要用到仿函数sort(v1.begin(), v1.end(), greater<int>());for (auto e : v1){cout << e << " ";}cout << endl;
}

运行结果如下:

在这里插入图片描述

迭代器的分类

在这里插入图片描述

不能随便乱用迭代器,因为底层是不一样的,可以理解为随机单向迭代器包含于双向迭代器,双向迭代器包含于随机迭代器

上面的排序,sort的底层是特殊处理过的,vector的底层是快排

效率对比测试:
测试的代码:

void test_op1()
{srand(time(0));const int N = 1000000;list<int> lt1;list<int> lt2;vector<int> v;for (int i = 0; i < N; ++i){auto e = rand() + i;lt1.push_back(e);v.push_back(e);}int begin1 = clock();// 排序sort(v.begin(), v.end());int end1 = clock();int begin2 = clock();lt1.sort();int end2 = clock();printf("vector sort:%d\n", end1 - begin1);printf("list sort:%d\n", end2 - begin2);
}void test_op2()
{srand(time(0));const int N = 1000000;list<int> lt1;list<int> lt2;for (int i = 0; i < N; ++i){auto e = rand();lt1.push_back(e);lt2.push_back(e);}int begin1 = clock();// 拷贝vectorvector<int> v(lt2.begin(), lt2.end());// 排序sort(v.begin(), v.end());// 拷贝回lt2lt2.assign(v.begin(), v.end());int end1 = clock();int begin2 = clock();lt1.sort();int end2 = clock();printf("list copy vector sort copy list sort:%d\n", end1 - begin1);printf("list sort:%d\n", end2 - begin2);
}

测试结果:

在这里插入图片描述

list的模拟实现

尾插的操作与前面学习的双向循环链表类似:

在这里插入图片描述

迭代器这里需要注意,与前面学习的string和vector不一样:

在这里插入图片描述

这里需要注意的是迭代器不可以通过下标的方式进行访问,像我们前面学过的string和vector底层结构是数组,物理结构是连续的,但是list的底层是双向循环链表,物理空间不连续,需要借助类封装节点指针,重载运算符,模拟指针的行为

operator->访问

代码如下:
list.h

T* operator->()//访问里面元素
{return &_node->_data;//取里面地址
}

Test.cpp

soobin::list<Pos> lt2;
Pos p1(1, 1);
lt2.push_back(p1);
lt2.push_back(Pos(2, 2));
lt2.push_back({ 3,3 });soobin::list<Pos>::iterator it2 = lt2.begin();
while (it2 != lt2.end())
{cout << (*it2)._row << ":" << (*it2)._col << endl;//为了可读性,特殊处理,省略了一个->cout << it2->_row << ":" << it2->_col << endl;//显示写法,第一个->是运算符重载,第二个->是结构体元素访问cout << it2.operator->()->_row << ":" << it2.operator->()->_col << endl;++it2;
}
cout << endl;

总体代码如下:
List.h

#include <assert.h>
namespace soobin
{// 惯例// 全部都是公有,一般用structtemplate<class T>struct list_node{T _data;list_node<T>* _next;list_node<T>* _prev;list_node(const T& x = T())//模板的缺省值,匿名对象:_data(x), _next(nullptr), _prev(nullptr){}};template<class T>struct list_iterator{typedef list_node<T> Node;typedef list_iterator<T> Self;Node* _node;list_iterator(Node* node):_node(node){}//引用返回的好处是既可以读也可以写T& operator*(){return _node->_data;}T* operator->(){return &_node->_data;}Self& operator++(){_node = _node->_next;return *this;}Self& operator--(){_node = _node->_prev;return *this;}Self operator++(int){Self tmp(*this);_node = _node->_next;return tmp;}Self operator--(int){Self tmp(*this);_node = _node->_prev;return tmp;}bool operator!=(const Self& s){return _node != s._node;}};template<class T>class list{typedef list_node<T> Node;public:typedef list_iterator<T> iterator;iterator begin(){return iterator(_head->_next);}iterator end(){return iterator(_head);}void empty_init(){_head = new Node();_head->_next = _head;_head->_prev = _head;}list(){empty_init();}void push_back(const T& x){Node* new_node = new Node(x);Node* tail = _head->_prev;tail->_next = new_node;new_node->_prev = tail;new_node->_next = _head;_head->_prev = new_node;}private:Node* _head;};
}

Test.h

#include <iostream>
#include <list>
#include <vector>
#include <algorithm>
using namespace std;//int main()
//{//尾插//list<int> lt1;//lt1.push_back(1);//lt1.push_back(1);//lt1.push_back(1);//lt1.push_back(1);//list<int> lt2 = { 1,2,3,4,5 };//迭代器//list<int>::iterator it1 = lt1.begin();//迭代器进行访问//while (it1 != lt1.end())//{//	cout << *it1 << " ";//	++it1;//}//cout << endl;//支持迭代器也就支持范围for//for (auto e : lt2)//{//	cout << e << " ";//}//cout << endl;
//}class Pos
{
public:int _row;int _col;Pos(int row, int col):_row(row),_col(col){cout << "Pos(int row, int col)" << endl;}//拷贝构造Pos(const Pos& p):_row(p._row), _col(p._col){cout << "Pos(const Pos&p)" << endl;}
};//int main()
//{//构造+拷贝构造//push_back
//	list<Pos> lt;//有名对象
//	Pos p1(1, 1);
//	lt.push_back(p1);
//	//匿名对象
//	lt.push_back(Pos(2, 2));//隐式类型转换
//	lt.push_back({ 3,3 });//emplace_back,可以看作模板
//	lt.emplace_back(p1);
//	lt.emplace_back(Pos(2, 2));//lt.emplace_back({3,3});不可以,因为形参类型未知//可以传递多个参数,相当于直接构造了Pos//直接构造
//	lt.emplace_back(3, 3);
//	return 0;
//}//int main()
//{//for (auto e : lt1)//{//	cout << e << " ";//}//cout << endl;//int x;//cin >> x;//auto it = find(lt1.begin(), lt1.end(), x);//if (it != lt1.end())//{//	it.erase(it);//}
//	return 0;
//}//int main()//{//	list<int> lt1 = { 1,2,3,4,5 };//LRU//这里可以理解为转移链表里面的元素//	int x;//	while (cin >> x)//	{//		auto pos = find(lt1.begin(), lt1.end(), x);//		if (pos != lt1.end())//		{//这里的含义是把lt1里的pos转移到开头位置//			lt1.splice(lt1.begin(), lt1, pos);//		}//	}//	return 0;//}//int main()
//{
//	list<int> lt1 = { 1,20,3,-4,5 };
//	for (auto e : lt1)
//	{
//		cout << e << " ";
//	}
//	cout << endl;//默认是升序
//	lt1.sort();
//	for (auto e : lt1)
//	{
//		cout << e << " ";
//	}
//cout<<endl;
//	//如果需要降序,要用到仿函数greater//有名对象的写法//greater<int> gt;//lt1.sort(gt);//匿名对象的写法,更推荐//lt1.sort(greater<int>());//vector的方式也可以写//vector<int> v1 = { 1,20,3,-4,5 };//for (auto e : v1)//{//	cout << e << " ";//}//cout << endl;//这里同样也是默认升序//sort(v1.begin(), v1.end());//for (auto e : v1)//{//	cout << e << " ";//}//cout << endl;//降序也要用到仿函数//sort(v1.begin(), v1.end(), greater<int>());//for (auto e : v1)//{//	cout << e << " ";
//	}//cout << endl;
//}
//void test_op1()
//{
//	srand(time(0));
//	const int N = 1000000;//	list<int> lt1;
//	list<int> lt2;//	vector<int> v;
//
//	for (int i = 0; i < N; ++i)
//	{
//		auto e = rand() + i;
//		lt1.push_back(e);
//		v.push_back(e);
//	}//	int begin1 = clock();// 排序
//	sort(v.begin(), v.end());
//	int end1 = clock();//	int begin2 = clock();
//	lt1.sort();
//	int end2 = clock();//	printf("vector sort:%d\n", end1 - begin1);
//	printf("list sort:%d\n", end2 - begin2);
//}//void test_op2()
//{
//	const int N = 1000000;//	list<int> lt1;
//	list<int> lt2;//	for (int i = 0; i < N; ++i)
//	{
//		auto e = rand();
//		lt1.push_back(e);
//		lt2.push_back(e);
//	}//	int begin1 = clock();// 拷贝vector//	vector<int> v(lt2.begin(), lt2.end());// 排序
//	sort(v.begin(), v.end());// 拷贝回lt2
//	lt2.assign(v.begin(), v.end());//	int end1 = clock();//	int begin2 = clock();
//	lt1.sort();
//	int end2 = clock();//	printf("list copy vector sort copy list sort:%d\n", end1 - begin1);
//	printf("list sort:%d\n", end2 - begin2);
//}#include "List.h"int main()
{soobin::list<int> lt1;lt1.push_back(1);lt1.push_back(1);lt1.push_back(1);lt1.push_back(1);//不直接在it1上进行改动是因为会造成没有指针指向哨兵位等问题//迭代器soobin::list<int>::iterator it1 = lt1.begin();//迭代器进行访问while (it1 != lt1.end()){//也可以写*it1 = 2;cout << *it1 << " ";++it1;}cout << endl;//支持迭代器也就支持范围forfor (auto e : lt1){cout << e << " ";}cout << endl;soobin::list<Pos> lt2;Pos p1(1, 1);lt2.push_back(p1);lt2.push_back(Pos(2, 2));lt2.push_back({ 3,3 });soobin::list<Pos>::iterator it2 = lt2.begin();while (it2 != lt2.end()){cout << (*it2)._row << ":" << (*it2)._col << endl;//为了可读性,特殊处理,省略了一个->cout << it2->_row << ":" << it2->_col << endl;//显示写法,第一个->是运算符重载,第二个->是结构体元素访问cout << it2.operator->()->_row << ":" << it2.operator->()->_col << endl;++it2;}cout << endl;return 0;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com