前言
我们在数据结构初阶阶段学过了链表,list的底层正是带头双向链表,本篇博客会主要讲解list的模拟实现,并且前期在数据结构讲解过的插入删除等操作,本篇博客不会重点讲解,list的迭代器是作为重点进行讲解。
list的构造
本篇模拟实现只实现了构造空的list。
template<class T>
struct ListNode
{
ListNode(T _data)
:data(_data)
,pre(nullptr)
,next(nullptr)
{}
ListNode()
:pre(nullptr)
, next(nullptr)
{}
T data;
ListNode* pre;
ListNode* next;
};
template<class T>
class list{
public:
typedef ListNode<T> Node;
list()
{
head = new Node();
head->next = head;
head->pre = head;
}
Node*head;
}
list iterator
在此阶段我们可以把迭代器理解为指针,但是list的指针又无法实现迭代器的功能,所以我们需要将list指针封装为迭代器,实现迭代器的所有功能。
template<class T,class Ref,class Ptr >
class IteratorList
{
public:
typedef ListNode<T> Node;
typedef IteratorList<T,Ref,Ptr> Self;
Node* _node;
IteratorList(Node* node)
{
_node = node;
}
Self& operator++()
{
_node = _node->next;
return *this;
}
Ref operator*()
{
return _node->data;
}
Ptr operator->()
{
return &(_node->data);
}
bool operator!=(const Self&node)
{
return _node != node._node;
}
bool operator==(const Self& node)
{
return _node == node._node;
}
Self& operator++(int)
{
IteratorList tmp = IteratorList(_node);
_node = _node->next;
return tmp;
}
};
模板中的Ref,Ptr在整体代码中会体现作用,它们是为了实现const_iterator和iterator的。需要重点讲解的是operator->,他的作用是当模板类型为自定义类型时,方便获取自定义类型中的数据。
例如:
struct student
{
student(const string& name="",const int& number=0)
:_name(name)
,_number(number)
{}
string _name;
int _number;
};
void test_list3()
{
bit::list<student> lt3;
lt3.push_back(student("张三", 100));
lt3.push_back(student("李四", 200));
lt3.push_back(student("王五", 300));
list<student>::iterator it = lt3.begin();
while (it != lt3.end())
{
//it->_name的本质时it.operator->()->_name,由于C++不允许两个->连用,所以省略了一个
cout << it->_name << " " << it->_number << endl;
++it;
}
}
模拟实现整体代码及测试代码
//stl_list.h
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
namespace bit
{
template<class T>
struct ListNode
{
ListNode(T _data)
:data(_data)
,pre(nullptr)
,next(nullptr)
{}
ListNode()
:pre(nullptr)
, next(nullptr)
{}
T data;
ListNode* pre;
ListNode* next;
};
template<class T,class Ref,class Ptr >
class IteratorList
{
public:
typedef ListNode<T> Node;
typedef IteratorList<T,Ref,Ptr> Self;
Node* _node;
IteratorList(Node* node)
{
_node = node;
}
Self& operator++()
{
_node = _node->next;
return *this;
}
Ref operator*()
{
return _node->data;
}
Ptr operator->()
{
return &(_node->data);
}
bool operator!=(const Self&node)
{
return _node != node._node;
}
bool operator==(const Self& node)
{
return _node == node._node;
}
Self& operator++(int)
{
IteratorList tmp = IteratorList(_node);
_node = _node->next;
return tmp;
}
};
template<class T>
class list
{
public:
typedef ListNode<T> Node;
typedef IteratorList<T,T&,T*> iterator;
typedef IteratorList<T, const T&, const T*> const_iterator;
list()
{
head = new Node();
head->next = head;
head->pre = head;
}
iterator begin()
{
return iterator(head->next);
}
iterator end()
{
return iterator(head);
}
void push_back(const T& x)
{
/*Node* node = new Node(x);
Node* cur = head;
while (cur->next != head)
{
cur = cur->next;
}
cur->next = node;
node->next = head;
head->pre = node;
node->pre = cur;*/
insert(end(), x);
}
iterator insert(iterator pos,const T& x)
{
Node* cur = pos._node;
Node* newnode = new Node(x);
Node* pre = cur->pre;
pre->next = newnode;
newnode->pre = pre;
newnode->next = cur;
cur->pre = newnode;
return iterator(newnode);
}
iterator earse(iterator pos)
{
assert(pos._node != head);
Node* cur = pos._node;
Node* pre = cur->pre;
Node* next = cur->next;
pre->next = next;
next->pre = pre;
delete cur;
return iterator(next);
}
iterator pop_back()
{
return earse(iterator(head->pre));
}
iterator pop_front()
{
return earse(begin());
}
void push_front()
{
insert(begin());
}
private:
Node* head;
};
struct student
{
student(const string& name="",const int& number=0)
:_name(name)
,_number(number)
{}
string _name;
int _number;
};
void test_list1()
{
list<int> Ls;
Ls.push_back(1);
Ls.push_back(5);
Ls.push_back(2);
Ls.push_back(3);
list<int>::iterator it = Ls.begin();
while (it != Ls.end())
{
cout << *it << " ";
++it;
}
}
void test_list2()
{
bit::list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
for (auto e : lt)
{
cout << e << endl;
}
bit::list<int>::iterator it = lt.begin();
lt.earse(it);
for (auto e : lt)
{
cout << e << endl;
}
}
void test_list3()
{
bit::list<student> lt3;
lt3.push_back(student("张三", 100));
lt3.push_back(student("李四", 200));
lt3.push_back(student("王五", 300));
list<student>::iterator it = lt3.begin();
while (it != lt3.end())
{
cout << it->_name << " " << it->_number << endl;
++it;
}
}
};