当前位置:网站首页>list的模拟实现
list的模拟实现
2022-07-25 07:18:00 【'派派'】
目录
1.介绍
2.模拟实现
先看listd的实现原理,本质是一个带头双向循环链表。如图

2.1先构造Node结点
template<class T>
struct list_node
{
list_node<T>* _next;
list_node<T>* _prev;
T _data;
list_node(const T& val = T())//缺省的构造函数
:_next(nullptr)
, _prev(nullptr)
, _data(val) //存储数据
{}
};2.2构造迭代器
接下来要对结点进行操作,完成遍历,增删查改等等,可再构造一个结构体,存储上面Node的指针。也就是一个迭代器。如图
template<class T>
struct __list_iterator
{
typedef list_node<T> Node; //将上面结点重命名Node
typedef __list_iterator<T> self;//将这个结点命名为self
Node* _node; //存储上面结点的指针
__list_iterator(Node* node)
:_node(node)
{}
};对结点进行一些操作,通过迭代器完成。
T& operator*() //该迭代器不是原生指针,需重载*
{
return _node->_data;//
}
self& operator++() //前置++,返回下一个结点的地址
{
_node = _node->_next;
return *this;
}
self operator++(int)//后置++
{
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& it)
{
return _node != it._node;
}
bool operator==(const self& it)
{
return _node == it._node;
}
2.3构造list容器
list类中存储有结构体Node的地址
template<class T>
class list
{
public:
typedef __list_iterator<T> iterator;
typedef list_node<T> Node;
list()
{
_head = new Node();
_head->_next = _head;
_head->_prev = _head;
}
iterator begin()//
{
return iterator(_head->_next);//_head->next是指向首元素的,类型是Node<T>*,用
itreator接收了
//return _head->_next;//单参构造函数支持隐式类型的转换
}
iterator end()
{
return iterator(_head);
}
void push_back(const T& x)
{
Node* tail = _head->_prev;
Node* newnode = new Node(x);
tail->_next = newnode;
newnode->_prev = tail;
newnode->_next = _head;
_head->_prev = newnode;
}
private:
Node* _head;//存储结点的地址
};
通过上面的代码,就基本完成了一个list了。下面可以验证一下。

但假设T是自定义类型的话,例如:
struct AA
{
AA(int a1 = 0, int a2 = 0)
:_a1(a1)
, _a2(a2)
{}
int _a1;
int _a2;
};
void test_list2()
{
list<AA> lt;
lt.push_back(AA(1, 1));
lt.push_back(AA(2, 2));
lt.push_back(AA(3, 3));
lt.push_back(AA(4, 4));
list<AA>::iterator it = lt.begin();
while (it != lt.end())
{
cout << (*it)._a1 << "-"<< (*it)._a2 <<" ";//目前只能这样访问元素
++it;
}
cout << endl;
}即使重载了解引用--*,不能直接访问,因为*it 拿到的是 AA类型的数据。所以可以在重载一个->符号。
T* operator->()
{
//return &(operator*());
return &_node->_data;
}
cout << it->_a1 << "-" << it->_a2 << " ";但其实it->是指AA*,it->->本质是这样访问才是正确的,不过编译器做了优化。
2.4const_iterator的实现
例如:
void print_list(const list<int>& lt)
{
list<int>::const_iterator it = lt.begin();
while (it != lt.end())
{
//*it = 10; // 不允许修改
cout << *it << " ";
++it;
}
cout << endl;
}需要在写一个const_iterator的实现,那是不是要重新再写一份struct __list_iterator{},再对里面内容进行适当修改。其实二者有许多地方相似,可通过模版实现。
对list容器部分代码进行改动
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;
const_iterator begin() const
{
return const_iterator(_head->_next);
}
const_iterator end() const
{
return const_iterator(_head);
}
iterator begin()
{
return iterator(_head->_next);
//return _head->_next;
}
iterator end()
{
return iterator(_head);
}
...........
...........//其余函数实现
...........
}再对迭代器部分代码改动:
template<class T, class Ref, class Ptr>//Ref是T&,Ptr是T*,或者Ref是const T&,Ptr是
const T*,根据传过来的类型进行确定
struct __list_iterator
{
typedef list_node<T> Node;
typedef __list_iterator<T, Ref, Ptr> self;
Node* _node;
__list_iterator(Node* node)
:_node(node)
{}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
//return &(operator*());
return &_node->_data;
}
........
........//其余函数的实现
........
}//Ref是T&,Ptr是T*, 或者 Ref是const T&,Ptr是 const T*,根据传过来的类型进行确定
看图分析:


