移情别恋c++ ദ്ദി˶ー̀֊ー́ ) ——7.list(模仿实现) ...

农民  论坛元老 | 2024-8-31 04:32:12 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 1011|帖子 1011|积分 3033

1.前言

1.1list与vector的不同

   区别:list的迭代器底层和其他两个迭代器底层有很大区别,因为list的链式结构决定了与它们两个的不一样
  相同:迭代器用法大致一样,其他成员函数的使用也大致一样。
  
  vector与list都是STL中非常紧张的序列式容器,由于两个容器的底层结构不同,导致其特性以及 应用场景不同,其主要不同如下
  

  1.2 迭代器的分类 

   

  
 例子:

   可以得知list类型无法使用std中的sort函数,因为list的迭代器是双向的,而sort函数的迭代器参数是随机的 ,同理可以得出,string,vector,deque都可以使用std中的sort
   1.3 list的本质

   带头双向循环链表!!!!!!!!!!!!!!!!!!!
  2.list节点 

  
  1. template<class T>//记得每一个类前要写模板
  2. struct list_node       //struct和class一样均为类,不同的是struct中的所有成员均为公有(public)类型,可直接访问
  3. {
  4.         T data;
  5.         list_node<T>* next;
  6.         list_node<T>* prev;
  7.         list_node(const T& x=T())  //const T& x=T(),在没有给值的情况下,系统会通过T()自动生成一个类型匹配的值赋给x
  8.                 :data(x)
  9.                 ,next(nullptr)
  10.                 ,prev(nullptr)
  11.         {}
  12. };
复制代码
用类来封装一个一个结点,内里有两个指针,一个是指向下一个位置的指针,一个是指向前一个位置,还有一个用来存放数据的变量
  3.list类框架 

  
  1. template<class T>
  2. class List
  3. {
  4. public:
  5.         typedef List_node<T> node;//取别名
  6.     void empty_list()
  7.         {
  8.                 head = new Node;
  9.                 head->_next = head;
  10.                 head->_prev = head;
  11.         }
  12.         List()//构造函数
  13.         {
  14.             empty_list();
  15.         }
  16. private:
  17.      node*head;//头节点
  18.      size_t _size;
  19. }
复制代码
list类内里包含的是结点的指针,也就是哨兵位头节点的指针
  4.list迭代器

4.1 list迭代器框架

   这里的迭代器是用封装加运算符重载来实现的,由于迭代器也会有许多类型,以是我们使用模板的情势
  1. //T,T&,T*
  2. //T,const T&,const T*        //设定了两种迭代器
  3. template<class T,class Ref,class Ptr>//记得每一个类前要写模板,可设置多个模板参数
  4. struct list_iterator
  5. {
  6.         typedef list_node<T> node;
  7.         typedef list_iterator<T,Ref,Ptr> self;
  8.         node* node1;
  9.         list_iterator(node* node2)
  10.                 :node1(node2)
  11.         {}
  12. }
复制代码
4.2 list常用迭代器 

  
  1. //T,T&,T*
  2. //T,const T&,const T*        //设定了两种迭代器
  3. template<class T,class Ref,class Ptr>//记得每一个类前要写模板,可设置多个模板参数
  4. struct list_iterator
  5. {
  6.         typedef list_node<T> node;
  7.         typedef list_iterator<T,Ref,Ptr> self;
  8.         node* node1;
  9.         list_iterator(node* node2)
  10.                 :node1(node2)
  11.         {}
  12.         self& operator++()
  13.         {
  14.                 node1 = node1->next;
  15.                 return *this;           //模拟++
  16.         }
  17.         self& operator--()
  18.         {
  19.                 node1 = node1->prev;
  20.                 return *this;           //模拟--
  21.         }
  22.         Ref operator*()
  23.         {
  24.                 return node1->data;    //模拟指针解引用
  25.         }
  26.         Ptr operator->()
  27.         {
  28.                 return &node1->data;
  29.         }
  30.         bool operator!=(const self& S)
  31.         {
  32.                 return node1 != S.node1;
  33.         }
  34. };
复制代码
迭代器的每一个操作都接纳了运算符重载,着实这样看来还是指针在操作,只不外他不是直接的进行操作,而是换了一种方式
  5.list函数详解 

