当前位置: 首页 > news >正文

C++学习之路,从0到精通的征途:List类的模拟实现

目录

一.list的介绍

二.list的接口实现

1.结点

2.list结构

3.迭代器 

(1)begin

(2)end

 4.修改

(1)insert

(2)push_back

(3)push_front

(4)erase

(5)pop_back

(6)pop_front

(7)swap

(8)clear 

5.默认成员函数

(1)构造函数

(2)拷贝构造函数

(3)赋值重载

(4)析构函数

三.代码总览

list.h

test.cpp


 

一.list的介绍

源文档

二.list的接口实现

1.结点

template<class T>
struct list_node
{list_node* _prev;list_node* _next;T _data;// 由于数据类型由模板参数决定,所以缺省值给匿名对象list_node(const T& x = T()):_prev(nullptr),_next(nullptr),_data(x){}
};

        用一个结构体来封装结点,我们手动写默认构造函数以便在申请结点时调用。

2.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&, const T*> const_iterator;
private:// 哨兵位Node* _head;// 有效数据个数size_t _size = 0;
};

3.迭代器 

        list的迭代器与之前的string和vector不同,由于list的数据存储空间并不是连续的,所以我们无法再继续用原生指针来实现迭代器类型,++,解引用等操作并不能实现想要达到的目的,所以我们需要重载这些操作符,并将迭代器封装成一个新的类。

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* node):_node(node){}// 比较指向的结点是否相同bool operator!=(const Self& s){return _node != s._node;}bool operator==(const Self& s){return _node == s._node;}// Ref来控制iterator与const_iterator// Ref->T& -- iterator;// Ref->const T& -- const_iterator;// 获取结点存储的数据Ref 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;}// 为了可读性进行特殊处理 it->->_a1 被优化为 it->_a1// Ptr来控制iterator与const_iterator// Ptr->T* -- iterator// Ptr->const T* -- const_iteratorPtr operator->(){return &_node->_data;}
};

(1)begin

iterator begin()
{return iterator(_head->_next);
}
const_iterator begin() const
{return const_iterator(_head->_next);
}

(2)end

iterator end()
{// 返回尾结点的下一个结点,也就是哨兵位return iterator(_head);
}
const_iterator begin() const
{return const_iterator(_head->_next);
}

 4.修改

(1)insert

void insert(iterator pos, const T& x)
{// 申请新结点的空间,调用构造Node* newnode = new Node(x);// 断开旧连接,连接新结点Node* cur = pos._node;Node* prev = cur->_prev;// prev newnode curnewnode->_prev = prev;newnode->_next = cur;prev->_next = newnode;cur->_prev = newnode;++_size;
}

(2)push_back

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

(3)push_front

void push_front(const T& x)
{insert(begin(), x);
}

(4)erase

iterator erase(iterator pos)
{Node* cur = pos._node;Node* prev = cur->_prev;Node* next = cur->_next;prev->_next = next;next->_prev = prev;delete cur;--_size;//return iterator(next);// 为防止迭代器失效,返回删除后的下一个结点的迭代器// 单参数构造函数支持隐式转换return next;
}

        为防止erase后,pos依然指向被delete的结点从而导致迭代器失效,erase返回指向下一个结点的迭代器。 

(5)pop_back

void pop_back()
{erase(--end());
}

(6)pop_front

void pop_front()
{erase(begin());
}

(7)swap

void swap(list<T>& lt)
{std::swap(_head, lt._head);std::swap(_size, lt._size);
}

        交换哨兵位即可交换两个list。

(8)clear 

void clear()
{auto it = begin();while (it != end()){it = erase(it);}
}

        除了哨兵位,其他结点逐个erase。 

5.默认成员函数

(1)构造函数

空list申请哨兵位:empty_init

// 空list申请哨兵位
void empty_init()
{_head = new Node;_head->_prev = _head;_head->_next = _head;
}// 无参数构造
list()
{//_head = new Node;//_head->_prev = _head;//_head->_next = _head;empty_init();
}// initializer_list构造
list(std::initializer_list<T> il)
{empty_init();for (auto& e : il){push_back(e);}
}

(2)拷贝构造函数

list(const list<T>& lt)
{empty_init();for (auto& e : lt){push_back(e);}
}

        先申请哨兵位,再逐个尾插即可。

(3)赋值重载

list<T>& operator=(list<T> lt)
{swap(lt);return *this;
}

(4)析构函数

~list()
{clear();delete _head;_head = nullptr;
}

三.代码总览

list.h

