标签:链表 return eve front let 常见 双向 空间 log
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 }
标签:链表 return eve front let 常见 双向 空间 log
原文地址:http://www.cnblogs.com/33debug/p/6901165.html