5.1插入和删除

  
  1. void push_back(const T& x)  //尾插
  2. {
  3.         insert(end(), x);
  4. }
  5. void push_front(const T& x)  //头插
  6. {
  7.         insert(begin(), x);
  8. }
  9. void pop_front()      //头删
  10. {
  11.         erase(begin());
  12. }
  13. void pop_back()      //尾删
  14. {
  15.         erase(--end());
  16. }
  17. iterator insert(iterator pos, const T& x)//在pos位置插入x
  18. {
  19.         node* it = pos.node1;
  20.         node* newnode = new node(x);
  21.         node* prev = it->prev;
  22.         prev->next = newnode;
  23.         newnode->prev = prev;
  24.         newnode->next = it;
  25.         it->prev = newnode;
  26.         ++_size;
  27.         return iterator(newnode);                    //返回新插入的元素的位置
  28. }
  29. iterator erase(iterator pos)
  30. {
  31.         node* it = pos.node1;
  32.         node* prev = it->prev;
  33.         node* next = it->next;
  34.         delete it;
  35.         prev->next = next;
  36.         next->prev = prev;
  37.         --_size;
  38.         return iterator(next);       //返回删除后的当前位置
  39. }
复制代码

  5.2  拷贝构造和赋值运算符重载

  
  1. list(const list<T>& it)    //i1(i2)
  2. {
  3.         int i = 0;
  4.         empty_list();  //初始化列表
  5.         for (auto e : it)  //相当于自动调用迭代器,并解引用,最后迭代器再++
  6.         {
  7.                 i = 1;
  8.                 push_back(e);
  9.         }
  10. }
  11. void swap(list<T>& it)
  12. {
  13.         std::swap(head, it.head);
  14.         std::swap(_size, it._size);
  15. }
  16. list operator=(list<T>it)// i1=i2      传参直接调用拷贝构造
  17. {
  18.         swap(it);
  19.         return *this;
  20. }
  21. size_t size()
  22. {
  23.         return _size;
  24. }
复制代码
5.3 list析构函数 

  
  1. ~list()
  2. {
  3.         clear();
  4.         delete head;
  5.         head = nullptr;
  6. }
  7. void clear()
  8. {
  9.         iterator it = begin();
  10.         while (it != end())
  11.         {
  12.                 it = erase(it);
  13.         }
  14. }
复制代码

  6.打印函数 

  
  1. //打印
  2. template<typename Container>
  3. void print_container(const Container& con)
  4. {
  5.         typename Container::const_iterator it = con.begin();
  6.         while (it != con.end())
  7.         {
  8.                 cout << *it << " ";
  9.                 ++it;
  10.         }
  11.         cout << endl;
  12. }
