日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

STL--list的模拟实现

發布時間:2024/3/13 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 STL--list的模拟实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

List

  • list的迭代器
  • list鏈表
  • list的功能函數
  • list測試
    • 函數主體

要模擬實現list,必須要熟悉list的底層結構以及其接口的含義,通過上面的學習,這些內容已基本掌握,現
在我們來模擬實現list。

list的迭代器

List 的迭代器
迭代器有兩種實現方式,具體應根據容器底層數據結構實現:

  • 原生態指針,比如:vector
  • 將原生態指針進行封裝,因迭代器使用形式與指針完全相同,因此在自定義的類中必須實現以下
    方法:
  • 指針可以解引用,迭代器的類中必須重載operator*()
  • 指針可以通過->訪問其所指空間成員,迭代器類中必須重載oprator->()
  • 指針可以++向后移動,迭代器類中必須重載operator++()與operator++(int)
    至于operator–()/operator–(int)釋放需要重載,根據具體的結構來抉擇,雙向鏈表可
    以向前 移動,所以需要重載,如果是forward_list就不需要重載–
  • 迭代器需要進行是否相等的比較,因此還需要重載operator==()與operator!=()
    */
    迭代器實現原理簡要框架
  • 說明:因為list的迭代器會指向下一個節點,所以我們創建一個迭代器結構體,這個結構體成員函數就是一個一個節點的指針_node。該構造函數會通過一個傳遞過來的節點來構造對象
    迭代器代碼

    // <T, T&, T*> iterator// <T, const T&, const T*> const_iterator// 類設計的復用 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) const {return _node != s._node;}bool operator==(const self& s) const{return !(*this != s);}//實現運算符的重載,比如++,節點的指針++之后就指向連續空間的下一個了,就找不到下一個節點的指針了//因此需要運算符的重載//如節點的指針++就讓他指向下一個節點,并且返回這個迭代器Ref operator*() {//返回的是節點里數據的引用:為了保證可讀可寫,返回引用的話我也可以改變這個節點的值return _node->_date;//返回的是節點的數據}//前置++it.operator(&it)構成函數重載self& operator++() {_node = _node->_next;return *this;}//后置++it.operator(&it,0)構成函數重載self& operator++(int) {self tmp(*this);_node = _node->_next;return tmp;}//前置--it.operator(&it)構成函數重載//++it; -->it.operator++()self& operator--() {//前置++返回++之后的_node = _node->_prev;//指向下一個位置return *this;//返回下一個迭代器}//后置--it.operator(&it,0)構成函數重載self& operator--(int) {//后置++返回++之前的,出了作用域不在了,所以不能返回引用self tmp(*this);//保存之前的迭代器_node = _node->_prev;return tmp;}//返回data的指針,data的指針里才會有數據Ptr operator->() const{return &_node->_date;}};

    析構不需要寫,因為節點的生命周期是跟著鏈表走的,鏈表銷毀了節點才會銷毀
    迭代器不是管理一個節點,它是封裝這個節點之后讓我們用同樣的方式去遍歷這個鏈表,而不暴露里面的東西
    我們可以理解為迭代器就像是一個隔離層,屏蔽了里面實現的東西,但是外面的使用都是一樣的

    list鏈表

    (1)空容器構造函數(默認構造函數)
    構造一個空容器,不包含任何元素。
    (2)填充構造函數
    構造一個包含n個元素的容器。每個元素都是val的副本。
    (3)范圍構造器
    構造一個包含范圍為[first,last)的元素的容器,每個元素由該范圍內其對應元素以相同的順序構造。
    (4)復制構造函數
    用相同的順序構造一個容器,其中包含x中每個元素的副本。

    template<class T>class list {typedef _list_node<T> node;//節點public://迭代器 typedef _list_iterator<T, T&, T*> iterator;//const迭代器typedef _list_iterator<T, const T&,const T*> const_iterator;constlist() {_head = new node();_head->_next = _head;_head->_prev = _head;}//析構函數~list() {clear();//清除所有數據delete _head;//釋放頭節點}//將迭代器輸入到范圍中的初始位置和最終位置。使用的范圍是//[first,last),它包括first和last之間的所有元素,包//括first指向的元素,但last指向的元素。 //函數模板參數InputIterator應該是一個輸入迭代器類型,該類//型指向可以從其構造value_type對象的類型的元素template<class InputIterator>list(InputIterator first, InputIterator last){_head = new node;_head->_next = _head;_head->_prev = _head;while (first != last)//把first到last區間的數據拷貝到this鏈表{push_back(*first);++first;}}list(const list<T>& lt){_head = new node;_head->_next = _head;_head->_prev = _head;//調用list范圍構造器填充tmplist<T> tmp(lt.begin(), lt.end());//把this和tmp除頭節點外交換,出了作用域tmp釋放std::swap(_head, tmp._head);}//lt1 = lt2list<T>& operator=(list<T> lt){//假設l1 = l2//l1就是l2拷貝構造出來的,因此交換this和l兩個鏈表的頭節點即可//交換過后l1原來的值會在l里,l出了作用域會自動釋放(臨時對象)std::swap(_head, lt._head);return *this;}//拷貝構造一般寫法/*list(const list<T>& it) {)//拷貝構造(拷貝構造要支持深拷貝,否則析構的時候會有問題)//申請頭節點_head = new node();_head->_prev = _head;_head->_next = _head;//將it的每個數據尾插到this鏈表中const_iterator i = it.begin();while (i != it.end()) {push_back(*i);i++;}}*///將鏈表中所有數據清除void clear () {iterator it = begin();while (it != end()) {erase(it++);//不用++這里刪除自動往后移動}}//const迭代器const_iterator begin() const {return _head->_next;}const_iterator end() const {return _head->prev;}//一般迭代器//begin是第一個位置的迭代器,有節點的指針就能構造迭代器,只有鏈表才有節點的指針//begin和end都是鏈表實現的,迭代器是我傳過去一個節點,他構造一個迭代器結構體的對象iterator begin() {//迭代器不是節點的指針,它是一個該結構體的自定義類型//可以用節點的指針構造一個對象return iterator(_head->_next);//調用構造}iterator end() {return _head;}private://帶頭雙向循環鏈表node* _head;};

    list的功能函數

    //在pos前邊插入iterator insert(iterator pos,const T&x) {node* newnode = new node(x);node* cur = pos._node;node* prev = cur->_prev;cur->_prev = newnode;newnode->_next = cur;newnode->_prev = prev;prev->_next = newnode;return newnode;}iterator erase(iterator pos1) {assert(pos1 != end());node* pos = pos1._node;node* cur = pos->_next;node* prev = pos->_prev;cur->_prev = prev;prev->_next = cur;delete pos;return cur;}//頭插void push_front(const T& x){insert(begin(), x);}//尾刪void pop_back(){erase(--end());//--end尾節點}//頭刪void pop_front(){erase(begin());}void push_back(const T& x){node* newnode = new node(x);node* tail = _head->_prev;tail->_next = newnode;newnode->_prev = tail;newnode->_next = _head;_head->_prev = newnode;}

    list測試

    函數主體

    acc.h

    #pragma once #include<iostream> #include<algorithm> #include<assert.h> using namespace std; namespace td {template<class T>struct _list_node {T _date;_list_node<T>* _next;_list_node<T>* _prev;_list_node(const T& x = T()):_date(x), _next(nullptr), _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* node):_node(node){}//淺拷貝 不需要拷貝構造和析構Ref operator*()const {return _node->_date;}//前置++it.operator(&it)構成函數重載self& operator++() {_node = _node->_next;return *this;}//后置++it.operator(&it,0)構成函數重載self& operator++(int) {self tmp(*this);_node = _node->_next;return tmp;}//前置--it.operator(&it)構成函數重載self& operator--() {_node = _node->_prev;return *this;}//后置--it.operator(&it,0)構成函數重載self& operator--(int) {self tmp(*this);_node = _node->_prev;return tmp;}Ptr operator->() const{return &_node->_date;}bool operator!=(const self& s) const {return _node != s._node;}bool operator==(const self& s) const{return !(*this != 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&,const T*> const_iterator;list() {_head = new node();_head->_next = _head;_head->_prev = _head;}~list() {clear();delete _head;}void push_back(const T& x){node* newnode = new node(x);node* tail = _head->_prev;tail->_next = newnode;newnode->_prev = tail;newnode->_next = _head;_head->_prev = newnode;}template<class InputIterator>list(InputIterator first, InputIterator last){_head = new node;_head->_next = _head;_head->_prev = _head;while (first != last){push_back(*first);++first;}}list(const list<T>& lt){_head = new node;_head->_next = _head;_head->_prev = _head;list<T> tmp(lt.begin(), lt.end());std::swap(_head, tmp._head);}//lt1 = lt2list<T>& operator=(list<T> lt){std::swap(_head, lt._head);return *this;}/*list(const list<T>& it) {_head = new node();_head->_prev = _head;_head->_next = _head;const_iterator i = it.begin();while (i != it.end()) {push_back(*i);i++;}}*/void clear () {iterator it = begin();while (it != end()) {erase(it++);//不用++這里刪除自動往后移動}}const_iterator begin() const {return _head->_next;}const_iterator end() const {return _head->prev;}iterator begin() {return _head->_next;}iterator end() {return _head;}//在pos前邊插入iterator insert(iterator pos,const T&x) {node* newnode = new node(x);node* cur = pos._node;node* prev = cur->_prev;cur->_prev = newnode;newnode->_next = cur;newnode->_prev = prev;prev->_next = newnode;return newnode;}iterator erase(iterator pos1) {assert(pos1 != end());node* pos = pos1._node;node* cur = pos->_next;node* prev = pos->_prev;cur->_prev = prev;prev->_next = cur;delete pos;return cur;}//頭插void push_front(const T& x){insert(begin(), x);}//尾刪void pop_back(){erase(--end());//--end尾節點}//頭刪void pop_front(){erase(begin());}private:node* _head;}; }

    源.cpp

    #include"acc.h" namespace td {void test_list1(){list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);lt.push_front(0);// 遍歷方式1list<int>::iterator it = lt.begin();while (it != lt.end()){cout << *it << " ";++it;}cout << endl;list<int>::reverse_iterator rit = lt.rbegin();while (rit != lt.rend()){cout << *rit << " ";++rit;}cout << endl;// 遍歷方式2for (auto e : lt){cout << e << " ";}cout << endl;}void test_list2(){list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);list<int>::iterator pos = std::find(lt.begin(), lt.end(), 2);if (pos != lt.end()){lt.insert(pos, 20);}list<int>::iterator it = lt.begin();while (it != lt.end()){if (*it % 2 == 0){it = lt.erase(it);}else{++it;}}// 遍歷方式2for (auto e : lt){cout << e << " ";}cout << endl;} }namespace bit {void print_list(const list<int>& lt){list<int>::const_iterator it = lt.begin();while (it != lt.end()){// const T& it.operator*()//*it = 1;cout << *it << endl;++it;}cout << endl;}void test_list1(){list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);list<int>::iterator it = lt.begin();list<int>::const_iterator it = lt.begin();while (it == lt.end()){*it = 1;cout << *it << endl;++it;}cout << endl;for (auto e : lt){cout << e << " ";}cout << endl;}struct Point{int x;int y;};void test_list2(){list<Point> lt;lt.push_back({ 1, 2 });lt.push_back({ 3, 3 });lt.push_back({ 5, 6 });list<Point>::iterator it = lt.begin();list<Point>::const_iterator it = lt.begin();while (it != lt.end()){cout << it->x << ":" << it->y << endl;//cout << (*it).x << ":" << (*it).y << endl;++it;}cout << endl;}void test_list3(){list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);list<int> copy = lt;for (auto e : copy){cout << e << " ";}cout << endl;} }int main() {bit::test_list3();return 0; }

    總結

    以上是生活随笔為你收集整理的STL--list的模拟实现的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。