[Introduction to C++]---The use and simulation implementation of List

1.Introduction to list

  1. listIt is a sequential container that can be inserted and deleted at any position within the constant range, and the container can be iterated forward and backward in both directions.
  2. listThe bottom layer of the doubly linked list is a doubly linked list structure. Each element in the doubly linked list is stored in an independent node that is independent of each other. The node points to its previous element and next element through pointers.
  3. listVery similar to forward_list: The main difference is that forward_list is a singly linked list and can only iterate forward, making it simpler and more efficient.
  4. Compared with other sequential containers (array, vector, deque), listit is usually more efficient to insert and remove elements at any position.
  5. Compared with other sequential containers, the listbiggest forward_listflaw is that it does not support random access at any position. For example, listthe 6th element to be accessed must be iterated from a known position (such as the head or tail) to that position. Iterating over this position requires linear time overhead; listsome additional space is also required to store the information associated with each node (this may be an important factor for large lists storing smaller elements)

2.Use of list

template < class T, class Alloc = allocator<T> > class list;
//list的使用需要使用显示实例化才能使用

2.1Constructor of list

list (size_type n, const value_type& val = value_type())//构造的list中包含n个值为val的元素
list()//构造空的list
list (const list& x)//拷贝构造函数
list (InputIterator first, InputIterator last)//用[first, last)区间中的元素构造list

eg:

void testlist1()
{
    
    
	list<int> lt1;
	list<int> lt2(10, 6);
	for (auto e : lt2)
	{
    
    
		cout << e << " ";
	}
	cout<<endl;
	list<int> lt3(lt2);
	for (auto e : lt3)
	{
    
    
		cout << e << " ";
	}
	cout << endl;
	list<int> lt4(lt3.begin(), lt3.end());
	for (auto e : lt4)
	{
    
    
		cout << e << " ";
	}
	cout << endl;
}

The result of running the code is:

2.2list modifiers

void push_front (const value_type& val);
//在首元素前插入值为val的元素
void pop_front();
//删除val的第一个元素
void push_back (const value_type& val);
//在list的尾部插入值为val的
void pop_back();
//删除list中最后一个元素
single element (1)	
iterator insert (iterator position, const value_type& val);
//在list position位置插入值为val的元素
fill (2)	
    void insert (iterator position, size_type n, const value_type& val);
//在list position的位置插入n个值为val的元素
range (3)	
template <class InputIterator>
    void insert (iterator position, InputIterator first, InputIterator last);
//在list position的位置插入[first,last]区间的元素
iterator erase (iterator position);
//删除position位置的值
iterator erase (iterator first, iterator last);
//删除[first,last)区间的元素
void swap (list& x);
//交换两个list中的元素
void clear();
//清空list中的数据

eg1:

void testlist2()
{
    
    
	list<int> lt1;
	lt1.push_back(10);
	lt1.push_back(20);
	lt1.push_back(30);
	lt1.push_back(40);
	lt1.push_back(50);
	lt1.push_back(60);
	for (auto& e : lt1)
	{
    
    
		cout << e << " ";
	}
	cout << endl;
	lt1.pop_front();
	for (auto& e : lt1)
	{
    
    
		cout << e << " ";
	}
	cout << endl;
	lt1.push_front(100);
	for (auto& e : lt1)
	{
    
    
		cout << e << " ";
	}
	cout << endl;
	lt1.pop_back();
	for (auto& e : lt1)
	{
    
    
		cout << e << " ";
	}
	cout << endl;
}

The result of compiling and running the code is:
Insert image description here
eg2:

