c++之List容器的模拟实现

打印 上一主题 下一主题

主题 1034|帖子 1034|积分 3102

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
注:终极代码以汇总的为准
1.前言

在之前的数据布局中,我们曾模拟实现过链表的数据布局,但是非常贫苦,全篇都袒露了链表的底层布局-----指针,但是从利用的角度,利用者并不关心你用的底层布局是啥,而且编写者也不肯意将所有的底层布局暴袒露来,为此,在此文章中,我们将充分发挥c++的上风,将指针包装一下,变为迭代器
2.根本框架的实现

根本布局包罗链表的创建,包罗链表结点的创建,结点的初始化,以及对底层布局----指针的封装,还有一些根本操作,例如++,==,!=,还有解引用操作等。
我们将造链表的文件放在List.h文件中,等下在test.cpp文件中进行测试。
如下代码是根本的布局代码:(具体功能没实现)
  1. #include <assert.h>
  2. namespace rens
  3. {
  4.         template<class T>
  5.         struct list_node              //定义结点结构
  6.         {
  7.                 list_node* <T> _next;
  8.                 list_node* <T> _prev;
  9.                 T _data;
  10.                 list_node(const T& x=T())
  11.                         :_next(nullptr)
  12.                         ,_prev(nullptr)
  13.                         ,_data(x)
  14.                 {}
  15.         };
  16. }
  17. template <class T>
  18. struct list_iterator
  19. {
  20.         typedef list_node<T> Node;
  21.         Node* _node;
  22.         list_iterator(Node* node)
  23.                 :_node(node)
  24.         {}
  25.         T& operator*()                  //模拟指针的解引用
  26.         {
  27.                 return _node->_data;        //返回的是数据,类型为T
  28.         }
  29.         T* operator->()                 //解引用的->,这个较为特殊
  30.         {
  31.                 return &_node->_data;
  32.         }
  33.         list_iterator<T>& operator++()
  34.         {
  35.                 _node = _node->_next;
  36.                 return *this;              //++操作返回的是下一个结点
  37.         }
  38.         bool operator!=(const list_iterator<T>& it)
  39.         {
  40.                 return this->_node != it._node;
  41.         }
  42.         bool operator==(const list_node<T>& it)
  43.         {
  44.                 return this->_node == it._node;
  45.         }
  46. };
  47. template <class T>
  48. class list
  49. {
  50.         typedef list_node<T> Node;
  51. public:
  52.         typedef list_iterator<T> iterator;
  53. private:
  54.         Node* _head;
  55.         size_t _size;
  56. };
复制代码
 但是,上述代码假如要是想遍历const对象是,由于我们的迭代器不是const迭代器,不能满足我们的需求,为此我们还要将上述代码cv一份,并改为const迭代器。
const迭代器代码如下:
  1. template <class T>
  2. struct const_list_iterator
  3. {
  4.         typedef list_node<T> Node;
  5.         Node* _node;
  6.         const_list_iterator(Node* node)
  7.                 :_node(node)
  8.         {}
  9.         const T& operator*()                  //模拟指针的解引用
  10.         {
  11.                 return _node->_data;        //返回的是数据,类型为T
  12.         }
  13.         const T* operator->()                 //解引用的->,这个较为特殊
  14.         {
  15.                 return &_node->_data;
  16.         }
  17.         const_list_iterator<T>& operator++()
  18.         {
  19.                 _node = _node->_next;
  20.                 return *this;              //++操作返回的是下一个结点
  21.         }
  22.         bool operator!=(const const_list_iterator<T>& it)
  23.         {
  24.                 return this->_node != it._node;
  25.         }
  26.         bool operator==(const const_list_iterator<T>& it)
  27.         {
  28.                 return this->_node == it._node;
  29.         }
  30. };
复制代码
但是,通过对比(对比图如下),我们发现这两段代码重复度太大了,仅仅是返回类型的区别,如许写未免太浪费,所以我们将其改造一下!
 