复制代码
这里用的是typename,原因在于编译器在编译的时间,会去Container内里去找const_iterator这个类型,但是Container是一个模板,并没有实例化,以是编译器也不知道怎么定义,以是就在编译的时间就过不了,但是我们在前面加一个typename就会告诉编译器,先过,后面再来实例化,这样就可以办理问题了
  
  适用于不知道list<T>中的T到底是什么类型时同一调用打印函数
  7.代码总览

  1. namespace zone
  2. {
  3.         template<class T>//记得每一个类前要写模板
  4.         struct list_node       //struct和class一样均为类,不同的是struct中的所有成员均为公有(public)类型,可直接访问
  5.         {
  6.                 T data;
  7.                 list_node<T>* next;
  8.                 list_node<T>* prev;
  9.                 list_node(const T& x=T())  //const T& x=T(),在没有给值的情况下,系统会通过T()自动生成一个类型匹配的值赋给x
  10.                         :data(x)
  11.                         ,next(nullptr)
  12.                         ,prev(nullptr)
  13.                 {}
  14.         };     
  15.         //T,T&,T*
  16.         //T,const T&,const T*        //设定了两种迭代器
  17.         template<class T,class Ref,class Ptr>//记得每一个类前要写模板,可设置多个模板参数
  18.         struct list_iterator
  19.         {
  20.                 typedef list_node<T> node;
  21.                 typedef list_iterator<T,Ref,Ptr> self;
  22.                 node* node1;
  23.                 list_iterator(node* node2)
  24.                         :node1(node2)
  25.                 {}
  26.                 self& operator++()
  27.                 {
  28.                         node1 = node1->next;
  29.                         return *this;           //模拟++
  30.                 }
  31.                 self& operator--()
  32.                 {
  33.                         node1 = node1->prev;
  34.                         return *this;           //模拟--
  35.                 }
  36.                
  37.                 Ref operator*()
  38.                 {
  39.                         return node1->data;    //模拟指针解引用
  40.                 }
  41.                 Ptr operator->()
  42.                 {
  43.                         return &node1->data;
  44.                 }
  45.                 bool operator!=(const self& S)
  46.                 {
  47.                         return node1 != S.node1;
  48.                 }
  49.         };
  50.         //
  51.         template<class T>//记得每一个类前要写模板
  52.         class list
  53.         {
  54.                 typedef list_node<T> node;
  55.             public:
  56.                         typedef list_iterator<T,T&,T*>  iterator;
  57.                         typedef list_iterator<T,const T&,const T*>  const_iterator;
  58.                         iterator begin()              //可读可写
  59.                         {
  60.                                 return iterator(head->next);
  61.                         }
  62.                         iterator end()
  63.                         {
  64.                                 return iterator(head);
  65.                         }
  66.                         const_iterator begin()const   //只可读,不可写
  67.                         {
  68.                                 return const_iterator(head->next);
  69.                         }
  70.                         const_iterator end()const
  71.                         {
  72.                                 return const_iterator(head);
  73.                         }
  74.                         void empty_list()
  75.                         {
  76.                                 head = new node;
  77.                                 head->next = head;
  78.                                 head->prev = head;
  79.                                 _size = 0;
  80.                         }//建立头节点
  81.                         list()
  82.                         {
  83.                                 empty_list();  //初始化列表
  84.                         }
  85.                         ~list()
  86.                         {
  87.                                 clear();
  88.                                 delete head;
  89.                                 head = nullptr;
  90.                         }
  91.                         void clear()
  92.                         {
  93.                                 iterator it = begin();
  94.                                 while (it != end())
  95.                                 {
  96.                                         it = erase(it);
  97.                                 }
  98.                         }
  99.                         void push_back(const T& x)
  100.                         {
  101.                                 insert(end(), x);
  102.                         }
  103.                         void push_front(const T& x)
  104.                         {
  105.                                 insert(begin(), x);
  106.                         }
  107.                         void pop_front()
  108.                         {
  109.                                 erase(begin());
  110.                         }
  111.                         void pop_back()
  112.                         {
  113.                                 erase(--end());
  114.                         }
  115.                         iterator insert(iterator pos, const T& x)//在pos位置插入x
  116.                         {
  117.                                 node* it = pos.node1;
  118.                                 node* newnode = new node(x);
  119.                                 node* prev = it->prev;
  120.                                 prev->next = newnode;
  121.                                 newnode->prev = prev;
  122.                                 newnode->next = it;
  123.                                 it->prev = newnode;
  124.                                 ++_size;
  125.                                 return iterator(newnode);                    //返回新插入的元素的位置
  126.                         }
  127.                         iterator erase(iterator pos)
  128.                         {
  129.                                 node* it = pos.node1;
  130.                                 node* prev = it->prev;
  131.                                 node* next = it->next;
  132.                                 delete it;
  133.                                 prev->next = next;
  134.                                 next->prev = prev;
  135.                                 --_size;
  136.                                 return iterator(next);       //返回删除后的当前位置
  137.                         }
  138.                         list(const list<T>& it)    //i1(i2)
  139.                         {
  140.                                 int i = 0;
  141.                                 empty_list();  //初始化列表
  142.                                 for (auto e : it)  //相当于自动调用迭代器,并解引用,最后迭代器再++
  143.                                 {
  144.                                         i = 1;
  145.                                         push_back(e);
  146.                                 }
  147.                         }
  148.                         void swap(list<T>& it)
  149.                         {
  150.                                 std::swap(head, it.head);
  151.                                 std::swap(_size, it._size);
  152.                         }
  153.                         list operator=(list<T>it)// i1=i2      传参直接调用拷贝构造
  154.                         {
  155.                                 swap(it);
  156.                                 return *this;
  157.                         }
  158.                         size_t size()
  159.                         {
  160.                                 return _size;
  161.                         }
  162.                        
  163.             private:
  164.                         node* head;
  165.                         size_t _size;
  166.         };
  167.         void test()
  168.         {
  169.                 list<int> arr; //调用class里的初始化列表
  170.                 arr.push_back(1);
  171.                 arr.push_back(2);
  172.                 arr.push_back(3);
  173.                 arr.push_back(4);
  174.                 arr.push_back(5);
  175.                 arr.pop_back();
  176.                 int i = 0;
  177.                 list<int> brr(arr);
  178.                 for (auto e : brr)
  179.                 {
  180.                         i = 1;
  181.                         cout << e << ' ';
  182.                 }
  183.         }
  184. }
复制代码


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

本帖子中包含更多资源

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

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

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

本版积分规则

农民

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