void testlist3()
{
    
    
	list<int> lt1;
	lt1.push_back(10);
	lt1.push_back(20);
	lt1.push_back(30);
	lt1.push_back(40);
	lt1.push_back(50);
	lt1.push_back(60);
	list<int>::iterator it = lt1.begin();
	//在it位置插入99
	lt1.insert(it, 99);
	for (auto& e : lt1)
	{
    
    
		cout << e << " ";
	}
	cout << endl;
	it = lt1.begin();
	//在it位置插入5个6
	lt1.insert(it, 5, 6);
	for (auto& e : lt1)
	{
    
    
		cout << e << " ";
	}
	cout << endl;
	it = lt1.begin();
	list<int> lt2(6, 5);
	lt1.insert(it, lt2.begin(), lt2.end());
	for (auto& e : lt1)
	{
    
    
		cout << e << " ";
	}
	cout << endl;
}

The result of compiling and running the code is:
Insert image description here
eg3:

void testlist4()
{
    
    
	list<int> lt1;
	lt1.push_back(10);
	lt1.push_back(20);
	lt1.push_back(30);
	lt1.push_back(40);
	lt1.push_back(50);
	lt1.push_back(60);
	list<int>::iterator it = lt1.begin();
	lt1.erase(it);
	for (auto& e : lt1)
	{
    
    
		cout << e << " ";
	}
	cout << endl;
	lt1.erase(lt1.begin(), lt1.end());
	for (auto& e : lt1)
	{
    
    
		cout << e << " ";
	}
	cout << endl;
}

The result of compiling and running the code is:
Insert image description here
eg4:

void testlist5()
{
    
    
	list<int> lt1;
	lt1.push_back(10);
	lt1.push_back(20);
	lt1.push_back(30);
	lt1.push_back(40);
	lt1.push_back(50);
	lt1.push_back(60);
	list<int> lt2(5, 6);
	printf("lt1的当前元素:");
	for (auto& e : lt1)
	{
    
    
		cout << e << " ";
	}
	cout << endl;
	printf("lt2的当前元素:");
	for (auto& e : lt2)
	{
    
    
		cout << e << " ";
	}
	cout << endl;
	swap(lt1, lt2);
	printf("lt1的当前元素:");
	for (auto& e : lt1)
	{
    
    
		cout << e << " ";
	}
	cout << endl;
	printf("lt2的当前元素:");
	for (auto& e : lt2)
	{
    
    
		cout << e << " ";
	}
	cout << endl;
}

The result of compiling and running the code is:
Insert image description here
eg5:

void testlist6()
{
    
    
	list<int> lt1;
	lt1.push_back(10);
	lt1.push_back(20);
	lt1.push_back(30);
	lt1.push_back(40);
	lt1.push_back(50);
	lt1.push_back(60);
	for (auto& e : lt1)
	{
    
    
		cout << e << " ";
	}
	cout << endl;
	//清空lt1原有数据后插入66
	lt1.clear();
	lt1.push_back(66);
	for (auto& e : lt1)
	{
    
    
		cout << e << " ";
	}
	cout << endl;
}

The result of compiling and running the code is:
Insert image description here

2.3list capacity

bool empty() const;
//检测list是否为空,是返回true,否则返回false
size_type size() const;
//返回list中有效节点的个数

2.4list gone access

reference front();
const_reference front() const;
//返回list的第一个节点中值的引用
reference back();
const_reference back() const;
//返回list的最后一个节点中值的引用

eg1:

void testlist7()
{
    
    
	list<int> lt1;
	lt1.push_back(10);
	lt1.push_back(20);
	lt1.push_back(30);
	lt1.push_back(40);
	lt1.push_back(50);
	lt1.push_back(60);
	cout << "list头部元素为:" << lt1.front() << endl;
	cout << "list尾部元素为:" << lt1.back() << endl;	
}

The result of running the code is:
Insert image description here

2.5Usage of iterator

iterator begin();
const_iterator begin() const;
//返回第一个元素的迭代器
iterator end();
const_iterator end() const;
//返回最后一个元素下一个位置的迭代器
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
//返回第一个元素的reverse_iterator,即end位置
reverse_iterator rend();
const_reverse_iterator rend() const;
//返回最后一个元素下一个位置的reverse_iterator,即begin位置

list container uses iterator