改造想法:既然我们的类型就是有无const的区别,那我们不妨利用模板,对其进行改造,添加一个Ref,即reference,引用&以及Ptr,即pointer,指针
为了方便改造,我们将原来的list_iterator<T>给typedef一下,省的总改!
 改造代码:
  1. template <class T, class Ref, class Ptr>
  2. struct list_iterator
  3. {
  4.         typedef list_node<T> Node;
  5.         typedef list_iterator<T, Ref, Ptr> self;
  6.         Node* _node;
  7.         list_iterator(Node* node)
  8.                 :_node(node)
  9.         {}
  10.         Ref operator*()                  //模拟指针的解引用
  11.         {
  12.                 return _node->_data;        //返回的是数据,类型为T
  13.         }
  14.         Ptr operator->()                 //解引用的->,这个较为特殊
  15.         {
  16.                 return &_node->_data;
  17.         }
  18.         self& operator++()           //前置++,返回的是引用, this指向的对象不销毁。
  19.         {
  20.                 _node = _node->_next;
  21.                 return *this;              //++操作返回的是下一个对象
  22.         }
  23.         self operator++(int)          //后置++,返回的是一个临时对象,tmp出函数就销毁了
  24.         {
  25.                 self tmp(*this);
  26.                 _node = _node->_next;
  27.                 return tmp;
  28.         }
  29.         self& operator--()
  30.         {
  31.                 _node = _node->_prev;
  32.                 return *this;
  33.         }
  34.         self operator--(int)
  35.         {
  36.                 self tmp(*this);
  37.                 _node = _node->_prev;
  38.                 return tmp;
  39.         }
  40.         bool operator!=(const self& it)
  41.         {
  42.                 return this->_node != it._node;
  43.         }
  44.         bool operator==(const self& it)
  45.         {
  46.                 return this->_node == it._node;
  47.         }
  48. };
复制代码
 别的功能的实现:
  1.         template <class T>
  2.         class list
  3.         {
  4.                 typedef list_node<T> Node;
  5.         public:
  6.                 //typedef list_iterator<T> iterator;
  7.                 typedef list_iterator<T, T&, T*> iterator;
  8.                 typedef list_iterator<T, const T&, const T*> const_iterator;
  9.                 iterator begin()
  10.                 {
  11.                         iterator it(_head->_next);      //我们的链表是双向循环链表,_head可以理解为哨兵结点
  12.                         return it;
  13.                 }
  14.                 iterator end()
  15.                 {
  16.                         return iterator(_head);
  17.                 }
  18.                 const_iterator begin()const        //加上const关键字表示该函数不会修改类的任何成员变量,即它是一个常量成员函数
  19.                 {
  20.                         return const_iterator(_head->_next);
  21.                 }
  22.                 const_iterator end()const
  23.                 {
  24.                         return const_iterator(_head);
  25.                 }
  26.                 void empty_init()
  27.                 {
  28.                         _head = new Node;
  29.                         _head->_next = _head;
  30.                         _head->_prev = _head;
  31.                         _size = 0;
  32.                 }
  33.                 list()
  34.                 {
  35.                         empty_init();
  36.                 }
  37.                 list(std::initializer_list<T> lt)
  38.                 {
  39.                         empty_init();
  40.                         for (auto& e : lt)
  41.                         {
  42.                                 push_back(e);
  43.                         }
  44.                 }
  45.                 //lt2(lt1)
  46.                 list(const list<T>& lt)
  47.                 {
  48.                         empty_init();
  49.                         for (auto& e : lt)
  50.                         {
  51.                                 push_back(e);
  52.                         }
  53.                 }
  54.                 //lt1=lt3
  55.                 list<T>& operator=(list<T> lt)
  56.                 {
  57.                         swap(lt);
  58.                         return *this;
  59.                 }
  60.                 void swap(list<T>& lt)
  61.                 {
  62.                         std::swap(_head, lt._head);
  63.                         std::swap(_size, lt._size);
  64.                 }
  65.                 ~list()
  66.                 {
  67.                         clear();
  68.                         delete _head;
  69.                         _head = nullptr;
  70.                 }
  71.                 void clear()
  72.                 {
  73.                         iterator it = begin();
  74.                         while (it != end())
  75.                         {
  76.                                 it = erase(it);
  77.                         }
  78.                 }
  79.                 size_t size()const
  80.                 {
  81.                         return _size;
  82.                 }
  83.                 void push_back(const T& x)
  84.                 {
  85.                         insert(end(), x);
  86.                 }
  87.                 void push_front(const T& x)
  88.                 {
  89.                         insert(begin(), x);
  90.                 }
  91.                 void pop_front()
  92.                 {
  93.                         erase(begin());
  94.                 }
  95.                 void pop_back()
  96.                 {
  97.                         erase(--end());
  98.                 }
  99.                 void insert(iterator pos, const T& x)
  100.                 {
  101.                         Node* cur = pos._node;
  102.                         Node* prev = cur->_prev;
  103.                         Node* newnode = new Node(x);
  104.                         prev->_next = newnode;
  105.                         newnode->_prev = prev;
  106.                         newnode->_next = cur;
  107.                         cur->_prev = newnode;
  108.                         ++_size;
  109.                 }
  110.                 iterator erase(iterator pos)
  111.                 {
  112.                         assert(pos != end());
  113.                         Node* cur = pos._node;
  114.                         Node* nextnode = cur->_next;
  115.                         Node* prevnode = cur->_prev;
  116.                         prevnode->_next = nextnode;
  117.                         nextnode->_prev = prevnode;
  118.                         delete cur;
  119.                         --_size;
  120.                         return iterator(nextnode);
  121.                 }
  122.         private:
  123.                 Node* _head;
  124.                 size_t _size;
  125.         };
  126. }
