STL源码剖析之list

先前我们讲过vector是连续线性存储的,其访问元素的时间复杂度是O(1),但是插入或者删除元素的时间复杂度是O(N),所以其插入或者删除的效率比价低。有什么容器的插入或者删除的效率是常数时间呢? 有啊~~ 就是list。list的每次插入或者删除元素时,配置或者释放一个内存空间,其时间复杂度永远是O(1)。现在就让我们来了解一下list的底层实现吧。

首先让我们来看一下list的节点。

template<typename T>
struct Listnode {
	T             value;
	Listnode<T>*  prev;
	Listnode<T>*  next;
public:
	Listnode() :value(0) {};
	Listnode(const T& _value) :value(_value) {};
};

所以list是一个双向链表。

  • 我们都知道vector是连续线性存储的,因此其迭代器就是原生指针。通过list的节点我们知道:list是一个双向链表结构。这就告诉我们其迭代器不是原生指针,而是class type。因此我们必须对其迭代器进行封装。

list的迭代器: 

template<typename T>
struct Listiteratortype {
	typedef T                 Value_type;
	typedef T*                Pointer;
	typedef T&                Reference;
	typedef size_t            Size_type;
	typedef size_t            Difference_type;
};
template<typename T>
class Listiterator {
public:
	Listiterator(Listnode<T>& _node) :node(_node) {};
	Listiterator():node(nullptr) {};
	Listiterator(const Listiterator<T>& _listiterator) :node(_listiterator.node) {};
	~Listiterator() { if (node!=nullptr) delete node; };
public:
	typename Listiteratortype<T>::Reference operator*()const;
	typename Listiteratortype<T>::Pointer operator->()const;
	typename Listiterator<T>& operator++();
	typename Listiterator<T>& operator--();
	typename Listiterator<T>* operator++(int);
	typename Listiterator<T>* operator--(int);
	bool operator==(const Listiterator<T>& _listiterator);
	bool operator!=(const Listiterator<T>& _listiterator);
private:
	Listnode<T>* node;
};

list迭代器的实现

template<typename T>
bool Listiterator<T>::operator==(const Listiterator<T>& _listiterator) {
	if (_listiterator.node == node)
		return true;
	else
		return false;
}

template<typename T>
bool Listiterator<T>::operator!=(const Listiterator<T>& _listiterator) {
	if (_listiterator.node != node)
		return true;
	else
		return false;
}

template<typename T>
typename Listiteratortype<T>::Reference Listiterator<T>::operator*()const {
	return node->value;
}

template<typename T>
typename Listiteratortype<T>::Pointer Listiterator<T>::operator->()const {
	return &(node->value);
}

template<typename T>
typename Listiterator<T>& Listiterator<T>::operator++() {
	node = node->next;
	return *this;
}

template<typename T>
typename Listiterator<T>& Listiterator<T>::operator--() {
	node = node->prev;
	return *this;
}

template<typename T>
typename Listiterator<T>* Listiterator<T>::operator++(int) {
	auto temp = *this;
	node = node->next;
	return *this;
}

template<typename T>
typename Listiterator<T>* Listiterator<T>::operator--(int) {
	auto temp = *this;
	node = node->prev;
	return *this;
}

链表的存储不是连续线性存储的,那么list的存储也不是。因此我们便可以知道:list的插入和删除操作并不会导致迭代器的失效(也可以理解为局部的改变,不会引起整体的变化)。我们已经知道list的底层是双向链表,但是更重要的是:list的底层实现是双向环状链表结构。为什么是环状的链表结构? 我的理解是因为链表的插入和删除的时间复杂度是常数,但是对对数据的访问的时间复杂度是线性时间,环状结构更利于对数据的访问吧。

list的头文件