#include<iostream>
#include<initializer_list>namespace my_list
{template<class T>struct list_node{list_node* _prev;list_node* _next;T _data;// 由于数据类型由模板参数决定,所以缺省值给匿名对象list_node(const T& x = T()):_prev(nullptr),_next(nullptr),_data(x){}};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* node):_node(node){}// 比较指向的结点是否相同bool operator!=(const Self& s){return _node != s._node;}bool operator==(const Self& s){return _node == s._node;}// Ref来控制iterator与const_iterator// Ref->T& -- iterator;// Ref->const T& -- const_iterator;// 获取结点存储的数据Ref 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;}// 为了可读性进行特殊处理 it->->_a1 被优化为 it->_a1// Ptr来控制iterator与const_iterator// Ptr->T* -- iterator// Ptr->const T* -- const_iteratorPtr operator->(){return &_node->_data;}};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;// 空list申请哨兵位void empty_init(){_head = new Node;_head->_prev = _head;_head->_next = _head;}// 无参数构造list(){//_head = new Node;//_head->_prev = _head;//_head->_next = _head;empty_init();}// initializer_list构造list(std::initializer_list<T> il){empty_init();for (auto& e : il){push_back(e);}}list(const list<T>& lt){empty_init();for (auto& e : lt){push_back(e);}}// lt2 = lt1list<T>& operator=(list<T> lt){swap(lt);return *this;}~list(){clear();delete _head;_head = nullptr;}void clear(){auto it = begin();while (it != end()){it = erase(it);}}void swap(list<T>& lt){std::swap(_head, lt._head);std::swap(_size, lt._size);}size_t size(){return _size;}iterator begin(){return iterator(_head->_next);}iterator end(){// 返回尾结点的下一个结点,也就是哨兵位return iterator(_head);}const_iterator begin() const{return const_iterator(_head->_next);}const_iterator end() const{return const_iterator(_head);}void push_back(const T& x){//Node* newnode = new Node(x);//Node* tail = _head->_prev;tail newnode _head//newnode->_prev = tail;//newnode->_next = _head;//tail->_next = newnode;//_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());}void insert(iterator pos, const T& x){// 申请新结点的空间,调用构造Node* newnode = new Node(x);// 断开旧连接,连接新结点Node* cur = pos._node;Node* prev = cur->_prev;// prev newnode curnewnode->_prev = prev;newnode->_next = cur;prev->_next = newnode;cur->_prev = newnode;++_size;}iterator erase(iterator pos){Node* cur = pos._node;Node* prev = cur->_prev;Node* next = cur->_next;prev->_next = next;next->_prev = prev;delete cur;--_size;//return iterator(next);// 为防止迭代器失效,返回删除后的下一个结点的迭代器// 单参数构造函数支持隐式转换return next;}private:// 哨兵位Node* _head;// 有效数据个数size_t _size = 0;};
}

test.cpp

#include"list.h"
using namespace std;namespace my_list
{void test_list1(){list<int> lt1;lt1.push_back(1);lt1.push_back(2);lt1.push_back(3);lt1.push_back(4);list<int>::iterator it = lt1.begin();while (it != lt1.end()){*it += 10;cout << *it << " ";++it;}cout << endl;lt1.push_back(1);lt1.push_back(2);lt1.push_front(3);lt1.push_front(4);for (auto& e : lt1){cout << e << " ";}cout << endl;lt1.pop_back();lt1.pop_front();for (auto& e : lt1){cout << e << " ";}cout << endl;cout << lt1.size() << endl;}void test_list2(){list<int> lt1;lt1.push_back(1);lt1.push_back(2);lt1.push_front(3);lt1.push_front(4);for (auto& e : lt1){cout << e << " ";}cout << endl;list<int> lt2(lt1);for (auto& e : lt1){cout << e << " ";}cout << endl;list<int> lt3;lt3 = lt1;for (auto& e : lt1){cout << e << " ";}}struct AA{int _a1;int _a2;AA(int a1 = 1, int a2 = 1):_a1(a1), _a2(a2){}};void test_list3(){list<int> lt1 = { 1,2,3,4 };for (auto& e : lt1){cout << e << " ";}cout << endl;list<AA> lt2 = { {1,1},{2,2},{3,3},{4,4} };list<AA>::iterator it = lt2.begin();while (it != lt2.end()){//cout << (*it)._a1 << ":" << (*it)._a2 << endl;//cout << it->->_a1 << ":" << it->->_a2 << endl;cout << it->_a1 << ":" << it->_a2 << endl;++it;}list<AA>::iterator lit = lt2.begin();while (lit != lt2.end()){cout << lit.operator->()->_a1 << ":" << lit.operator->()->_a2 << endl;++lit;}}
}int main()
{my_list::test_list3();return 0;
}

相关文章:

  • 【概念】什么是 JWT Token?
  • Gewechat启动启动报错
  • GPU加速-系统CUDA12.5-Windows10
  • 【开源】基于51单片机的简易智能楼道照明设计
  • 栈应用:括号匹配
  • 论文阅读:2025 arxiv Aligning to What? Limits to RLHF Based Alignment
  • Java大师成长计划之第4天:Java中的泛型
  • Yarn 安装与使用教程
  • 自动化测试方法有哪些?
  • 【软考-架构】14、软件可靠性基础
  • 深入解析 ASP.NET Core 中的 ResourceFilter
  • 从像素到实例:揭示图像分割如何改变视觉世界
  • 线程池单例模式
  • 【设计模式区别】装饰器模式和适配器模式区别
  • 单例设计模式之懒汉式以及线程安全问题
  • 从循环角度分析逐位分离法
  • 【人工智能之大模型】详述大模型中流水线并行(Pipeline Parallelism)的​GPipe推理框架?
  • 如何选择合适的探针台
  • C#中wpf程序中的x名空间详解
  • 微信小程序 template 模版详解
  • 《沙尘暴》:用贴近生活的影像和表演拍摄悬疑剧
  • 王一博赛车故障退赛冲上热搜,工作室回应:下次再战
  • 同款瑞幸咖啡竟差了6元,开了会员仍比别人贵!客服回应
  • 视频丨伊朗阿巴斯港一处油罐发生高强度爆炸:造成大面积破坏,伤亡不明
  • 出国留学、来华留学呈现双增新趋势,“00后留学生个性鲜明”
  • 经济日报:上海车展展现独特魅力