复制代码
3.代码的汇总及实现

这是List.h文件 
  1. #include <assert.h>#include <initializer_list>#include<iostream>#include<algorithm>namespace rens{        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)                {}        };        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)                {}                Ref operator*()                  //模拟指针的解引用                {                        return _node->_data;        //返回的是数据,类型为T                }                Ptr operator->()                 //解引用的->,这个较为特殊                {                        return &_node->_data;                }                self& operator++()           //前置++,返回的是引用, this指向的对象不烧毁。                {                        _node = _node->_next;                        return *this;              //++操作返回的是下一个对象                }                self operator++(int)          //后置++,返回的是一个临时对象,tmp出函数就烧毁了                {                        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 this->_node != it._node;                }                bool operator==(const self& it)                {                        return this->_node == it._node;                }        };        //template <class T>        //struct list_iterator        //{        //        typedef list_node<T> Node;        //        Node* _node;        //        list_iterator(Node* node)        //                :_node(node)        //        {}        //        //        T& operator*()                  //模拟指针的解引用        //        {        //                return _node->_data;        //返回的是数据,类型为T        //        }        //        //        T* operator->()                 //解引用的->,这个较为特殊        //        {        //                return &_node->_data;        //        }        //        //        list_iterator<T>& operator++()        //        {        //                _node = _node->_next;        //                return *this;              //++操作返回的是下一个结点        //        }        //        //        bool operator!=(const list_iterator<T>& it)        //        {        //                return this->_node != it._node;        //        }        //        //        bool operator==(const list_node<T>& it)        //        {        //                return this->_node == it._node;        //        }        //};        //template <class T>        //struct const_list_iterator        //{        //        typedef list_node<T> Node;        //        Node* _node;        //        const_list_iterator(Node* node)        //                :_node(node)        //        {}        //        //        const T& operator*()                  //模拟指针的解引用        //        {        //                return _node->_data;        //返回的是数据,类型为T        //        }        //        //        const T* operator->()                 //解引用的->,这个较为特殊        //        {        //                return &_node->_data;        //        }        //        //        const_list_iterator<T>& operator++()        //        {        //                _node = _node->_next;        //                return *this;              //++操作返回的是下一个结点        //        }        //        //        bool operator!=(const const_list_iterator<T>& it)        //        {        //                return this->_node != it._node;        //        }        //        //        bool operator==(const const_list_iterator<T>& it)        //        {        //                return this->_node == it._node;        //        }        //};        template <class T>
  2.         class list
  3.         {
  4.                 typedef list_node<T> Node;
  5.         public:
  6.                 //typedef list_iterator<T> iterator;
  7.                 typedef list_iterator<T, T&, T*> iterator;
  8.                 typedef list_iterator<T, const T&, const T*> const_iterator;
  9.                 iterator begin()
  10.                 {
  11.                         iterator it(_head->_next);      //我们的链表是双向循环链表,_head可以理解为哨兵结点
  12.                         return it;
  13.                 }
  14.                 iterator end()
  15.                 {
  16.                         return iterator(_head);
  17.                 }
  18.                 const_iterator begin()const        //加上const关键字表示该函数不会修改类的任何成员变量,即它是一个常量成员函数
  19.                 {
  20.                         return const_iterator(_head->_next);
  21.                 }
  22.                 const_iterator end()const
  23.                 {
  24.                         return const_iterator(_head);
  25.                 }
  26.                 void empty_init()
  27.                 {
  28.                         _head = new Node;
  29.                         _head->_next = _head;
  30.                         _head->_prev = _head;
  31.                         _size = 0;
  32.                 }
  33.                 list()
  34.                 {
  35.                         empty_init();
  36.                 }
  37.                 list(std::initializer_list<T> lt)
  38.                 {
  39.                         empty_init();
  40.                         for (auto& e : lt)
  41.                         {
  42.                                 push_back(e);
  43.                         }
  44.                 }
  45.                 //lt2(lt1)
  46.                 list(const list<T>& lt)
  47.                 {
  48.                         empty_init();
  49.                         for (auto& e : lt)
  50.                         {
  51.                                 push_back(e);
  52.                         }
  53.                 }
  54.                 //lt1=lt3
  55.                 list<T>& operator=(list<T> lt)
  56.                 {
  57.                         swap(lt);
  58.                         return *this;
  59.                 }
  60.                 void swap(list<T>& lt)
  61.                 {
  62.                         std::swap(_head, lt._head);
  63.                         std::swap(_size, lt._size);
  64.                 }
  65.                 ~list()
  66.                 {
  67.                         clear();
  68.                         delete _head;
  69.                         _head = nullptr;
  70.                 }
  71.                 void clear()
  72.                 {
  73.                         iterator it = begin();
  74.                         while (it != end())
  75.                         {
  76.                                 it = erase(it);
  77.                         }
  78.                 }
  79.                 size_t size()const
  80.                 {
  81.                         return _size;
  82.                 }
  83.                 void push_back(const T& x)
  84.                 {
  85.                         insert(end(), x);
  86.                 }
  87.                 void push_front(const T& x)
  88.                 {
  89.                         insert(begin(), x);
  90.                 }
  91.                 void pop_front()
  92.                 {
  93.                         erase(begin());
  94.                 }
  95.                 void pop_back()
  96.                 {
  97.                         erase(--end());
  98.                 }
  99.                 void insert(iterator pos, const T& x)
  100.                 {
  101.                         Node* cur = pos._node;
  102.                         Node* prev = cur->_prev;
  103.                         Node* newnode = new Node(x);
  104.                         prev->_next = newnode;
  105.                         newnode->_prev = prev;
  106.                         newnode->_next = cur;
  107.                         cur->_prev = newnode;
  108.                         ++_size;
  109.                 }
  110.                 iterator erase(iterator pos)
  111.                 {
  112.                         assert(pos != end());
  113.                         Node* cur = pos._node;
  114.                         Node* nextnode = cur->_next;
  115.                         Node* prevnode = cur->_prev;
  116.                         prevnode->_next = nextnode;
  117.                         nextnode->_prev = prevnode;
  118.                         delete cur;
  119.                         --_size;
  120.                         return iterator(nextnode);
  121.                 }
  122.         private:
  123.                 Node* _head;
  124.                 size_t _size;
  125.         };
  126. }