template<typename T>
class List {
public:
	List() :node(new Listnode<T>()) {
		node->next = node;
	}
	List(const size_t n, const T* t);
	~List();
public:
	Listiterator<T> begin()const;
	Listiterator<T> end()const;
	bool empty()const;
	typename Listiteratortype<T>::Size_type size()const;
	typename Listiteratortype<T>::Reference front()const;
	typename Listiteratortype<T>::Reference back()const;
	void push_back(const T& key);
	Listiterator<T> insert(Listiterator<T>& position, const T& value);
	Listiterator<T> erase(Listiterator<T>& position);
	void push_back(const T& value);
	void pop_back();
	void push_front(const T& value);
	void pop_front();
	void clear();
private:
	Listnode<T>* node;
	void destory()noexcept;
	Listnode<T>* construct(const size_t n, const T* t)noexcept;
};

list的实现

template<typename T>
void List<T>::destory()noexcept {
	auto first = node->next;
	auto last = node;
	while (first != last) {
		delete first;
		first = nullptr;
		first=first->next;
	}
	delete last;
	last = nullptr;
}

template<typename T>
Listnode<T>* List<T>::construct(const size_t n, const T* t)noexcept {

	Listnode<T>* p = node;
	for (int i = 0; i < n; ++i) {
		Listnode<T>* newnode = new Listnode<T>();
		newnode->value = t[i];
		p->next = newnode;
		newnode->prev = p;
	}
	p->next = node;
	node->prev = p;
}

template<typename T>
List<T>::List(const size_t n, const T* t) {
	construct(n, t);
}

template<typename T>
List<T>::~List() {
	destory();
}

template<typename T>
Listiterator<T> List<T>::begin()const {
	node = node->next;
	return Listiterator<T>listiterator(node);
}

template<typename T>
Listiterator<T> List<T>::end()const {
	return Listiterator<T>listiterator(node);
}

template<typename T>
bool List<T>::empty()const {
	if (node->next == node)
		return true;
	else
		return false;
}

template<typename T>
typename Listiteratortype<T>::Size_type  List<T>::size()const {
	size_t count = 0;
	auto first = node->next;
	auto last = node;
	while (first != last) {
		++count;
		first=first->next;
	}
	return count;
}

template<typename T>
typename Listiteratortype<T>::Reference  List<T>::front()const {
	node = node->next;
	return node->value;
}

template<typename T>
typename Listiteratortype<T>::Reference  List<T>::back()const {
	node = node->prev;
	return node->value;
}

template<typename T>
Listiterator<T> List<T>::insert(Listiterator<T>& position, const T& value) {
	Listnode<T>* newnode = new Listnode<T>(value);
	newnode->next = position.node;
	newnode->prev = position.node->prev;
	position.node->prev->next = newnode;
	position.node->prev = newnode;

	return Listiterator<T>(newnode);
}

template<typename T>
Listiterator<T> List<T>::erase(Listiterator<T>& position) {
	Listnode<T>* position_next = position.node->next;
	Listnode<T>* position_prev = position.node->prev;
	position_next->prev = position_prev;
	position_prev->next = position_next;
	delete position;

	return Listiterator<T>(position_next);
}

template<typename T>
void List<T>::pop_back() {
	Listiterator<T>* tmp = end();
	--tmp;
	erase(tmp);
}

template<typename T>
void List<T>::pop_front() {
	erase(begin());
}

template<typename T>
void List<T>::push_back(const T& value) {
	insert(end(), value);
}

template<typename T>
void List<T>::push_front(const T& value) {
	insert(begin(), value);
}

template<typename T>
void List<T>::clear() {
	Listnode<T>* first = node->next;
	Listnode<T>* last = node;
	while (first != last) {
		delete first;
		first = first->next;
	}

	node->next = node;
	node->prev = node;
}

以上代码是我写的简单的list。 如果有不理解的或者错误的地方,欢迎指出哦~~~

发布了78 篇原创文章 · 获赞 11 · 访问量 5090

猜你喜欢

转载自blog.csdn.net/qq_43145594/article/details/104130595