void testlist8()
{
    
    
	list<int> lt1(5, 6);
	list<int>::iterator it = lt1.begin();	
	while (it != lt1.end())
	{
    
    
		cout << *it <<" ";
		it++;
	}
	cout << endl;
}

The result of running the code is:
Insert image description here
iterator classification:

input iterator//输入迭代器
output iterator//输出迭代器
forward iterator//单向迭代器可以++ 适用forward_list/unorderd_xxx容器
bidirectional iterator//双向迭代器可以++/-- 适用list/map/set容器
random access iteartor//任意迭代器可以++/--/+/- 适用于vector/string/deque容器

Insert image description here

Random iterators can use bidirectional iterators, but bidirectional iterators cannot use random iterators! Container iterators with more functions can use algorithm interface functions adapted to iterators with less functions, but not vice versa!

Chestnut:
The iterator of list is:
Insert image description here
the algorithm interface function is:
Insert image description here
Insert image description here

void testlist9()
{
    
    
	list<int> lt1;
	lt1.push_back(16);
	lt1.push_back(8);
	lt1.push_back(99);
	lt1.push_back(18);
	lt1.push_back(36);
	lt1.push_back(6);
	//不可以使用algorithm
	//sort(lt1.begin(), lt1.end());
	//可以使用list自己的sort进行排序
	lt1.sort();
	for (auto& e : lt1)
	{
    
    
		cout << e << " ";
	}
	cout << endl;
}

The result of compiling and running the code is:
Insert image description here

listThe iterator is a bidirectional iterator and cannot be used to adapt any iterator in the algorithm interface function sort函数. It can only be used list的sort函数.

3.Simulation implementation of list

3.1list source code

#pragma once
#include<iostream>
using namespace std;
namespace newspace
{
    
    
	template<class T>
	struct list_node
	{
    
    
		list_node<T>* _prev;
		list_node<T>* _next;
		T _val;

		list_node(const T& val = T())
			:_prev(nullptr)
			, _next(nullptr)
			, _val(val)
		{
    
    }
	};
	template<class T,class Ref,class Ptr>
	struct __list_iterator
	{
    
    
		typedef list_node<T> Node;
		Node* _node;
		typedef __list_iterator<T, Ref, Ptr> self;
		__list_iterator(Node* node)
			:_node(node)
		{
    
    }

		Ref operator*()
		{
    
    
			return _node->_val;
		}

		Ptr operator->()
		{
    
    
			return &_node->_val;
		}
		
		//__list_iterator<T,Ref,Ptr>& operator++()
		self& operator++()
		{
    
    
			_node = _node->_next;

			return *this;
		}
		__list_iterator<T, Ref, Ptr> operator++(int)
		//self operator++(int)
		{
    
    
			//__list_iterator<T, Ref, Ptr> tmp(*this);
			self tmp(*this);
			_node = _node->_next;

			return tmp;
		}
		__list_iterator<T, Ref, Ptr>& operator--()
		//self& operator--(int)
		{
    
    
			_node = _node->_prev;

			return *this;
		}
		//__list_iterator<T, Ref, Ptr> operator--(int)
		self operator--(int)
		{
    
    
			//__list_iterator<T, Ref, Ptr> tmp(*this);
			self tmp(*this);
			_node = _node->_prev;

			return tmp;
		}
		bool operator==(const __list_iterator<T, Ref, Ptr>& it)
		{
    
    
			return _node == it._node;
		}
		bool operator!=(const __list_iterator<T, Ref, Ptr>& it)
		{
    
    
			return _node != it._node;
		}
	};
	//template<class T>
	//struct __list_const_iterator
	//{
    
    
	//	typedef list_node<T> Node;
	//	Node* _node;

	//	__list_const_iterator(Node* node)
	//		:_node(node)
	//	{}

	//	const T& operator*()
	//	{
    
    
	//		return _node->_val;
	//	}

	//	__list_const_iterator<T>& operator++()
	//	{
    
    
	//		_node = _node->_next;