复制代码
这是test.cpp文件
  1. #include"list.h"
  2. using namespace std;
  3. void test1()
  4. {
  5.         rens::list<int> lt1;
  6.         lt1.push_back(1);
  7.         lt1.push_back(2);
  8.         lt1.push_back(3);
  9.         lt1.push_back(4);
  10.         rens::list<int>::iterator it1 = lt1.begin();
  11.         while (it1 != lt1.end())
  12.         {
  13.                 *it1 += 1;
  14.                 cout << *it1 << " ";
  15.                 ++it1;
  16.         }
  17.         cout << endl;
  18. }
  19. void print(const rens::list<int>& lt)
  20. {
  21.         // const迭代器本身可以修改,指向内容不能修改
  22.         rens::list<int>::const_iterator it = lt.begin();
  23.         while (it != lt.end())
  24.         {
  25.                 cout << *it << " ";
  26.                 ++it;
  27.         }
  28.         cout << endl;
  29. }
  30. struct A
  31. {
  32.         A(int a1=1,int a2=1)
  33.                 :_a1(a1)
  34.                 ,_a2(a2)
  35.         {}
  36.         int _a1;
  37.         int _a2;
  38. };
  39. void test2()
  40. {
  41.         rens::list<A> lt2;
  42.         lt2.push_back({ 1,1 });
  43.         lt2.push_back({ 2,2 });
  44.         lt2.push_back({ 3,3 });
  45.         lt2.push_back({ 4,4 });
  46.         rens::list<A>::iterator it = lt2.begin();
  47.         while (it != lt2.end())
  48.         {
  49.                 cout << it->_a1 << "," << it->_a2 << endl;
  50.                 ++it;
  51.         }
  52.         cout << endl;
  53.         rens::list<int> lt1;
  54.         lt1.push_back(1);
  55.         lt1.push_back(2);
  56.         lt1.push_back(3);
  57.         print(lt1);
  58. }
  59. void test3()
  60. {
  61.         rens::list<int> lt1;
  62.         lt1.push_back(1);
  63.         lt1.push_back(2);
  64.         lt1.push_back(3);
  65.         lt1.push_back(4);
  66.         for (auto e : lt1)
  67.         {
  68.                 cout << e << " ";
  69.         }
  70.         cout << endl;
  71.         lt1.push_front(5);
  72.         lt1.push_front(6);
  73.         for (auto e : lt1)
  74.         {
  75.                 cout << e << " ";
  76.         }
  77.         cout << endl;
  78.         lt1.pop_back();
  79.         lt1.pop_back();
  80.         lt1.pop_front();
  81.         lt1.pop_front();
  82.         for (auto e : lt1)
  83.         {
  84.                 cout << e << " ";
  85.         }
  86.         cout << endl;
  87.         lt1.pop_back();
  88.         lt1.pop_back();
  89.         for (auto e : lt1)
  90.         {
  91.                 cout << e << " ";
  92.         }
  93.         cout << endl;
  94. }
  95. void test4()
  96. {
  97.         rens::list<int> lt1;
  98.         lt1.push_back(1);
  99.         lt1.push_back(2);
  100.         lt1.push_back(3);
  101.         lt1.push_back(4);
  102.         for (auto e : lt1)
  103.         {
  104.                 cout << e << " ";
  105.         }
  106.         cout << endl;
  107.         rens::list<int> lt2(lt1);
  108.         lt1.clear();
  109.         for (auto e : lt1)
  110.         {
  111.                 cout << e << " ";
  112.         }
  113.         cout << endl;
  114.         for (auto e : lt2)
  115.         {
  116.                 cout << e << " ";
  117.         }
  118.         cout << endl;
  119.         rens::list<int> lt3 = { 10,20,30,40 };
  120.         lt1 = lt3;
  121.         for (auto e : lt1)
  122.         {
  123.                 cout << e << " ";
  124.         }
  125.         cout << endl;
  126. }
  127. int main()
  128. {
  129.     //test1();
  130.         //test2();
  131.         //test3();
  132.         test4();
  133.         return 0;
  134. }
复制代码
 


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

河曲智叟

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表