[C++]Deque with iterator實現細節
Deque with iterator實現細節
一、deque的中控器 deque是連續空間(至少邏輯上看來如此),連續線性空間總令我們聯想到array或vector。array無法成長,vector雖可成長,卻只能向尾端成長,而且其所謂的成長原是個假象,事實上是(1)另覓更大空間;(2)將原資料複製過去;(3)釋放原空間三部曲。如果不是vector每次配置新空間時都有留下一些餘裕,其成長假象所帶來的代價將是相當高昂。 deque系由一段一段的定量連續空間構成。一旦有必要在deque的前端或尾端增加新空間,便配置一段定量連續空間,串接在整個deque的頭端或尾端。deque的最大任務,便是在這些分段的定量連續空間上,維護其整體連續的假象,並提供隨機存取的藉口。避開了“重新配置、複製、釋放”的輪迴,代價則是複雜的迭代器架構。 受到分段連續線性空間的字面影響,我們可能以為deque的實現複雜度和vector相比雖不中亦不遠矣,其實不然。主要因為,既是分段連續線性空間,就必須有中央控制,而為了維持整體連續的假象,資料結構的設計及迭代器前進後退等操作都頗為繁瑣。deque的實現程式碼分量遠比vector或list都多得多。 deque採用一塊所謂的map(注意,不是STL的map容器)作為主控。這裡所謂map是一小塊連續空間,其中每個元素(此處稱為一個節點,node)都是指標,指向另一段(較大的)連續線性空間,稱為緩衝區。緩衝區才是deque的儲存空間主體。SGI STL 允許我們指定緩衝區大小,預設值0表示將使用512 bytes 緩衝區。 二、deque的迭代器 讓我們思考一下,deque的迭代器應該具備什麼結構,首先,它必須能夠指出分段連續空間(亦即緩衝區)在哪裡,其次它必須能夠判斷自己是否已經處於其所在緩衝區的邊緣,如果是,一旦前進或後退就必須跳躍至下一個或上一個緩衝區。為了能夠正確跳躍,deque必須隨時掌握管控中心(map)。所以在迭代器中需要定義:當前元素的指標,當前元素所在緩衝區的起始指標,當前元素所在緩衝區的尾指標,指向map中指向所在緩區地址的指標。 在進行迭代器的移動時,需要考慮跨緩衝區的情況。 過載前加(減),在實現後加(減)時,呼叫過載的前加(減)。 過載+=,實現+時,直接呼叫+=,實現-=時,呼叫+=負數,實現-時,呼叫-=. //當需要實現新的功能時,最好使用已經過載好的操作,即方便有安全。。。。 另外,deque在效率上來說是不夠vector好的,因此有時候在對deque進行sort的時候,需要先將元素移到vector再進行sort,然後移回來。
建構函式:根據緩衝區設定大小和元素個數,決定map的大小;給map分配空間,根據緩衝區的個數,分配緩衝區,預設指定一個緩衝區; 設定start和finish迭代器,滿足左閉右開的原則。 push_back:如果空間滿足,直接插入;不滿足,呼叫push_back_aux。 push_back_aux:先呼叫reverse_map_at_back,若符合某種條件,重換一個map;分配空間。 reserve_map_at_back:看看map有沒有滿,滿的話,呼叫reallocate_map。 reallocate_map:如果前端或後端pop過多,就會導致大量的空閒空間,如果是這種情況,則不用新分配空間,調整一下start的位置即可; 如果不夠,則需要重新申請空間。 pop:析構元素,如果是最後一塊還需要刪除空間。 erase:需要判斷,前面的元素少還是後面的元素少,移動較少的部分。 insert:判斷位置,如果為前端或後端直接呼叫push操作,否則,移動較少的一端。 deque的構造與記憶體管理: 由於deque的設計思想就是由一塊塊的快取區連線起來的,因此它的記憶體管理會比較複雜。插入的時候要考慮是否要跳轉快取區、是否要新建map節點(和vector一樣,其實是重新分配一塊空間給map,刪除原來空間)、插入後元素是前面元素向前移動還是後面元素向後面移動(誰小移動誰)。而在刪除元素的時候,考慮是將前面元素後移覆蓋需要移除元素的地方還是後面元素前移覆蓋(誰小移動誰)。移動完以後要析構冗餘的元素,釋放冗餘的快取區。
// // Deque.h // deque // // Created by 顏澤鑫 on 6/3/16. // Copyright © 2016 顏澤鑫. All rights reserved. // /* template <typename T> // template declaration. class DequeIterator { public: typedef DequeIterator iterator; typedef DequeIterator const_iterator; typedef random_access_iterator_tag iterator_category; // iterator tag. typedef T value_type; typedef T* pointer; typedef T& reference; typedef size_t size_type; typedef ptrdiff_t difference_type; typedef T** map_pointer; typedef DequeIterator self; T* cur; // pointer, pointing to the current element. T* first; // pointer, pointing to the first element in current buffer. T* last; // pointer, pointing to the last element in current buffer. map_pointer node; // pointer, pointing to the buffer. public: // constructor DequeIterator(Tx x, map_pointer y); DequeIterator(); DequeIterator(const iterator& x); public: // basic operation reference operator*() const; reference operator->() const; void set_node(map_pointer new_node); difference_type operator-(const self& x) const; // logic operation bool operator==(const self& x); bool operator!=(const self& x); bool operator<(const self& x); // random access self& operator++(); self operator++(int); self& operator--(); self operator--(int); self& operator+=(difference_type n); self& operator-=(difference_type n); self operator+(difference_type n) const; self operator-(difference_type n) const; reference operator[](differece_type n) const; */ #ifndef DequeIterator_ #define DequeIterator_ #include <iostream> #define BUFFER_SIZE 10 using namespace std; namespace Deque { template <typename T> class DequeIterator { public: typedef DequeIterator iterator; typedef const DequeIterator const_iterator; typedef random_access_iterator_tag iterator_category; // iterator tag. typedef T value_type; typedef T* pointer; typedef T& reference; typedef size_t size_type; typedef ptrdiff_t difference_type; typedef T** map_pointer; typedef DequeIterator self; T* cur; // pointer, pointing to the current element. T* first; // pointer, pointing to the first element in current buffer. T* last; // pointer, pointing to the last element in current buffer. map_pointer node; // pointer, pointing to the buffer. static size_t buffer_size() { return BUFFER_SIZE; } DequeIterator(T* x, map_pointer y) : cur(x), first(*y), last(*y + buffer_size()), node(y) {} DequeIterator() : cur(0), first(0), last(0), node(0) {} DequeIterator(const iterator& x) : cur(x.cur), first(x.first), last(x.last), node(x.node) {} // return *current;定義解引用操作 reference operator*() const { return *cur; } // return current;定義箭頭操作符 reference operator->() const { return cur; } // 判斷兩個迭代器是否相等 bool operator==(const self& x) const { return cur == x.cur; } // 判斷兩個迭代器是否不相等 bool operator!=(const self& x) const { return !(*this == x); } // 先比較map的node,在比較cur bool operator<(const self& x) const { return (node == x.node) ? (cur < x.cur) : (node < x.node); } // 將當前的迭代器設定為new_node,主要是設定node、first、last屬性的值 void set_node(map_pointer new_node) { node = new_node; first = *new_node; last = first + buffer_size(); } difference_type operator-(const self& x) const { return difference_type(buffer_size()) * (node - x.node - 1) + (cur - first) + (x.last - x.cur); } /** * Preincrement ++ * @return *this */ self& operator++() { ++cur; if (cur == last) { set_node(node + 1); cur = first; } return *this; } /** * Postincrement ++ * @param int just for placement. * @return temporary value */ self operator++(int) { self temp = *this; ++*this; return temp; } /** * Predecrement * @return *this */ self& operator--() { if (cur == first) { set_node(node - 1); cur = last; } --cur; return *this; } /** * Postdecrement -- * @param int just for placement * @return temporary value */ self operator--(int) { self temp = *this; --*this; return temp; } /** * define increment for n steps * inorder to realize random access * @param n steps * @return *this */ self& operator+=(difference_type n) { difference_type offset = n + (cur - first); if (offset >= 0 && offset < difference_type(buffer_size())) { cur += n; // The destination is in the same buffer. } else { // The destination is in the different buffer. difference_type node_offset = offset > 0 ? offset / difference_type(buffer_size()) : -difference_type((-offset - 1) / buffer_size()) - 1; // transfer to the right buffer node set_node(node + node_offset); // transfer to the right node cur = first + (offset - node_offset * difference_type(buffer_size())); } return *this; } // The same as the += and we change the n to negative. self& operator-=(difference_type n) { return * this += -n; } /** * increment n step but to get temporary object. * @param n steps * @return temporary object. */ self operator+(difference_type n) const { self tmp = *this; // call += operation. return tmp += n; } // The same as the += version and we change the n to negative. self operator-(difference_type n) const { self tmp = *this; return tmp -= n; } /** * subscript operation * random access * @param n steps * @return reference of object value. */ reference operator[](difference_type n) const { return *(*this + n); } }; #endif /* DequeIterator */ /* #include <new> #define MAP_SIZE 20 template <typename T> class deque { public: typedef T value_type; typedef value_type* pointer; typedef value_type& reference; typedef size_t size_type; typedef ptrdiff_t difference_type; typedef allocator<value_type> d_allocator; typedef allocator<pointer> m_allocator; typedef DequeIterator<T> iterator; typedef pointer* map_pointer; m_allocator map_allocator; d_allocator data_allocator; protected: static size_type buffer_size(); static size_type initial_map_size(); size_type max_size() const; protected: // memeory operation pointer allocate_node(); void deallocate_node(pointer n); void create_map_and_nodes(size_type num_elements); void reallocate_map(size_type nodes_to_add, bool add_at_front); void destroy_map_and_nodes(); void reserve_map_at_back(size_type nodes_to_add = 1); void reserve_map_at_front(size_type nodes_to_add = 1); protected: iterator start; iterator finish; map_pointer map; size_type map_size; public: deque(); ~deque(); iterator begin(); iterator end(); reference front(); reference back(); reference operator[](size_type n); size_type size() const; bool empty() const; public: // elements operation void push_back(const value_type& value); void push_back_aux(const value_type& value); void push_front(const value_type& value); void push_front_aux(const value_type& value); void pop_back(); void pop_front(); void pop_back_aux(); void pop_front_aux(); void insert(iterator pos, const value_type& value = value_type()); void insert_aux(iterator pos, const value_type& value); iterator erase(iterator pos); iterator erase(iterator first, iterator last); void clear(); }; */ #ifndef Deque #define Deque #include <new> #define MAP_SIZE 20 // we set the size of map is 20 template <typename T> class deque { public: typedef T value_type; typedef value_type* pointer; typedef value_type& reference; typedef size_t size_type; typedef ptrdiff_t difference_type; typedef allocator<value_type> d_allocator; typedef allocator<pointer> m_allocator; typedef DequeIterator<T> iterator; typedef pointer* map_pointer; m_allocator map_allocator; d_allocator data_allocator; protected: static size_type buffer_size() { return size_t(BUFFER_SIZE); } static size_type initial_map_size() { return 8; } size_type max_size() const { return size_type(-1); } // The functions are used to allocate and deallocate memory. /** * allocate memory for node. * @return pointer with memory. */ pointer allocate_node() { return data_allocator.allocate(buffer_size()); } /** * deallocate memory of node. * @param n pointer of node. */ void deallocate_node(pointer n) { data_allocator.deallocate(n, buffer_size()); } /** * create map and node for deque * @param num_elements the number of elements */ void create_map_and_nodes(size_type num_elements) { size_type num_nodes = num_elements / BUFFER_SIZE + 1; map_size = max(initial_map_size(), num_nodes + 2); // begin and last will be allocate more memory // to save time for inserting elements in deque. map = map_allocator.allocate(map_size); // set start and finish node in the middle of map. map_pointer nstart = map + (map_size - num_nodes) / 2; map_pointer nfinish = nstart + num_nodes - 1; for (map_pointer cur = nstart; cur <= nfinish; cur++) { *cur = allocate_node(); } start.set_node(nstart); finish.set_node(nfinish); start.cur = start.first; finish.cur = finish.first + num_elements % BUFFER_SIZE; } /** * reallocate map to reallocate nodes for map. * @param nodes_to_add The number of nodes to add. * @param add_at_front Add front or add back. */ void reallocate_map(size_type nodes_to_add, bool add_at_front) { size_type old_num_nodes = finish.node - start.node + 1; size_type new_num_nodes = old_num_nodes + nodes_to_add; map_pointer new_nstart; if (map_size > 2 * new_num_nodes) { // to balance map size. // just to avoid map size being off balance. new_nstart = map + (map_size - new_num_nodes) / 2 + (add_at_front ? nodes_to_add : 0); if (new_nstart < start.node) copy(start.node, finish.node + 1, new_nstart); else copy_backward(start.node, finish.node + 1, new_nstart + old_num_nodes); } else { size_type new_map_size = map_size + max(map_size, nodes_to_add) + 2; // allocate new memory for new map. map_pointer new_map = map_allocator.allocate(new_map_size); new_nstart = new_map + (new_map_size - new_num_nodes) / 2 + (add_at_front ? nodes_to_add : 0); // copy original map. copy(start.node, finish.node + 1, new_nstart); // reallocate original map. map_allocator.deallocate(map, map_size); // set new map and corresponding size. map = new_map; map_size = new_map_size; } // reset start and finish node. start.set_node(new_nstart); finish.set_node(new_nstart + old_num_nodes - 1); } protected: iterator start; iterator finish; map_pointer map; size_type map_size; public: /** * default constructor */ deque() : start(), finish(), map(0) { create_map_and_nodes(0); } /** * deconstructor */ ~deque() { for (map_pointer node = start.node; node <= finish.node; ++node) { // free memory of buffer. delete *node; } destroy_map_and_nodes(); } /** * reallocate map memory. */ void destroy_map_and_nodes() { map_allocator.deallocate(map, map_size); } iterator begin() { return start; } iterator end() { return finish; } reference front() { return *start; } reference back() { iterator temp = finish; --temp; return *temp; } /** * random access to get reference of element. * @param n steps * @return reference of elements. */ reference operator[](size_type n) { return start[difference_type(n)]; } size_type size() const { return finish - start; } bool empty() const { return finish == start; } /** * insert value in the back of deque. * @param t value. */ void push_back(const value_type& t) { // check if there is the enough memory to insert element if (finish.cur != finish.last - 1) { data_allocator.construct(finish.cur, t); // directly constructor. ++finish.cur; // adjust the finish map iterator. } else { // the special push back version. push_back_aux(t); } } /** * the speacial version of push_back. * @param t value. */ void push_back_aux(const value_type& t) { value_type t_copy = t; reserve_map_at_back(); *(finish.node + 1) = allocate_node(); // allocate new node buffer. map_allocator.construct(finish.cur, t_copy); // constructe. finish.set_node(finish.node + 1); // change finish iterator to point to new node. finish.cur = finish.first; // set finish state. } /** * reserve map at back. * @param nodes_to_add the number of nodes to add. */ void reserve_map_at_back(size_type nodes_to_add = 1) { if (nodes_to_add > map_size - (finish.node - map) - 1) // if the size of back deque // reallocate map at back. reallocate_map(nodes_to_add, false); } /** * insert elements in the front of deque. * @param t value. */ void push_front(const value_type& t) { if (start.cur != start.first) { // check if there is enough memory to allocate new element. data_allocator.construct(start.cur - 1, t); --start.cur; } else // if there isn't enough memory to insert new element // call the special push front version. push_front_aux(t); } /** * the special version of push front. * @param t value */ void push_front_aux(const value_type& t) { value_type t_copy = t; reserve_map_at_front(); *(start.node - 1) = allocate_node(); start.set_node(start.node - 1); start.cur = start.last - 1; data_allocator.construct(start.cur, t_copy); } void reserve_map_at_front(size_type nodes_to_add = 1) { if (nodes_to_add > start.node - map) reallocate_map(nodes_to_add, true); } /** * erase the back element of the deque. */ void pop_back() { if (!empty()) { if (finish.cur != finish.first) { data_allocator.destroy(finish.cur); --finish.cur; } else pop_back_aux(); } } /** * the special version of pop back. */ void pop_back_aux() { deallocate_node(finish.first); // reallocate tha last buffer. finish.set_node(finish.node - 1); finish.cur = finish.last - 1; data_allocator.destroy(finish.cur); // deconstructor element } /** * erase the front element */ void pop_front() { if (!empty()) { if (start.cur != start.last - 1) { data_allocator.destroy(start.cur); ++start.cur; } else pop_front_aux(); } } void pop_front_aux() { data_allocator.destroy(start.cur); deallocate_node(start.first); // free the first map iterator. start.set_node(start.node + 1); start.cur = start.first; } /** * random insert elements * @param position iterator of random position. * @param value * @return iterator. */ iterator insert(iterator position, const value_type& value = value_type()) { if (position == start) { push_front(value); return start; } else if (position == finish) { push_front(value); return finish; } else { return insert_aux(position, value); } } /** * speacial version of insert * @param pos random position. * @param x value * @return iterator of new element */ iterator insert_aux(iterator pos, const value_type& x) { difference_type index = pos - start; // 插入點之前的元素個數 value_type x_copy = x; if (index < size() / 2) // 如果插入點之前的元素個數比較少 { push_front(front()); // 在最前端加入與第一元素同值的元素 iterator front1 = start; // 以下標示記號,然後進行元素移動 ++front1; iterator front2 = front1; ++front2; pos = start + index; iterator pos1 = pos; ++pos1; copy(front2, pos1, front1); // 元素移動 } else // 插入點之後的元素個數比較少 { push_back(back()); // 在最尾端加入與最後元素同值的元素 iterator back1 = finish; // 以下標示記號,然後進行元素移動 --back1; iterator back2 = back1; --back2; pos = start + index; copy_backward(pos, back2, back1); // 元素移動 } *pos = x_copy; // 在插入點上設定新值 return pos; } /** * erase elements at random position. * @param pos position * @return the next element's iterator. */ iterator erase(iterator pos) { iterator next = pos; ++next; difference_type index = pos - start; // check operate at which side will cost less price. if (index < (size() >> 1)) { copy_backward(start, pos, next); pop_front(); } else { copy(next, finish, pos); pop_back(); } return start + index; } /** * erase elements at random position * between first iterator and last iterator. * @param first start position * @param last finish position * @return the next element's iterator. */ iterator erase(iterator first, iterator last) { if (first == start && last == finish) { // if erasing the whole deque. // just clear. clear(); return finish; } else { difference_type n = last - first; difference_type elems_before = first - start; if (elems_before < (size() - n) / 2) { copy_backward(start, first, last); // 向後移動前方元素(覆蓋清除區間) iterator new_start = start + n; // 標記deque的新起點 destroy(start, new_start); // 移動完畢,將冗餘的元素析構 // 以下將冗餘的緩衝區釋放 for (map_pointer cur = start.node; cur < new_start.node; ++cur) data_allocator.deallocate(*cur, buffer_size()); start = new_start; // 設定deque的新起點 } else // 如果清除區間後方的元素個數比較少 { copy(last, finish, first); // 向前移動後方元素(覆蓋清除區間) iterator new_finish = finish - n; // 標記deque的新尾點 destroy(new_finish, finish); // 移動完畢,將冗餘的元素析構 // 以下將冗餘的緩衝區釋放 for (map_pointer cur = new_finish.node + 1; cur <= finish.node; ++cur) data_allocator.deallocate(*cur, buffer_size()); finish = new_finish; // 設定deque的新尾點 } return start + elems_before; } } /** * clear every element in the deque. */ void clear() { // 以下針對頭尾以外的每一個緩衝區 for (map_pointer node = start.node + 1; node < finish.node; ++node) { // 將緩衝區內的所有元素析構 for (int i = 0; i != buffer_size() + 1; i++) { data_allocator.destroy(*node + i); } // 釋放緩衝區記憶體 data_allocator.deallocate(*node, buffer_size()); } if (start.node != finish.node) // 至少有頭尾兩個緩衝區 { for (auto iter = start.cur; iter != start.last; iter++) { data_allocator.destroy(iter); } for (auto iter = finish.first; iter != finish.cur; iter++) { data_allocator.destroy(iter); } // 以下釋放尾緩衝區。注意:頭緩衝區保留 data_allocator.deallocate(finish.first, buffer_size()); } else // 只有一個緩衝區 for (auto iter = start.cur; iter != finish.cur; iter++) { data_allocator.destroy(iter); // 將此唯一緩衝區內的所有元素析構 } // 注意:並不釋放緩衝區空間,這唯一的緩衝區將保留 finish = start; // 調整狀態 } }; #endif /* Deque_h */ }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
- 248
- 249
- 250
- 251
- 252
- 253
- 254
- 255
- 256
- 257
- 258
- 259
- 260
- 261
- 262
- 263
- 264
- 265
- 266
- 267
- 268
- 269
- 270
- 271
- 272
- 273
- 274
- 275
- 276
- 277
- 278
- 279
- 280
- 281
- 282
- 283
- 284
- 285
- 286
- 287
- 288
- 289
- 290
- 291
- 292
- 293
- 294
- 295
- 296
- 297
- 298
- 299
- 300
- 301
- 302
- 303
- 304
- 305
- 306
- 307
- 308
- 309
- 310
- 311
- 312
- 313
- 314
- 315
- 316
- 317
- 318
- 319
- 320
- 321
- 322
- 323
- 324
- 325
- 326
- 327
- 328
- 329
- 330
- 331
- 332
- 333
- 334
- 335
- 336
- 337
- 338
- 339
- 340
- 341
- 342
- 343
- 344
- 345
- 346
- 347
- 348
- 349
- 350
- 351
- 352
- 353
- 354
- 355
- 356
- 357
- 358
- 359
- 360
- 361
- 362
- 363
- 364
- 365
- 366
- 367
- 368
- 369
- 370
- 371
- 372
- 373
- 374
- 375
- 376
- 377
- 378
- 379
- 380
- 381
- 382
- 383
- 384
- 385
- 386
- 387
- 388
- 389
- 390
- 391
- 392
- 393
- 394
- 395
- 396
- 397
- 398
- 399
- 400
- 401
- 402
- 403
- 404
- 405
- 406
- 407
- 408
- 409
- 410
- 411
- 412
- 413
- 414
- 415
- 416
- 417
- 418
- 419
- 420
- 421
- 422
- 423
- 424
- 425
- 426
- 427
- 428
- 429
- 430
- 431
- 432
- 433
- 434
- 435
- 436
- 437
- 438
- 439
- 440
- 441
- 442
- 443
- 444
- 445
- 446
- 447
- 448
- 449
- 450
- 451
- 452
- 453
- 454
- 455
- 456
- 457
- 458
- 459
- 460
- 461
- 462
- 463
- 464
- 465
- 466
- 467
- 468
- 469
- 470
- 471
- 472
- 473
- 474
- 475
- 476
- 477
- 478
- 479
- 480
- 481
- 482
- 483
- 484
- 485
- 486
- 487
- 488
- 489
- 490
- 491
- 492
- 493
- 494
- 495
- 496
- 497
- 498
- 499
- 500
- 501
- 502
- 503
- 504
- 505
- 506
- 507
- 508
- 509
- 510
- 511
- 512
- 513
- 514
- 515
- 516
- 517
- 518
- 519
- 520
- 521
- 522
- 523
- 524
- 525
- 526
- 527
- 528
- 529
- 530
- 531
- 532
- 533
- 534
- 535
- 536
- 537
- 538
- 539
- 540
- 541
- 542
- 543
- 544
- 545
- 546
- 547
- 548
- 549
- 550
- 551
- 552
- 553
- 554
- 555
- 556
- 557
- 558
- 559
- 560
- 561
- 562
- 563
- 564
- 565
- 566
- 567
- 568
- 569
- 570
- 571
- 572
- 573
- 574
- 575
- 576
- 577
- 578
- 579
- 580
- 581
- 582
- 583
- 584
- 585
- 586
- 587
- 588
- 589
- 590
- 591
- 592
- 593
- 594
- 595
- 596
- 597
- 598
- 599
- 600
- 601
- 602
- 603
- 604
- 605
- 606
- 607
- 608
- 609
- 610
- 611
- 612
- 613
- 614
- 615
- 616
- 617
- 618
- 619
- 620
- 621
- 622
- 623
- 624
- 625
- 626
- 627
- 628
- 629
- 630
- 631
- 632
- 633
- 634
- 635
- 636
- 637
- 638
- 639
- 640
- 641
- 642
- 643
- 644
- 645
- 646
- 647
- 648
- 649
- 650
- 651
- 652
- 653
- 654
- 655
- 656
- 657
- 658
- 659
- 660
- 661
- 662
- 663
- 664
- 665
- 666
- 667
- 668
- 669
- 670
- 671
- 672
- 673
- 674
測試檔案:(gtest)
#include <iostream>
#include "gtest/gtest.h"
#include <deque>
#include "Deque.h"
using namespace std;
deque<int> deq_standard;
Deque::deque<int> deq_test;
TEST(TestOperation, Test_push_back) {
int n;
cout << "input a random number" << endl;
cin >> n;
for (int i = 0; i != n; i++) {
deq_standard.push_back(i);
deq_test.push_back(i);
}
EXPECT_EQ(deq_standard, deq_test);
}
TEST(TestOperation, Test_push_front) {
int n;
cout << "input a random number" << endl;
cin >> n;
for (int i = 0; i != n; i++) {
deq_standard.push_front(i);
deq_test.push_front(i);
}
EXPECT_EQ(deq_standard, deq_test);
}
TEST(TestOperation, Test_insert) {
deq_test.insert(deq_test.begin(), 3);
deq_standard.insert(deq_standard.begin(), 3);
deq_test.insert(deq_test.end(), 4);
deq_standard.insert(deq_standard.end(), 4);
Deque::deque<int>::iterator iter_t = deq_test.begin();
deque<int>::iterator iter_s = deq_standard.begin();
iter_t += 3;
iter_s += 3;
deq_test.insert(iter_t, 10);
deq_standard.insert(iter_s, 10);
EXPECT_EQ(deq_standard, deq_test);
}
TEST(TestOperation, Test_erase) {
Deque::deque<int>::iterator iter_t = deq_test.begin();
deque<int>::iterator iter_s = deq_standard.begin();
iter_t += 6;
iter_s += 6;
deq_test.erase(iter_t);
deq_standard.erase(iter_s);
EXPECT_EQ(deq_standard, deq_test);
}
TEST(TestOperation, Test_clear) {
deq_standard.clear();
deq_test.clear();
EXPECT_EQ(deq_standard, deq_test);
}
TEST(Test_all, test_all) {
int m, n;
cout << "input two random number" << endl;
cin >> m >> n;
for (int i = 0; i < m; i++) {
deq_standard.push_front(i);
deq_test.push_front(i);
}
EXPECT_EQ(deq_standard, deq_test);
EXPECT_EQ(deq_standard.size(), deq_test.size());
EXPECT_EQ(deq_standard[0], deq_test[0]);
deque<int>::iterator tmp1 = deq_standard.begin();
deque<int>::iterator tmp2 = tmp1;
Deque::deque<int>::iterator tmp1_t = deq_test.begin();
Deque::deque<int>::iterator tmp2_t = tmp1_t;
tmp2 = tmp2 + 5;
tmp2_t = tmp2_t + 5;
EXPECT_EQ(*(tmp2++), *(tmp2_t++));
++tmp2;
++tmp2_t;
EXPECT_EQ(*(tmp2++), *(tmp2_t++));
tmp2 = tmp2 - 2;
tmp2_t = tmp2_t - 2;
EXPECT_EQ(*(tmp2++), *(tmp2_t++));
tmp2 += 25;
tmp2_t += 25;
EXPECT_EQ(*(tmp2--), *(tmp2_t--));
--tmp2;
tmp2 -= 13;
--tmp2_t;
tmp2_t -= 13;
EXPECT_EQ(*tmp2, *tmp2_t);
EXPECT_EQ(tmp1[0], tmp1_t[0]);
EXPECT_EQ(tmp1[8], tmp1_t[8]);
EXPECT_EQ(tmp1[23], tmp1_t[23]);
EXPECT_EQ(tmp2[-3], tmp2_t[-3]);
}
int main(int argc, char **argv) {
printf("Running main() from gtest_main.cc\n");
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
測試
用valgrind測試記憶體和gtest進行單元測試。