C++ list模拟实现


风晓
风晓 2024-01-08 14:48:33 53346 赞同 0 反对 0
分类: 资源
C++ list模拟实现
一、节点
template<class T>
struct list_node
{
list_node<T>* _next;
list_node<T>* _prev;
T _data;
 
list_node(const T& x = T())
:_next(nullptr)
, _prev(nullptr)
, _data(x)
{}
};
这段代码定义了一个模板结构list_node,它是一个双向链表的节点结构。
 
在这个结构中,有三个成员:
 
_next:这是一个指向下一个节点的指针。它的类型是list_node<T>*,表示它指向的是一个list_node类型的对象。
 
_prev:这是一个指向前一个节点的指针。它的类型也是list_node<T>*,表示它指向的是一个list_node类型的对象。
 
_data:这是节点存储的数据。它的类型是T,这是一个模板参数,表示数据可以是任何类型。
 
此外,这个结构还有一个构造函数list_node(const T& x = T()),它接受一个类型为T的参数x,并将x赋值给_data。这个构造函数的参数有一个默认值T(),表示如果在创建list_node对象时没有提供参数,那么_data将被初始化为T类型的默认值。同时,_next和_prev被初始化为nullptr,表示新创建的节点没有连接到任何其他节点。
 
二、 迭代器
template<class T,class Ref,class Ptr>
struct _list_iterator
{
typedef list_node<T> node;
typedef _list_iterator<T, Ref,Ptr> self;
node* _node;
 
_list_iterator(node* n)
:_node(n)
{}
 
Ref operator*()
{
return _node->_data;
}
 
Ptr operator->()
{
return &_node->_data;
}
 
self& operator++()
{
_node = _node->_next;
return *this;
}
 
self operator++(int)
{
self tmp(*this);
_node = _node->_prev;
return tmp;
}
 
self& operator--()
{
_node = _node->_prev;
return *this;
}
 
self operator--(int)
{
self tmp(*this);
_node = _node->_prev;
return tmp;
}
 
bool operator!=(const self& s)
{
return  _node != s._node;
}
 
bool operator==(const self& s)
{
return _node == s._node;
}
};
 
这段代码定义了一个模板结构_list_iterator,它是一个双向链表的迭代器。
 
在这个结构中,有以下几个部分:
 
typedef list_node<T> node;和typedef _list_iterator<T, Ref,Ptr> self;:这两行代码定义了两个类型别名,node代表链表节点的类型,self代表迭代器自身的类型。
 
typedef ListIterator<T, Ref, Ptr>的作用是定义了一个新的类型名ListIterator,这个类型名后面可以直接接模板参数,用于创建特定类型的迭代器。
 
例如,ListIterator<int, int&, int*>就是一个可以用于遍历int类型链表的迭代器,它的引用类型和指针类型也都是int的引用和指针。
 
这样做的好处是,我们可以根据需要创建不同类型的迭代器,而不需要为每一种类型都写一个新的迭代器类。这大大提高了代码的复用性和可维护性。
 
node* _node;:这是迭代器内部的一个私有成员,它是一个指向链表节点的指针,用于在链表中移动。
 
_list_iterator(node* n) : _node(n) {}:这是迭代器的构造函数,它接受一个节点指针作为参数,并将这个指针赋值给_node。
 
接下来是一些重载的操作符,它们使得我们可以像使用指针一样使用迭代器:
 
Ref operator*():这是解引用操作符,它返回当前迭代器指向的节点的数据。
 
Ptr operator->():这是箭头操作符,它返回当前迭代器指向的节点的数据的地址。
 
self& operator++()和self operator++(int):这是前置和后置的++操作符,它们使得迭代器向后移动一位。
 
self& operator--()和self operator--(int):这是前置和后置的--操作符,它们使得迭代器向前移动一位。
 
bool operator==(const self& s)和bool operator!=(const self& s):这是等于和不等于操作符,它们用于比较两个迭代器是否相等。
 
三、双向链表
template<class T>
class list
{
typedef list_node<T> node;
public:
typedef _list_iterator<T, T&, T*> iterator;
typedef _list_iterator<T, const T&, constT*>const_iterator;
 
iterator begin()
{
return iterator(_head->_next);
}
 
const_iterator begin() const
{
return const_iterator(_head->next);
}
 
iterator end()
{
return iterator(_head);
}
 
const_iterator end() const
{
return const_iterator(_head);
}
 
void empty_init()
{
_head = new node;
_head->_prev = _head;
_head->_next = _head;
}
 
list()
{
empty_init();
}
 
template <class Iterator>
list(Iterator first, Iterator last)
{
empty_init();
 
while (first != last)
{
push_back(*first);
++first;
}
}
 
void swap(list<T>& tmp)
{
std::swap(_head, tmp._head);
}
 
list(const list<T>& lt)
{
empty_init();
 
list<T> tmp(lt.begin(), lt.end());
swap(tmp);
}
 
list<T>& operator=(list<T> lt)
{
swap(lt);
return *this;
}
 
~list()
{
clear();
delete _head;
_head = nullptr;
}
 
void clear()
{
iterator it = begin();
while (it != end())
{
erase(it++);
}
}
 
void push_back(const T& x)
{
insert(end(), x);
}
 
void push_front(const T& x)
{
insert(begin(), x);
}
 
void pop_back()
{
erase(--end());
}
 
void pop_front()
{
erase(begin());
}
 
void insert(iterator pos, const T& x)
{
node* cur = pos._node;
node* prev = cur->_prev;
 
node* new_node = new node(x);
 
prev->_next = new_node;
new_node->_prev = prev;
new_node->_next = cur;
cur->_prev = new_node;
}
 
iterator erase(iterator pos)
{
assert(pos != end());
 
node* prev = pos._node->_prev;
node* next = pos._node->_next;
 
prev->_next = next;
next->_prev = prev;
delete pos._node;
 
return iterator(next);
}
 
private:
node* _head;
};
 
