std之list

目录
前言:
一.list的介绍
二.list的模拟实现以及实现中所需要的细节
1.实现每个元素的类
2.主类
3.构造函数
4.push_back
5.迭代器函数以及迭代器类的实现
6.insert和erase
7.拷贝构造和operator=
结言:
前言:
我们今天讲一下list的内置函数以及list的模拟实现。在数据结构中我们学习了链表,之后我们还会根据我们所学的内容来实现stack和queue和priority_queue不过那都是后话了。今天我来给大家完整的讲一下list的内置函数以及一些常用的内置函数的实现。
一.list的介绍
二.list的模拟实现以及实现中所需要的细节
在简单介绍完之后list的大致内容后我们先来实现一下我们自己list的一个基本框架。list主要有3部分组成。一个是list每一个元素中的详细内容,还有一个就是存储链表的。以及一个迭代器的设置。
1.实现每个元素的类
template<class T>struct ListNode {T _date;ListNode<int>* _prev;ListNode<int>* _next;ListNode(const T node):_date(node),_prev(nullptr), _next ( nullptr){; }};
有人可能会好奇为什么我们使用struct而不是class呢?在我们的基础语法中我们提到了struct和class的区别。他们两个都能进行对类的定义,而有不同的是struct的基本类型是public而class的基本类型是private。所以这边我们可以用struct定义或者是在class中进行public。
这个类里面我们分别定义了_data,_prev_next我们用这三个变量实现对数据的存储。
2.主类
第二个类主要的就是实现我们对我们list的控制,基本上所有的操作都是在list中进行。
template<class T>class list{public:typedef ListNode<T> Node;private:Node* _ahead;};
在没有实现迭代器之前我们主要进行的工作就只有这些了。
3.构造函数
void empty_init(){_head = new Node(T());_head->_next = _head;_head->_prev = _head;}List(){empty_init();}
将这两部分分离的目的主要是empty_init函数后面会多次进行使用。
4.push_back
void push_back(const T& x){Node* newnode = new Node(x);Node* tail = _head->_prev;tail->_next = newnode;newnode->_next = _head;newnode->_prev = tail;_head->_prev = newnode;}
基本操作与我们在数据结构上学的链表几乎相同。
5.迭代器函数以及迭代器类的实现
template<class T,class Tqu,class Con>class ListIterator {typedef ListIterator<T, Tqu,Con> self;typedef ListNode<T> Node;public:Node* _node;ListIterator(Node* node):_node (node){}self& operator ++(){_node = _node->_next;return *this;}self& operator --(){_node = _node->prev;return *this;}self& operator ++(int){self tmp = _node;_node = _node->_next;return tmp;}bool operator!=(const self& it){return _node != it._node;}bool operator==(const self& it){return _node == it._node;}Tqu operator*(){return _node->_date;}};
在list中由于不是一块连续的空间导致我们不可以使用[]去访问,所以我们就不可以把迭代器单纯的看作是一个指针了。那么问题又来了那么我们要怎么去实现指针才能实现的内容呢?这时就需要用到我们的operator了。如上述代码所展示。
模板后面两个参数是T*和T&主要的作用是在增加const变量时不需要手动再写一个函数。
typedef ListIterator<T, T&, T*> iterator;typedef ListIterator<T, const T&,const T*> const_iterator;
iterator begin(){iterator tmp(_head->_next);return tmp;}iterator end(){iterator tmp(_head);return tmp;}const_iterator begin() const{iterator tmp(_head->_next);return tmp;}const_iterator end(){iterator tmp(_head);return tmp;}
这些就是我们迭代器所需要的内置类型函数了。
6.insert和erase
iterator insert(iterator pos,const T&x){Node* newnode = new Node(x);Node* cur = pos._node;Node* prev = pos._node->_prev;//prev newnode curnewnode->_next = cur;newnode->_prev = prev;prev->_next = newnode;cur->_prev = newnode;return iterator(newnode);}iterator erase(iterator pos){assert(pos != end());Node* cur = pos._node;Node* prev = pos._node->_prev;Node* next = cur->_next;//prev cur nextprev->_next = next;next->_prev = prev;delete cur;cur = nullptr;return iterator(next);}
这两个函数的作用主要是在指定位置插入数据,以及在指定位置删除数据。
7.拷贝构造和operator=
List(List<T>& lt){empty_init();for (auto& e : lt){push_back(e);}}list<T>& operator=(list<T> lt){swap(_head, lt._head);return *this;}
基本上也是很简单,需要注意的时候我们在进行拷贝构造的时候需要定义一个新的开年表所以我们需要对它进行初始化。
结言:
list与vetcor的实现思路基本上相似的。不过他们在内存上有着本质上的区别。他们两个各有各的好处。好了今天的内容就到此为止了。