2.5其余函数的实现
void empty_init()
{
_head = new Node();
_head->_next = _head;
_head->_prev = _head;
}
template <class InputIterator>
list(InputIterator first, InputIterator last)//用一段迭代器区间完成构造
{
empty_init();
while (first != last)
{
push_back(*first);
++first;
}
}
void swap(list<T>& lt)
{
std::swap(_head, lt._head);
}
// lt2(lt1) -- 现代写法
list(const list<T>& lt)
{
empty_init();
list<T> tmp(lt.begin(), lt.end());
swap(tmp);
}
// lt2 = lt1
list<T>& operator=(list<T> lt)//值传递
{
swap(lt);
return *this;
}
~list()
{
clear();
delete _head;
_head = nullptr;
}
void clear()
{
iterator it = begin();
while (it != end())
{
it = erase(it);
}
}
void push_back(const T& x)
{
//Node* tail = _head->_prev;
//Node* newnode = new Node(x);
_head tail newnode
//tail->_next = newnode;
//newnode->_prev = tail;
//newnode->_next = _head;
//_head->_prev = newnode;
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* newNode = new Node(x);
Node* cur = pos._node;
Node* prev = cur->_prev;
prev->_next = newNode;
newNode->_prev = prev;
newNode->_next = cur;
cur->_prev = newNode;
return iterator(newNode);
}
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;
delete cur;
return iterator(next);
}补充:由上面代码可知,当插入新元素后,pos依旧指向原来的元素,但函数是返回指向新元素的指针。当删除元素后,当前pos所指向的空间已被销毁,函数返回的是被删除元素的下一个元素的地址。
边栏推荐
- 华为无线设备配置WPA2-802.1X-AES安全策略
- CEPH in hand, I have!
- paddlepaddle 34 调整模型的layer结构与forward流程(实现layer的增删改与forward的修改)
- 新库上线| CnOpenDataA股上市公司股东信息数据
- 2022天工杯CTF---crypto1 wp
- 章鱼网络 Community Call #1|开启 Octopus DAO 构建
- 线代(矩阵‘)
- leetcode刷题:动态规划06(整数拆分)
- Electronic Association C language level 2 60, integer parity sort (real question in June 2021)
- The relationship between Informatics, mathematics and Mathematical Olympiad (July 19, 2022) C
猜你喜欢

北京内推 | 微软STCA招聘NLP/IR/DL方向研究型实习生(可远程)

js无法获取headers中Content-Disposition

NLP hotspots from ACL 2022 onsite experience

Rongyun launched a real-time community solution and launched "advanced players" for vertical interest social networking

Oracle19采用自动内存管理,AWR报告显示SGA、PGA设置的过小了?

Wechat applet switchtab transmit parameters and receive parameters

章鱼网络 Community Call #1|开启 Octopus DAO 构建

OpenAtom XuperChain 开源双周报 |2022.7.11-2022.7.22

File operation-

Hierarchical reinforcement learning: a comprehensive survey
随机推荐
RPC通信原理与项目技术选型
Alibaba cloud image address & Netease cloud image
BOM overview
PADS导出gerber文件
OpenAtom XuperChain 开源双周报 |2022.7.11-2022.7.22
2022天工杯CTF---crypto1 wp
CodeForces 1417B Two Arrays
Devops has been practiced for many years. What is the most painful thing?
9大最佳工程施工项目管理系统
Default value of dart variable
DJI内推码(一码一用,限时内推)
【程序员2公务员】关于体制调研的一些常见问题总结
Two week learning results of machine learning
Enable the free pan domain SSL certificate for kubesphere cluster and realize the automatic update and distribution of certificates
Electronic Association C language level 2 60, integer parity sort (real question in June 2021)
Scavenging vultures or woodpeckers? How to correctly understand short selling
YOLOv7模型推理和训练自己的数据集
RPC communication principle and project technology selection
Luo min from qudian, prefabricate "leeks"?
paddlepaddle 34 调整模型的layer结构与forward流程(实现layer的增删改与forward的修改)