	//		return *this;
	//	}
	//	__list_const_iterator<T>& operator++(int)
	//	{
    
    
	//		__list_const_iterator<T> tmp(*this);
	//		_node = _node->_next;

	//		return *this;
	//	}
	//	bool operator==(const __list_const_iterator<T>& it)
	//	{
    
    
	//		return _node == it._node;
	//	}
	//	bool operator!=(const __list_const_iterator<T>& it)
	//	{
    
    
	//		return _node != it._node;
	//	}
	//};

	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;
		//这样设计太冗余了
		//typedef __list_const_iterator<T> const_iterator;
		
		//这样设计const迭代器是不行的,因为const迭代器期望修饰内容不被修改
		//这样设计迭代器本身不能修改
		//typedef const _list_iterator<T> const_iterator;
		//如何设计const对象的iterator
		//const T* ptr1;//ptr1本身不能修改
		//T* const ptr2;//ptr2指向的内容不能修改
		iterator begin()
		{
    
    
			return _head->_next;
		}
		iterator end()
		{
    
    
			return _head;
		}
		const_iterator begin()const
		{
    
    
			return _head->_next;
		}
		const_iterator end()const
		{
    
    
			return _head;
		}
		void empty_init()
		{
    
    
			_head = new Node;
			_head->_prev = _head;
			_head->_next = _head;
			_size = 0;
		}
		//构造函数
		list()
		{
    
    
			empty_init();
		}
		list(const list<T>& lt)
		{
    
    
			empty_init();
			for (auto& e : lt)
			{
    
    
				push_back(e);
			}
		}
		void swap(list<T>& lt)
		{
    
    
			std::swap(_head, lt._head);
			std::swap(_size, lt._size);
		}
		const list<T>& operator=(list<T> lt)
		{
    
    
			swap(lt);
			return *this;
		}
		void clear()
		{
    
    
			if (_head != nullptr)
			{
    
    
				iterator it = begin();
				while (it != end())
				{
    
    
					it = erase(it);
				}
				_size = 0;
			}
		}
		~list()
		{
    
    
			clear();
			delete _head;
			_head = nullptr;
			_size = 0;
		}
		//void push_back(const T& x)
		//{
    
    
		//	Node* tail = new Node(x);
		//	tail->_prev = _head->_prev;
		//	tail->_prev->_next = tail;

		//	_head->_prev = tail;
		//	tail->_next = _head;
		//}
		void push_back(const T& x)
		{
    
    
			//Node* tail = _head->_prev;
			//Node* newnode = new Node(x);
			//newnode->_prev = tail;
			//tail->_next = newnode;

			//_head->_prev = newnode;
			//newnode->_next = _head;
			insert(end(), x);
		}
		void push_front(const T& x)
		{
    
    
			insert(begin(), x);
		}
		void pop_back()
		{
    
    
			erase(end()--);
		}
		void pop_front()
		{
    
    
			erase(begin());
		}
		//在pos位置插入数据
		iterator insert(iterator pos, const T& x)
		{
    
    
			Node* cur = pos._node;
			Node* prev = cur->_prev;
			Node* newnode = new Node(x);
			
			prev->_next = newnode;
			newnode->_prev = prev;

			newnode->_next = cur;
			cur->_prev = newnode;
			++_size;
			return newnode;
		}
		//删除pos位置的数据
		iterator erase(iterator pos)
		{
    
    
			assert(pos != end());
			Node* cur = pos._node;
			Node* prev = cur->_prev;
			Node* next = cur->_next;

			prev->_next = next;
			next->_prev = prev;
			--_size;
			delete cur;

			return next;
		}
		size_t size()const
		{
    
    
			//const_iterator it = begin();
			//size_t size = 0;
			//while (it != end())
			//{
    
    
			//	size++;
			//	it++;
			//}
			//return size;
			return _size;
		}
	private:
		Node* _head;
		size_t _size;
	};

Guess you like

Origin blog.csdn.net/m0_74288306/article/details/132916531