List容器

此处是带头双向链表

对于List,不像string、vector之类的,没有reserve的说法,也不支持[ ]和下标,只有一种方式遍历List也就是采用迭代器(范围for的底层也是迭代器)。

insert函数和erase函数(需要配合std库里面的find函数)

If no elements match, the function returns last.

cpp 复制代码
void testlist1()
{
	std::list<int> lt;
	lt.push_back(1);
	lt.push_back(2);
	lt.push_back(3);
	lt.push_back(4);
	for (auto e : lt)
	{
		std::cout << e << " ";
	}
	std::cout << std::endl;
	std::list<int>::iterator pos = std::find(lt.begin(), lt.end(), 3);//std::find替换成find也可以正常运行
	if (pos != lt.end())
	{
		lt.insert(pos, 30);
	}
	for (auto e : lt)
	{
		std::cout << e << " ";
	}
	std::cout << std::endl;
	lt.erase(lt.begin());
	for (auto e : lt)
	{
		std::cout << e << " ";
	}
	std::cout << std::endl;
}

sort函数

很少用,因为效率特别低。比如说List<int>类型,将每一个整型元素push_back到vector里面,再用标准库的sort函数来排序,然后将排好序的vector内的元素又重新push_back到List<int>当中的速度比直接采用List的sort成员函数来排序的速度要更快,

为什么list将sort函数单独拎出来做为一个成员函数,而不采用标准库里面的sort函数?

迭代器可以分为单向、双向、随机这三种类型。双向迭代器是兼容单向迭代器的,随机迭代器是兼容双向迭代器,List采用的是双向迭代器。而标准库的sort要求的是随机迭代器,无法适配,所以只能增加一个sort的成员函数。

list_node

cpp 复制代码
template<class T>
struct list_node
{
	list_node<T>* _next;
	list_node<T>* _prev;
	T _data;
	list_node(const T& x = T())
		:_next(nullptr)
		, _prev(nullptr)//双向列表
		, _data(x)
	{}
};

list_node迭代器

cpp 复制代码
// 1、迭代器要么就是原生指针
// 2、迭代器要么就是自定义类型对原生指针的封装,模拟指针的行为
template<class T, class Ref, class Ptr>
struct __list_iterator
{
	typedef list_node<T> node;
	typedef __list_iterator<T, Ref, Ptr> self;
	node* _node;//本质上是对指针进行了封装
	__list_iterator(node* n)
		:_node(n)
	{}

	Ref operator*()
	{
		return _node->_data;
	}
	Ptr operator->()
	{
		return &(_node->_data);//返回值是T*
	}

	self& operator++()
	{
		_node = _node->_next;
		return *this;
	}
	self operator++(int)//tmp出了该函数也销毁了,所以无法采用传引用返回
	{
		self tmp(*this);
		_node = _node->_next;
		return tmp;
	}

	self& operator--()
	{
		_node = _node->_prev;
		return *this;
	}

	self operator--(int)
	{
		self tmp(*this);
		_node = _node->_prev;
		return tmp;
	}
	bool operator!=(const self& s)
	{
		return _node != s._node;//看底层封装的指针是否相同
	}

	bool operator==(const self& s)
	{
		return _node == s._node;
	}
};

List封装

成员变量

cpp 复制代码
template<class T>
class list
{
	typedef list_node<T> node;
public:
	typedef __list_iterator<T, T&, T*> iterator;
	typedef __list_iterator<T, const T&, const T*> const_iterator;
private:
	node* _head;//list类的唯一一个成员变量就是一个哨兵位头节点
}

begin()函数

cpp 复制代码
iterator begin()
{
	return iterator(_head->_next);
}

const_iterator begin() const
{
	return const_iterator(_head->_next);
}

end()函数

cpp 复制代码
iterator end()
{
	return iterator(_head);
}
const_iterator end() const
{
	return const_iterator(_head);
}

默认构造函数和empty_init()函数

cpp 复制代码
void empty_init()
{
	_head = new node;
	_head->_next = _head;//自己的next指向自己
	_head->_prev = _head;
}

list()
{
	empty_init();
}

析构函数和clear()函数

cpp 复制代码
void clear()
{
	iterator it = begin();
	while (it != end())
	{
		erase(it++);//
	}
}

迭代器构造函数

cpp 复制代码
template <class Iterator>
list(Iterator first, Iterator last)
{
	empty_init();
	while (first != last)
	{
		push_back(*first);//*first返回的是_node->_data;
		++first;
	}
}

拷贝构造

cpp 复制代码
//传统写法
list(const list<T>& lt)
{
	empty_init();
	for (auto e : lt)
	{
		push_back(e);
	}
}
//现代写法
list(const list<T>& lt)
{
	empty_init();

	list<T> tmp(lt.begin(), lt.end());//服用了迭代器构造函数
	swap(tmp);
}

swap函数

cpp 复制代码
void swap(list<T>& tmp)
{
	std::swap(_head, tmp._head);
}

赋值运算符重载

cpp 复制代码
list<T>& operator=(list<T> lt)//这里采用传值传参,形参是实参的一个拷贝
{
	swap(lt);
	return *this;
}

push_back()函数和push_front()函数

cpp 复制代码
void push_back(const T& x)
{
	insert(end(), x);
}
void push_front(const T& x)
{
	insert(begin(), x);
}

pop_back()函数和pop_front()函数

cpp 复制代码
void pop_back()
{
	erase(--end());
}
void pop_front()
{
	erase(begin());
}

insert()函数 Key

cpp 复制代码
void insert(iterator pos, const T& x)
{
	node* cur = pos._node;//迭代器封装的是指针
	node* prev = cur->_prev;
	node* new_node = new node(x);
	prev->_next = new_node;//prev是指针,要修改*prev的成员变量就要采用指针。
	new_node->_prev = prev;
	new_node->_next = cur;
	cur->_prev = new_node;
}

erase()函数 Key

cpp 复制代码
iterator erase(iterator pos)
{
	assert(pos != end());
	node* prev = pos._node->_prev;
	node* next = pos._node->_next;

	prev->_next = next;
	next->_prev = prev;
	delete pos._node;
	return iterator(next);
}
相关推荐
机器视觉知识推荐、就业指导7 分钟前
Qt/C++事件过滤器与控件响应重写的使用、场景的不同
开发语言·数据库·c++·qt
孤寂大仙v15 分钟前
【C++】STL----list常见用法
开发语言·c++·list
咩咩大主教1 小时前
C++基于select和epoll的TCP服务器
linux·服务器·c语言·开发语言·c++·tcp/ip·io多路复用
Ylucius3 小时前
动态语言? 静态语言? ------区别何在?java,js,c,c++,python分给是静态or动态语言?
java·c语言·javascript·c++·python·学习
是店小二呀3 小时前
【C++】C++ STL探索:Priority Queue与仿函数的深入解析
开发语言·c++·后端
ephemerals__3 小时前
【c++】动态内存管理
开发语言·c++
manba_3 小时前
leetcode-560. 和为 K 的子数组
数据结构·算法·leetcode
CVer儿3 小时前
条件编译代码记录
开发语言·c++
程序猿练习生4 小时前
C++速通LeetCode简单第18题-杨辉三角(全网唯一递归法)
c++·算法·leetcode
汉字萌萌哒4 小时前
【2022 CCF 非专业级别软件能力认证第一轮(CSP-J1)入门级 C++语言试题及解析】
数据结构·c++·算法