模擬實現簡化版List叠代器&嵌入List
阿新 • • 發佈:2017-05-25
元素 sort 可能 節點數 != ring type 部分 分配
1、叠代器(iterators)概念
(1)叠代器是一種抽象的設計概念,其定義為:提供一種方法,使他能夠按順序遍歷某個聚合體(容器)所包含的所有元素,但又不需要暴露該容器的內部表現方式。
(2)叠代器是一種行為類似智能指針的對象, 而指針最常見的行為就是內 容提領和成員 訪問。 因此叠代器最重要的行為就是對operator*和operator->進行重載。
(3)STL的中心思想在於: 將數據容器和算法分開, 彼此獨立設計, 最後再以一貼膠合劑( iterator) 將它們撮合在一起。STL的叠代器是一個可遍歷STL容器全部或者部分數據。
2、叠代器的使用
以list和vector為例說明
1 #include<iostream> 2 #include<vector> 3 #include<list> 4 #include<algorithm> 5 #include<string> 6 using namespace std; 7 void Test1() 8 { 9 vector<int>v1; 10 v1. push_back(5) ; 11 v1. push_back(4) ; 12 v1. push_back(3) ; 13 v1. push_back(2) ; 14 v1. push_back(1) ; 15 //叠代器遍歷順序表 16 vector<int>: : iteratorit=v1. begin() ; 17 for(; it! =v1. end() ; ++it) 18 { 19 cout<<*it<<" "; 20 } 21 cout<<endl; 22 // STL的排序算法 23 sort(v1. begin() , v1. end() ) ; 24 it=v1. begin() ; 25 for(; it! =v1. end() ; ++it) 26 { 27 cout<<*it<<" "; 28 }29 cout<<endl; 30 } 31 voidTest2() 32 { 33 list<string>l1; 34 l1. push_back("xjh") ; 35 l1. push_back("zpw") ; 36 l1. push_back("yb") ; 37 l1. push_back("whb") ; 38 //叠代器遍歷鏈表 39 list<string>: : iteratorit=l1. begin() ; 40 for(; it! =l1. end() ; ++it) 41 { 42 cout<<*it<<" "; 43 } 44 cout<<endl; 45 // STL的替換算法 46 replace(l1. begin() , l1. end() , "xjh", "lcf") ; 47 it=l1. begin() ; 48 for(; it! =l1. end() ; ++it) 49 { 50 cout<<*it<<" "; 51 } 52 cout<<endl; 53 } 54 voidTest3() 55 { 56 list<string>l1; 57 l1. push_back("xjh") ; 58 l1. push_back("zpw") ; 59 l1. push_back("yb") ; 60 l1. push_back("whb") ; 61 //叠代器遍歷鏈表 62 list<string>: : iteratorit=l1. begin() ; 63 for(; it! =l1. end() ; ++it) 64 { 65 cout<<*it<<" "; 66 } 67 cout<<endl; 68 // STL的find算法查找叠代器區間的數據, 並返回找到節點的叠代器 69 it=find(l1. begin() , l1. end() , "yb") ; 70 if(it! =l1. end() ) 71 { 72 cout<<"find success: "<<*it<<endl; 73 //通過叠代器修改節點數據 74 *it="yls"; 75 } 76 it=find(l1. begin() , l1. end() , "yb") ; 77 if(it==l1. end() ) 78 { 79 cout<<"find failed"<<endl; 80 } 81 }
3、什麽是叠代器失效
以vector為例,當我們插入一個元素時它的預分配空間不夠時,它會重新申請一段新空間,將原空間上的元素 復制到新的空間上去,然後再把新加入的元素放到新空間的尾部,以滿足vector元素要求連續存儲的目的。而後原空間會被系統撤銷或征做他用,於是指向原 空間的叠代器就成了類似於“懸垂指針”一樣的東西,指向了一片非法區域。如果使用了這樣的叠代器會導致嚴重的運行時錯誤就變得很自然了。這也是許多書上敘 述vector在insert操作後“可能導致所有叠代器實效”的原因。但是想到這裏我不禁想到vector的erase操作的敘述是“會導致指向刪除元 素和刪除元素之後的叠代器失效”。
1 void PrintVector(vector<int>&v) 2 { 3 vector<int>: : iteratorit=v. begin() ; 4 for(; it! =v. end() ; ++it) 5 { 6 cout<<*it<<" "; 7 } 8 cout<<endl; 9 } 10 void Test1() 11 { 12 vector<int>v1; 13 v1. push_back(1) ; 14 v1. push_back(2) ; 15 v1. push_back(3) ; 16 v1. push_back(4) ; 17 v1. push_back(5) ; 18 v1. push_back(6) ; 19 v1. push_back(7) ; 20 v1. push_back(8) ; 21 PrintVector(v1) ; 22 //叠代器失效 23 vector<int>: : iteratorit=v1. begin() ; 24 while(it! =v1. end() ) 25 { 26 if(*it% 2 == 0) 27 it=v1. erase(it) ; 28 else 29 ++it; 30 } 31 PrintVector(v1) ; 32 } 33 void PrintList(list<int>&l1) 34 { 35 list<int>: : iteratorit=l1. begin() ; 36 for(; it! =l1. end() ; ++it) 37 { 38 cout<<*it<<" "; 39 } 40 cout<<endl; 41 } 42 void Test2() 43 { 44 list<int>l1; 45 l1. push_back(1) ; 46 l1. push_back(2) ; 47 l1. push_back(3) ; 48 l1. push_back(4) ; 49 l1. push_back(5) ; 50 l1. push_back(6) ; 51 l1. push_back(7) ; 52 l1. push_back(8) ; 53 PrintList(l1) ; 54 //叠代器失效 55 list<int>: : iteratorit=l1. begin() ; 56 while(it! =l1. end() ) 57 { 58 if(*it% 2 == 0) 59 it=l1. erase(it) ; 60 else 61 ++it; 62 } 63 PrintList(l1) ; 64 }
1 // 1.正向叠代器/反向叠代器 2 // 2.const/非const 3 void PrintList(const list<int>& l) 4 { 5 list<int>::const_iterator it = l.begin(); 6 while (it != l.end()) 7 { 8 cout<<*it<<" "; 9 ++it; 10 } 11 cout<<endl; 12 13 list<int>::const_reverse_iterator rit = l.rbegin(); 14 while (rit != l.rend()) 15 { 16 //*rit = 10; 17 cout<<*rit<<" "; 18 ++rit; 19 } 20 cout<<endl; 21 22 //list<int>::iterator it1 = l.end(); 23 //while (it1 != l.begin()) 24 //{ 25 // --it1; 26 // cout<<*it1<<" "; 27 //} 28 //cout<<endl; 29 }
歸納一下叠代器失效的類型:
(1)由於容器元素整體“遷移”導致存放原容器元素的空間不再有效,從而使得指向原空間的叠代器失效。
(2)由於刪除元素使得某些元素次序發生變化使得原本指向某元素的叠代器不再指向希望指向的元素。
4、模擬實現簡化版List叠代器&嵌入List
1 #pragma once 2 #include<iostream> 3 #include<assert.h> 4 using namespace std; 5 6 template <class T> 7 struct ItListNode 8 { 9 ItListNode<T>* _prev; // 指向前一個結點的指針 10 ItListNode<T>* _next; // 指向後一個結點的指針 11 T data; // 結點數據 12 ItListNode(const T& n) 13 :_prev(NULL) 14 ,_next(NULL) 15 ,data(n) 16 {} 17 }; 18 // List的叠代器 19 template <class T, class Ref, class Ptr> 20 class ListIterator 21 { 22 public: 23 typedef ItListNode<T> Node; 24 Node* node; // 指向節點的指針 25 // 這裏Ref、 Ptr模板參數主要是為了方便復用的方式實現const類型的叠代器ConstIterator 26 typedef ListIterator<T, Ref, Ptr> Self; 27 28 ListIterator(Node* n) 29 :node(n) 30 {} 31 Ref operator*() { 32 return node->data; 33 } 34 Ptr operator->() { 35 return &node->data; 36 //return &(operator*()); 37 } 38 Self& operator--() { 39 node = node->_prev; 40 return *this; 41 } 42 Self& operator--(int) { 43 Self tmp(*this); 44 node = node->_prev; 45 return tmp; 46 } 47 Self& operator++() { 48 node = node->_next; 49 return *this; 50 } 51 Self& operator++(int) { 52 Self tmp(*this); 53 node = node->_next; 54 return tmp; 55 } 56 bool operator != (const Self& s)const { 57 return node != s.node; 58 } 59 }; 60 61 //雙向循環鏈表 62 template <class T> 63 class List 64 { 65 typedef ItListNode<T> Node; 66 public: 67 68 // 定義叠代器、 const叠代器 69 typedef ListIterator<T, T&, T*> Iterator; 70 typedef ListIterator<T, const T&, const T*> ConIterator; 71 List() { 72 Head = BuyNode(T()); 73 Head->_prev = Head; 74 Head->_next = Head; 75 } 76 List(const T& l) 77 :Head(BuyNode(T())) 78 { 79 Head->_next = Head; 80 Head->_prev = Head; 81 ConIterator it = l.Begin(); 82 while (it != l.End()) { 83 this->PushBack(*it); 84 ++it; 85 } 86 } 87 List<T>& operator=(const T& l) { 88 if (*this != &l) { 89 swap(node, l.node); 90 } 91 return *this; 92 } 93 ~List() { 94 Clear(); 95 delete Head; 96 Head = NULL; 97 } 98 Iterator Begin() { 99 return Iterator(Head->_next); 100 } 101 ConIterator Begin()const { 102 return ConIterator(Head->_next); 103 } 104 Iterator End() { 105 return Iterator(Head); 106 } 107 ConIterator End()const { 108 return ConIterator(Head); 109 } 110 void Clear() { 111 Node*cur = Head->_next; 112 while (cur != Head) { 113 Node* next = cur->_next; 114 delete cur; 115 cur = next; 116 } 117 Head->_next = Head; 118 Head->_prev = Head; 119 } 120 void PushBack(const T& n) { 121 /*Node* tail = Head->_prev; 122 Node* tmp = BuyNode(n); 123 tail->_next = tmp; 124 tmp->_prev = tail; 125 tmp->_next = Head; 126 Head->_prev = tmp;*/ 127 Insert(End(), n); 128 } 129 void PopBack() { 130 Erase(--End()); 131 } 132 void PushFront(const T& n) { 133 Insert(Begin(), n); 134 } 135 void PopFront() { 136 Erase(Begin()); 137 } 138 // 在pos前插入一個節點 139 void Insert(Iterator pos, const T& n) { 140 Node* Next = pos.node; 141 Node* Prev = Next->_prev; 142 Node* Cur = BuyNode(n); 143 Prev->_next = Cur; 144 Cur->_prev = Prev; 145 Cur->_next = Next; 146 Next->_prev = Cur; 147 } 148 // 在pos前插入一個節點 149 Iterator Erase(Iterator pos) { 150 assert(pos.node&&pos.node != Head); 151 Node* Cur = pos.node; 152 Node* Prev = Cur -> _prev; 153 Node* Next = Cur -> _next; 154 delete Cur; 155 Prev->_next = Next; 156 Next->_prev = Prev; 157 return Iterator(Next); 158 } 159 Iterator Find(const T& n) { 160 Iteraptor* it = Begin(); 161 while (it != End()) { 162 if (*it == n) 163 return it; 164 } 165 return End(); 166 } 167 168 protected: 169 Node* BuyNode(const T& n) { 170 return new Node(n); 171 } 172 173 private: 174 Node* Head; 175 }; 176 177 // 1.測試List叠代器Iterator 178 void PrintList1(List<int>& l1) 179 { 180 List<int>::Iterator it = l1.Begin(); 181 for (; it != l1.End(); ++it) 182 { 183 cout << *it << " "; 184 } 185 cout << endl; 186 } 187 //2.測試List叠代器ConstIterator 188 void PrintMyList(const List<int>& L1) { 189 List<int>::ConIterator it1 = L1.Begin(); 190 while (it1 != L1.End()) { 191 cout << *it1 << " "; 192 ++it1; 193 } 194 cout << endl; 195 } 196 int main() { 197 List<int> L1; 198 L1.PushBack(1); 199 L1.PushBack(2); 200 L1.PushBack(3); 201 L1.PushBack(4); 202 PrintMyList(L1); 203 204 PrintList1(L1); 205 L1.PopBack(); 206 PrintMyList(L1); 207 208 L1.PushFront(4); 209 L1.PushFront(5); 210 L1.PushFront(6); 211 L1.PushFront(7); 212 PrintMyList(L1); 213 L1.PopFront(); 214 PrintMyList(L1); 215 216 getchar(); 217 return 0; 218 }
模擬實現簡化版List叠代器&嵌入List