这段代码定义了一个模板类list,它是一个双向链表的实现。
 
在这个类中,有以下几个部分:
 
template<class T>
class list
{
    typedef list_node<T> node;
public:
typedef _list_iterator<T, T&, T*> iterator;
typedef _list_iterator<T, const T&, constT*>const_iterator;
这些行定义了一些类型别名,node代表链表节点的类型,iterator代表链表迭代器的类型,const_iterator代表常量链表迭代器的类型。
 
node* _head;:这是链表的头节点,它是一个私有成员。
 
接下来是一些成员函数:
 
iterator begin()和const_iterator begin() const:这两个函数返回链表的开始迭代器,也就是指向链表第一个元素的迭代器。
 
iterator end()和const_iterator end() const:这两个函数返回链表的结束迭代器,也就是指向链表尾部之后位置的迭代器。
 
void empty_init():这个函数用于初始化一个空的链表,链表的头节点指向自己。
 
list():这是链表的默认构造函数,它调用empty_init()来初始化一个空的链表。
 
list(Iterator first, Iterator last):这是链表的另一个构造函数,它接受两个迭代器参数,然后将这两个迭代器之间的元素添加到链表中。
 
void swap(list<T>& tmp):这个函数用于交换两个链表。
 
list(const list<T>& lt):这是链表的拷贝构造函数,它创建一个新的链表,然后将传入的链表的元素复制到新的链表中。
 
list<T>& operator=(list<T> lt):这是链表的赋值运算符,它使用了拷贝-交换技术,先创建一个临时链表,然后交换临时链表和当前链表。
 
~list():这是链表的析构函数,它首先调用clear()函数删除所有的元素,然后删除头节点。
 
void clear():这个函数用于删除链表中的所有元素。
 
void push_back(const T& x),void push_front(const T& x):这两个函数用于在链表的尾部和头部添加元素。
 
void pop_back(),void pop_front():这两个函数用于删除链表的尾部和头部的元素。
 
void insert(iterator pos, const T& x):这个函数用于在指定位置插入一个元素。
 
iterator erase(iterator pos):这个函数用于删除指定位置的元素。
 
四、测试代码
void TestList() {
hbr::list<int> l;
 
// 测试push_back和遍历
for (int i = 0; i < 5; ++i) {
l.push_back(i);
}
for (hbr::list<int>::iterator it = l.begin(); it != l.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
 
// 测试push_front
for (int i = 5; i < 10; ++i) {
l.push_front(i);
}
for (hbr::list<int>::iterator it = l.begin(); it != l.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
 
// 测试pop_back
l.pop_back();
for (hbr::list<int>::iterator it = l.begin(); it != l.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
 
// 测试pop_front
l.pop_front();
for (hbr::list<int>::iterator it = l.begin(); it != l.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
 
// 测试erase
hbr::list<int>::iterator it = l.begin();
++it; ++it; // 让迭代器指向第三个元素
l.erase(it);
for (hbr::list<int>::iterator it = l.begin(); it != l.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
 
// 测试insert
it = l.begin();
++it; // 让迭代器指向第二个元素
l.insert(it, 100);
for (hbr::list<int>::iterator it = l.begin(); it != l.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
}
 
 

如果您发现该资源为电子书等存在侵权的资源或对该资源描述不正确等,可点击“私信”按钮向作者进行反馈;如作者无回复可进行平台仲裁,我们会在第一时间进行处理!

评价 0 条
风晓L1
粉丝 1 资源 2038 + 关注 私信
最近热门资源
银河麒麟桌面操作系统备份用户数据  132
统信桌面专业版【全盘安装UOS系统】介绍  132
银河麒麟桌面操作系统安装佳能打印机驱动方法  122
银河麒麟桌面操作系统 V10-SP1用户密码修改  111
麒麟系统连接打印机常见问题及解决方法  35
最近下载排行榜
银河麒麟桌面操作系统备份用户数据 0
统信桌面专业版【全盘安装UOS系统】介绍 0
银河麒麟桌面操作系统安装佳能打印机驱动方法 0
银河麒麟桌面操作系统 V10-SP1用户密码修改 0
麒麟系统连接打印机常见问题及解决方法 0
作者收入月榜
1

prtyaa 收益393.62元

2

zlj141319 收益218元

3

1843880570 收益214.2元

4

IT-feng 收益210.13元

5

风晓 收益208.24元

6

777 收益172.71元

7

Fhawking 收益106.6元

8

信创来了 收益105.84元

9

克里斯蒂亚诺诺 收益91.08元

10

技术-小陈 收益79.5元

请使用微信扫码

加入交流群

请使用微信扫一扫!