├── .DS_Store ├── src ├── a.out ├── sub_allocator.cc ├── test_my_allocator.cc ├── .vscode │ ├── settings.json │ └── c_cpp_properties.json ├── iterator_traits.cc ├── list_find_test.cc ├── my_iter.cc ├── test_vector.cc └── my_allocator.h ├── images ├── 2.png ├── .DS_Store ├── 1-1.png ├── 1-2.png ├── 2-2.png ├── 2-3.png ├── 2-4.png ├── 3-1.png ├── 3-2.png ├── 4-1.png ├── 4-10.png ├── 4-11.png ├── 4-12.png ├── 4-13.png ├── 4-2.png ├── 4-3.png ├── 4-4.png ├── 4-5.png ├── 4-6.png ├── 4-7.png ├── 4-8.png ├── 4-9.png └── stl-overview.png ├── MindNote ├── .DS_Store ├── 序列式容器.mindnode │ ├── contents.xml │ ├── viewState.plist │ ├── QuickLook │ │ └── Preview.jpg │ └── style.mindnodestyle │ │ ├── metadata.plist │ │ └── contents.xml ├── 空间分配器.mindnode │ ├── contents.xml │ ├── viewState.plist │ ├── QuickLook │ │ └── Preview.jpg │ └── style.mindnodestyle │ │ ├── metadata.plist │ │ └── contents.xml ├── STL-源码剖析.mindnode │ ├── contents.xml │ ├── viewState.plist │ ├── QuickLook │ │ └── Preview.jpg │ └── style.mindnodestyle │ │ ├── metadata.plist │ │ └── contents.xml ├── STL概述与版本简介.mindnode │ ├── contents.xml │ ├── viewState.plist │ ├── QuickLook │ │ └── Preview.jpg │ └── style.mindnodestyle │ │ ├── metadata.plist │ │ └── contents.xml └── 迭代器(iterators).mindnode │ ├── contents.xml │ ├── viewState.plist │ ├── QuickLook │ └── Preview.jpg │ └── style.mindnodestyle │ ├── metadata.plist │ └── contents.xml └── README.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/.DS_Store -------------------------------------------------------------------------------- /src/a.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/src/a.out -------------------------------------------------------------------------------- /images/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/images/2.png -------------------------------------------------------------------------------- /images/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/images/.DS_Store -------------------------------------------------------------------------------- /images/1-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/images/1-1.png -------------------------------------------------------------------------------- /images/1-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/images/1-2.png -------------------------------------------------------------------------------- /images/2-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/images/2-2.png -------------------------------------------------------------------------------- /images/2-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/images/2-3.png -------------------------------------------------------------------------------- /images/2-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/images/2-4.png -------------------------------------------------------------------------------- /images/3-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/images/3-1.png -------------------------------------------------------------------------------- /images/3-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/images/3-2.png -------------------------------------------------------------------------------- /images/4-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/images/4-1.png -------------------------------------------------------------------------------- /images/4-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/images/4-10.png -------------------------------------------------------------------------------- /images/4-11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/images/4-11.png -------------------------------------------------------------------------------- /images/4-12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/images/4-12.png -------------------------------------------------------------------------------- /images/4-13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/images/4-13.png -------------------------------------------------------------------------------- /images/4-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/images/4-2.png -------------------------------------------------------------------------------- /images/4-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/images/4-3.png -------------------------------------------------------------------------------- /images/4-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/images/4-4.png -------------------------------------------------------------------------------- /images/4-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/images/4-5.png -------------------------------------------------------------------------------- /images/4-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/images/4-6.png -------------------------------------------------------------------------------- /images/4-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/images/4-7.png -------------------------------------------------------------------------------- /images/4-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/images/4-8.png -------------------------------------------------------------------------------- /images/4-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/images/4-9.png -------------------------------------------------------------------------------- /MindNote/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/MindNote/.DS_Store -------------------------------------------------------------------------------- /images/stl-overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/images/stl-overview.png -------------------------------------------------------------------------------- /MindNote/序列式容器.mindnode/contents.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/MindNote/序列式容器.mindnode/contents.xml -------------------------------------------------------------------------------- /MindNote/空间分配器.mindnode/contents.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/MindNote/空间分配器.mindnode/contents.xml -------------------------------------------------------------------------------- /MindNote/STL-源码剖析.mindnode/contents.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/MindNote/STL-源码剖析.mindnode/contents.xml -------------------------------------------------------------------------------- /MindNote/STL概述与版本简介.mindnode/contents.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/MindNote/STL概述与版本简介.mindnode/contents.xml -------------------------------------------------------------------------------- /MindNote/序列式容器.mindnode/viewState.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/MindNote/序列式容器.mindnode/viewState.plist -------------------------------------------------------------------------------- /MindNote/空间分配器.mindnode/viewState.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/MindNote/空间分配器.mindnode/viewState.plist -------------------------------------------------------------------------------- /MindNote/STL-源码剖析.mindnode/viewState.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/MindNote/STL-源码剖析.mindnode/viewState.plist -------------------------------------------------------------------------------- /src/sub_allocator.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using std::vector; 4 | 5 | int main() { 6 | vector > iv; 7 | } -------------------------------------------------------------------------------- /MindNote/STL概述与版本简介.mindnode/viewState.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/MindNote/STL概述与版本简介.mindnode/viewState.plist -------------------------------------------------------------------------------- /MindNote/序列式容器.mindnode/QuickLook/Preview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/MindNote/序列式容器.mindnode/QuickLook/Preview.jpg -------------------------------------------------------------------------------- /MindNote/空间分配器.mindnode/QuickLook/Preview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/MindNote/空间分配器.mindnode/QuickLook/Preview.jpg -------------------------------------------------------------------------------- /MindNote/迭代器(iterators).mindnode/contents.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/MindNote/迭代器(iterators).mindnode/contents.xml -------------------------------------------------------------------------------- /MindNote/STL-源码剖析.mindnode/QuickLook/Preview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/MindNote/STL-源码剖析.mindnode/QuickLook/Preview.jpg -------------------------------------------------------------------------------- /MindNote/迭代器(iterators).mindnode/viewState.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/MindNote/迭代器(iterators).mindnode/viewState.plist -------------------------------------------------------------------------------- /MindNote/STL概述与版本简介.mindnode/QuickLook/Preview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/MindNote/STL概述与版本简介.mindnode/QuickLook/Preview.jpg -------------------------------------------------------------------------------- /MindNote/迭代器(iterators).mindnode/QuickLook/Preview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landodo/Cpp-STL/HEAD/MindNote/迭代器(iterators).mindnode/QuickLook/Preview.jpg -------------------------------------------------------------------------------- /src/test_my_allocator.cc: -------------------------------------------------------------------------------- 1 | #include "my_allocator.h" 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int main() { 8 | int ia[5] = {0, 1, 2, 3, 4}; 9 | vector > iv(ia, ia+5); 10 | 11 | for (unsigned int i = 0; i < iv.size(); ++i) { 12 | cout << iv[i] << " "; 13 | } 14 | cout << endl; 15 | 16 | return 0; 17 | } -------------------------------------------------------------------------------- /src/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "*.tex": "tex", 4 | "map": "cpp", 5 | "new": "cpp", 6 | "vector": "cpp", 7 | "*.tcc": "cpp", 8 | "__split_buffer": "cpp", 9 | "__tree": "cpp", 10 | "bitset": "cpp", 11 | "initializer_list": "cpp", 12 | "list": "cpp", 13 | "memory": "cpp", 14 | "string": "cpp", 15 | "string_view": "cpp" 16 | } 17 | } -------------------------------------------------------------------------------- /src/iterator_traits.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | template 6 | struct iterator_traits { 7 | // 当迭代器是个pointer-to-const 8 | // 萃取出来的类型应该是 T 而非 const T 9 | typedef value_type; 10 | }; 11 | 12 | template 13 | typename iterator_traits::value_type 14 | func(I ite) { 15 | return *ite; 16 | } 17 | 18 | 19 | int main() { 20 | 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /src/list_find_test.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using std::list; 5 | 6 | int main() { 7 | list ls; 8 | list::iterator list_iter; 9 | ls.push_back(1); 10 | ls.push_back(2); 11 | ls.push_back(3); 12 | ls.insert(ls.begin(), 6); 13 | ls.unique(2); 14 | for (list_iter = ls.begin(); list_iter != ls.end(); list_iter++) { 15 | printf("%d ", ls.front()); 16 | ls.pop_front(); 17 | } 18 | ls.reverse(); 19 | return 0; 20 | } 21 | 22 | -------------------------------------------------------------------------------- /src/my_iter.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | template 6 | struct MyIter 7 | { 8 | typedef T value_type; 9 | T* ptr; 10 | MyIter(T* p = 0) : ptr(p) {} 11 | T& operator*() const { 12 | return *ptr; 13 | } 14 | // ... 15 | }; 16 | 17 | template 18 | typename I::value_type func(I ite) { 19 | return *ite; 20 | } 21 | 22 | int main() { 23 | MyIter ite(new int(8)); 24 | cout << func(ite); 25 | 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /MindNote/序列式容器.mindnode/style.mindnodestyle/metadata.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | author 6 | IdeasOnCanvas 7 | id 8 | 3F02E642-D05D-4C5E-8876-711B9447F761 9 | title 10 | Candyland 11 | version 12 | 3 13 | 14 | 15 | -------------------------------------------------------------------------------- /MindNote/空间分配器.mindnode/style.mindnodestyle/metadata.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | author 6 | IdeasOnCanvas 7 | id 8 | 3F02E642-D05D-4C5E-8876-711B9447F761 9 | title 10 | Candyland 11 | version 12 | 3 13 | 14 | 15 | -------------------------------------------------------------------------------- /MindNote/STL-源码剖析.mindnode/style.mindnodestyle/metadata.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | author 6 | IdeasOnCanvas 7 | id 8 | 3F02E642-D05D-4C5E-8876-711B9447F761 9 | title 10 | Candyland 11 | version 12 | 3 13 | 14 | 15 | -------------------------------------------------------------------------------- /MindNote/STL概述与版本简介.mindnode/style.mindnodestyle/metadata.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | author 6 | IdeasOnCanvas 7 | id 8 | 3F02E642-D05D-4C5E-8876-711B9447F761 9 | title 10 | Candyland 11 | version 12 | 3 13 | 14 | 15 | -------------------------------------------------------------------------------- /MindNote/迭代器(iterators).mindnode/style.mindnodestyle/metadata.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | author 6 | IdeasOnCanvas 7 | id 8 | 3F02E642-D05D-4C5E-8876-711B9447F761 9 | title 10 | Candyland 11 | version 12 | 3 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/test_vector.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using std::vector; 5 | 6 | int main() { 7 | vector vec; 8 | vector::iterator first; 9 | vector::iterator last; 10 | vector::iterator it; 11 | for (int i = 0; i < 10; ++i) { 12 | vec.push_back(i); 13 | } 14 | first = vec.begin(); 15 | last = vec.begin(); 16 | first ++; 17 | last++; 18 | last++; 19 | last++; 20 | for ( it = vec.begin(); it != vec.end() ; ++it) { 21 | printf("%d ", *it); 22 | } 23 | 24 | printf("\n, After:\n"); 25 | vec.erase(first, last); 26 | for ( it = vec.begin(); it != vec.end() ; ++it) { 27 | printf("%d ", *it); 28 | } 29 | return 0; 30 | } -------------------------------------------------------------------------------- /src/.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "Mac", 5 | "includePath": [ 6 | "${workspaceFolder}/", 7 | "usr/include", 8 | "usr/local/include", 9 | "/usr/include/c++/4.2.1" 10 | ], 11 | "macFrameworkPath": [ 12 | "/System/Library/Frameworks", 13 | "/Library/Frameworks" 14 | ], 15 | "intelliSenseMode": "clang-x64", 16 | "compilerPath": "/usr/bin/clang", 17 | "cStandard": "c11", 18 | "cppStandard": "c++17" 19 | } 20 | ], 21 | "version": 4 22 | } -------------------------------------------------------------------------------- /src/my_allocator.h: -------------------------------------------------------------------------------- 1 | #ifndef MY_ALLOCATOR_H 2 | #define MY_ALLOCATOR_H 3 | 4 | #include 5 | #include // ptrdiff_t sie_t 6 | #include // exit() 7 | #include // UINT_MAX 8 | #include // cerr 9 | 10 | namespace ldl 11 | { 12 | 13 | template 14 | inline T* _allocate(ptrdiff_t size, T*) { 15 | std::set_new_handler(0); 16 | T* tmp = (T*)(::operator new((size_t)(size * sizeof(T)))); 17 | if (tmp == 0) { 18 | std::cerr << "out od memory" << std::endl; 19 | exit(1); 20 | } 21 | return tmp; 22 | } 23 | 24 | template 25 | inline void _deallocate(T* buffer) { 26 | ::operator delete(buffer); 27 | } 28 | 29 | template 30 | inline void _construct(T1* p, const T2& value) { 31 | new(p) T1(value); // placement new. invoke ctor of T1. } 32 | } 33 | 34 | template 35 | inline void _destroy(T* ptr) { 36 | ptr->~T(); 37 | } 38 | 39 | template 40 | class allocator { 41 | public: 42 | typedef T value_type; 43 | typedef T* pointer; 44 | typedef const T* const_pointer; 45 | typedef T& reference; 46 | typedef const T& const_reference; 47 | typedef size_t size_type; 48 | typedef ptrdiff_t difference_type; 49 | 50 | // rebind allocator of type U 51 | template 52 | struct rebind { 53 | typedef allocator other; 54 | }; 55 | 56 | // hint used for locality. ref.[Austern],p189 57 | pointer allocate(size_type n, const void* hint=0) { 58 | return _allocate((difference_type)n, (pointer)0); 59 | } 60 | 61 | void deallocate(pointer p, size_type n) { 62 | _deallocate(p); 63 | } 64 | 65 | void construct(pointer p, const T& value) { 66 | _construct(p, value); 67 | } 68 | 69 | void destroy(pointer p) { 70 | _destroy(p); 71 | } 72 | 73 | pointer address(reference x) { 74 | return (pointer)&x; 75 | } 76 | 77 | const_pointer const_address(const_reference x) { 78 | return (const_pointer)&x; 79 | } 80 | 81 | size_type max_size() const { 82 | return size_type(UINT_MAX/sizeof(T)); 83 | } 84 | }; 85 | 86 | 87 | }; // namespace ldl 88 | #endif // MY_ALLOCATOR_H 89 | -------------------------------------------------------------------------------- /MindNote/序列式容器.mindnode/style.mindnodestyle/contents.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | allowNodeStrokeColorVariation 6 | 7 | backgroundColor 8 | {0.983000, 0.970000, 0.973000, 1.000000} 9 | baseSubnode 10 | 11 | shapeStyle 12 | 13 | borderStrokeStyle 14 | 15 | color 16 | {0.494000, 0.757000, 0.921000, 1.000000} 17 | dash 18 | 0 19 | width 20 | 6 21 | 22 | fillColor 23 | {1.000000, 1.000000, 1.000000, 1.000000} 24 | shapeType 25 | 0 26 | 27 | strokeStyle 28 | 29 | color 30 | {0.494000, 0.757000, 0.921000, 1.000000} 31 | dash 32 | 0 33 | width 34 | 6 35 | 36 | titleStyle 37 | 38 | alignment 39 | 0 40 | bold 41 | 42 | color 43 | {0.275000, 0.082000, 0.208000, 1.000000} 44 | fontName 45 | ArialRoundedMTBold 46 | fontSize 47 | 18 48 | italic 49 | 50 | 51 | 52 | crossConnections 53 | 54 | 55 | arrowStyle 56 | 57 | endArrow 58 | 3 59 | startArrow 60 | 3 61 | 62 | pathStyle 63 | 64 | strokeStyle 65 | 66 | color 67 | {0.992000, 0.357000, 0.227000, 1.000000} 68 | dash 69 | 0 70 | width 71 | 3 72 | 73 | 74 | titleStyle 75 | 76 | alignment 77 | 0 78 | bold 79 | 80 | color 81 | {0.000000, 0.000000, 0.000000, 1.000000} 82 | fontName 83 | HelveticaNeue 84 | fontSize 85 | 14 86 | italic 87 | 88 | strikethrough 89 | 90 | underline 91 | 92 | 93 | 94 | 95 | mainNodes 96 | 97 | 98 | shapeStyle 99 | 100 | borderStrokeStyle 101 | 102 | color 103 | {1.000000, 1.000000, 1.000000, 1.000000} 104 | dash 105 | 0 106 | width 107 | 2 108 | 109 | fillColor 110 | {0.908000, 0.060000, 0.276000, 1.000000} 111 | shapeType 112 | 3 113 | 114 | strokeStyle 115 | 116 | color 117 | {0.908000, 0.060000, 0.276000, 1.000000} 118 | dash 119 | 0 120 | width 121 | 4 122 | 123 | titleStyle 124 | 125 | alignment 126 | 1 127 | bold 128 | 129 | color 130 | {1.000000, 1.000000, 1.000000, 1.000000} 131 | fontName 132 | Helvetica 133 | fontSize 134 | 20 135 | italic 136 | 137 | 138 | 139 | 140 | subnodeColors 141 | 142 | 143 | shapeStyle 144 | 145 | borderStrokeStyle 146 | 147 | color 148 | {0.566, 0.812, 0.406, 1.000} 149 | 150 | fillColor 151 | {1.000, 1.000, 1.000, 1.000} 152 | 153 | strokeStyle 154 | 155 | color 156 | {0.566, 0.812, 0.406, 1.000} 157 | 158 | titleStyle 159 | 160 | color 161 | {0.275, 0.082, 0.208, 1.000} 162 | 163 | 164 | 165 | shapeStyle 166 | 167 | borderStrokeStyle 168 | 169 | color 170 | {0.227, 0.749, 0.737, 1.000} 171 | 172 | fillColor 173 | {1.000, 1.000, 1.000, 1.000} 174 | 175 | strokeStyle 176 | 177 | color 178 | {0.227, 0.749, 0.737, 1.000} 179 | 180 | titleStyle 181 | 182 | color 183 | {0.275, 0.082, 0.208, 1.000} 184 | 185 | 186 | 187 | shapeStyle 188 | 189 | borderStrokeStyle 190 | 191 | color 192 | {0.494, 0.757, 0.921, 1.000} 193 | 194 | fillColor 195 | {1.000, 1.000, 1.000, 1.000} 196 | 197 | strokeStyle 198 | 199 | color 200 | {0.494, 0.757, 0.921, 1.000} 201 | 202 | titleStyle 203 | 204 | color 205 | {0.275, 0.082, 0.208, 1.000} 206 | 207 | 208 | 209 | shapeStyle 210 | 211 | borderStrokeStyle 212 | 213 | color 214 | {0.559, 0.437, 0.964, 1.000} 215 | 216 | fillColor 217 | {1.000, 1.000, 1.000, 1.000} 218 | 219 | strokeStyle 220 | 221 | color 222 | {0.559, 0.437, 0.964, 1.000} 223 | 224 | titleStyle 225 | 226 | color 227 | {0.275, 0.082, 0.208, 1.000} 228 | 229 | 230 | 231 | shapeStyle 232 | 233 | borderStrokeStyle 234 | 235 | color 236 | {0.820, 0.127, 0.858, 1.000} 237 | 238 | fillColor 239 | {1.000, 1.000, 1.000, 1.000} 240 | 241 | strokeStyle 242 | 243 | color 244 | {0.820, 0.127, 0.858, 1.000} 245 | 246 | titleStyle 247 | 248 | color 249 | {0.275, 0.082, 0.208, 1.000} 250 | 251 | 252 | 253 | shapeStyle 254 | 255 | borderStrokeStyle 256 | 257 | color 258 | {0.781, 0.054, 0.301, 1.000} 259 | 260 | fillColor 261 | {1.000, 1.000, 1.000, 1.000} 262 | 263 | strokeStyle 264 | 265 | color 266 | {0.781, 0.054, 0.301, 1.000} 267 | 268 | titleStyle 269 | 270 | color 271 | {0.275, 0.082, 0.208, 1.000} 272 | 273 | 274 | 275 | subnodeLevels 276 | 277 | 278 | 279 | -------------------------------------------------------------------------------- /MindNote/空间分配器.mindnode/style.mindnodestyle/contents.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | allowNodeStrokeColorVariation 6 | 7 | backgroundColor 8 | {0.983000, 0.970000, 0.973000, 1.000000} 9 | baseSubnode 10 | 11 | shapeStyle 12 | 13 | borderStrokeStyle 14 | 15 | color 16 | {0.494000, 0.757000, 0.921000, 1.000000} 17 | dash 18 | 0 19 | width 20 | 6 21 | 22 | fillColor 23 | {1.000000, 1.000000, 1.000000, 1.000000} 24 | shapeType 25 | 0 26 | 27 | strokeStyle 28 | 29 | color 30 | {0.494000, 0.757000, 0.921000, 1.000000} 31 | dash 32 | 0 33 | width 34 | 6 35 | 36 | titleStyle 37 | 38 | alignment 39 | 0 40 | bold 41 | 42 | color 43 | {0.275000, 0.082000, 0.208000, 1.000000} 44 | fontName 45 | ArialRoundedMTBold 46 | fontSize 47 | 18 48 | italic 49 | 50 | 51 | 52 | crossConnections 53 | 54 | 55 | arrowStyle 56 | 57 | endArrow 58 | 3 59 | startArrow 60 | 3 61 | 62 | pathStyle 63 | 64 | strokeStyle 65 | 66 | color 67 | {0.992000, 0.357000, 0.227000, 1.000000} 68 | dash 69 | 0 70 | width 71 | 3 72 | 73 | 74 | titleStyle 75 | 76 | alignment 77 | 0 78 | bold 79 | 80 | color 81 | {0.000000, 0.000000, 0.000000, 1.000000} 82 | fontName 83 | HelveticaNeue 84 | fontSize 85 | 14 86 | italic 87 | 88 | strikethrough 89 | 90 | underline 91 | 92 | 93 | 94 | 95 | mainNodes 96 | 97 | 98 | shapeStyle 99 | 100 | borderStrokeStyle 101 | 102 | color 103 | {1.000000, 1.000000, 1.000000, 1.000000} 104 | dash 105 | 0 106 | width 107 | 2 108 | 109 | fillColor 110 | {0.908000, 0.060000, 0.276000, 1.000000} 111 | shapeType 112 | 3 113 | 114 | strokeStyle 115 | 116 | color 117 | {0.908000, 0.060000, 0.276000, 1.000000} 118 | dash 119 | 0 120 | width 121 | 4 122 | 123 | titleStyle 124 | 125 | alignment 126 | 1 127 | bold 128 | 129 | color 130 | {1.000000, 1.000000, 1.000000, 1.000000} 131 | fontName 132 | Helvetica 133 | fontSize 134 | 20 135 | italic 136 | 137 | 138 | 139 | 140 | subnodeColors 141 | 142 | 143 | shapeStyle 144 | 145 | borderStrokeStyle 146 | 147 | color 148 | {0.566, 0.812, 0.406, 1.000} 149 | 150 | fillColor 151 | {1.000, 1.000, 1.000, 1.000} 152 | 153 | strokeStyle 154 | 155 | color 156 | {0.566, 0.812, 0.406, 1.000} 157 | 158 | titleStyle 159 | 160 | color 161 | {0.275, 0.082, 0.208, 1.000} 162 | 163 | 164 | 165 | shapeStyle 166 | 167 | borderStrokeStyle 168 | 169 | color 170 | {0.227, 0.749, 0.737, 1.000} 171 | 172 | fillColor 173 | {1.000, 1.000, 1.000, 1.000} 174 | 175 | strokeStyle 176 | 177 | color 178 | {0.227, 0.749, 0.737, 1.000} 179 | 180 | titleStyle 181 | 182 | color 183 | {0.275, 0.082, 0.208, 1.000} 184 | 185 | 186 | 187 | shapeStyle 188 | 189 | borderStrokeStyle 190 | 191 | color 192 | {0.494, 0.757, 0.921, 1.000} 193 | 194 | fillColor 195 | {1.000, 1.000, 1.000, 1.000} 196 | 197 | strokeStyle 198 | 199 | color 200 | {0.494, 0.757, 0.921, 1.000} 201 | 202 | titleStyle 203 | 204 | color 205 | {0.275, 0.082, 0.208, 1.000} 206 | 207 | 208 | 209 | shapeStyle 210 | 211 | borderStrokeStyle 212 | 213 | color 214 | {0.559, 0.437, 0.964, 1.000} 215 | 216 | fillColor 217 | {1.000, 1.000, 1.000, 1.000} 218 | 219 | strokeStyle 220 | 221 | color 222 | {0.559, 0.437, 0.964, 1.000} 223 | 224 | titleStyle 225 | 226 | color 227 | {0.275, 0.082, 0.208, 1.000} 228 | 229 | 230 | 231 | shapeStyle 232 | 233 | borderStrokeStyle 234 | 235 | color 236 | {0.820, 0.127, 0.858, 1.000} 237 | 238 | fillColor 239 | {1.000, 1.000, 1.000, 1.000} 240 | 241 | strokeStyle 242 | 243 | color 244 | {0.820, 0.127, 0.858, 1.000} 245 | 246 | titleStyle 247 | 248 | color 249 | {0.275, 0.082, 0.208, 1.000} 250 | 251 | 252 | 253 | shapeStyle 254 | 255 | borderStrokeStyle 256 | 257 | color 258 | {0.781, 0.054, 0.301, 1.000} 259 | 260 | fillColor 261 | {1.000, 1.000, 1.000, 1.000} 262 | 263 | strokeStyle 264 | 265 | color 266 | {0.781, 0.054, 0.301, 1.000} 267 | 268 | titleStyle 269 | 270 | color 271 | {0.275, 0.082, 0.208, 1.000} 272 | 273 | 274 | 275 | subnodeLevels 276 | 277 | 278 | 279 | -------------------------------------------------------------------------------- /MindNote/STL-源码剖析.mindnode/style.mindnodestyle/contents.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | allowNodeStrokeColorVariation 6 | 7 | backgroundColor 8 | {0.983000, 0.970000, 0.973000, 1.000000} 9 | baseSubnode 10 | 11 | shapeStyle 12 | 13 | borderStrokeStyle 14 | 15 | color 16 | {0.494000, 0.757000, 0.921000, 1.000000} 17 | dash 18 | 0 19 | width 20 | 6 21 | 22 | fillColor 23 | {1.000000, 1.000000, 1.000000, 1.000000} 24 | shapeType 25 | 0 26 | 27 | strokeStyle 28 | 29 | color 30 | {0.494000, 0.757000, 0.921000, 1.000000} 31 | dash 32 | 0 33 | width 34 | 6 35 | 36 | titleStyle 37 | 38 | alignment 39 | 0 40 | bold 41 | 42 | color 43 | {0.275000, 0.082000, 0.208000, 1.000000} 44 | fontName 45 | ArialRoundedMTBold 46 | fontSize 47 | 18 48 | italic 49 | 50 | 51 | 52 | crossConnections 53 | 54 | 55 | arrowStyle 56 | 57 | endArrow 58 | 3 59 | startArrow 60 | 3 61 | 62 | pathStyle 63 | 64 | strokeStyle 65 | 66 | color 67 | {0.992000, 0.357000, 0.227000, 1.000000} 68 | dash 69 | 0 70 | width 71 | 3 72 | 73 | 74 | titleStyle 75 | 76 | alignment 77 | 0 78 | bold 79 | 80 | color 81 | {0.000000, 0.000000, 0.000000, 1.000000} 82 | fontName 83 | HelveticaNeue 84 | fontSize 85 | 14 86 | italic 87 | 88 | strikethrough 89 | 90 | underline 91 | 92 | 93 | 94 | 95 | mainNodes 96 | 97 | 98 | shapeStyle 99 | 100 | borderStrokeStyle 101 | 102 | color 103 | {1.000000, 1.000000, 1.000000, 1.000000} 104 | dash 105 | 0 106 | width 107 | 2 108 | 109 | fillColor 110 | {0.908000, 0.060000, 0.276000, 1.000000} 111 | shapeType 112 | 3 113 | 114 | strokeStyle 115 | 116 | color 117 | {0.908000, 0.060000, 0.276000, 1.000000} 118 | dash 119 | 0 120 | width 121 | 4 122 | 123 | titleStyle 124 | 125 | alignment 126 | 1 127 | bold 128 | 129 | color 130 | {1.000000, 1.000000, 1.000000, 1.000000} 131 | fontName 132 | Helvetica 133 | fontSize 134 | 20 135 | italic 136 | 137 | 138 | 139 | 140 | subnodeColors 141 | 142 | 143 | shapeStyle 144 | 145 | borderStrokeStyle 146 | 147 | color 148 | {0.566, 0.812, 0.406, 1.000} 149 | 150 | fillColor 151 | {1.000, 1.000, 1.000, 1.000} 152 | 153 | strokeStyle 154 | 155 | color 156 | {0.566, 0.812, 0.406, 1.000} 157 | 158 | titleStyle 159 | 160 | color 161 | {0.275, 0.082, 0.208, 1.000} 162 | 163 | 164 | 165 | shapeStyle 166 | 167 | borderStrokeStyle 168 | 169 | color 170 | {0.227, 0.749, 0.737, 1.000} 171 | 172 | fillColor 173 | {1.000, 1.000, 1.000, 1.000} 174 | 175 | strokeStyle 176 | 177 | color 178 | {0.227, 0.749, 0.737, 1.000} 179 | 180 | titleStyle 181 | 182 | color 183 | {0.275, 0.082, 0.208, 1.000} 184 | 185 | 186 | 187 | shapeStyle 188 | 189 | borderStrokeStyle 190 | 191 | color 192 | {0.494, 0.757, 0.921, 1.000} 193 | 194 | fillColor 195 | {1.000, 1.000, 1.000, 1.000} 196 | 197 | strokeStyle 198 | 199 | color 200 | {0.494, 0.757, 0.921, 1.000} 201 | 202 | titleStyle 203 | 204 | color 205 | {0.275, 0.082, 0.208, 1.000} 206 | 207 | 208 | 209 | shapeStyle 210 | 211 | borderStrokeStyle 212 | 213 | color 214 | {0.559, 0.437, 0.964, 1.000} 215 | 216 | fillColor 217 | {1.000, 1.000, 1.000, 1.000} 218 | 219 | strokeStyle 220 | 221 | color 222 | {0.559, 0.437, 0.964, 1.000} 223 | 224 | titleStyle 225 | 226 | color 227 | {0.275, 0.082, 0.208, 1.000} 228 | 229 | 230 | 231 | shapeStyle 232 | 233 | borderStrokeStyle 234 | 235 | color 236 | {0.820, 0.127, 0.858, 1.000} 237 | 238 | fillColor 239 | {1.000, 1.000, 1.000, 1.000} 240 | 241 | strokeStyle 242 | 243 | color 244 | {0.820, 0.127, 0.858, 1.000} 245 | 246 | titleStyle 247 | 248 | color 249 | {0.275, 0.082, 0.208, 1.000} 250 | 251 | 252 | 253 | shapeStyle 254 | 255 | borderStrokeStyle 256 | 257 | color 258 | {0.781, 0.054, 0.301, 1.000} 259 | 260 | fillColor 261 | {1.000, 1.000, 1.000, 1.000} 262 | 263 | strokeStyle 264 | 265 | color 266 | {0.781, 0.054, 0.301, 1.000} 267 | 268 | titleStyle 269 | 270 | color 271 | {0.275, 0.082, 0.208, 1.000} 272 | 273 | 274 | 275 | subnodeLevels 276 | 277 | 278 | 279 | -------------------------------------------------------------------------------- /MindNote/STL概述与版本简介.mindnode/style.mindnodestyle/contents.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | allowNodeStrokeColorVariation 6 | 7 | backgroundColor 8 | {0.983000, 0.970000, 0.973000, 1.000000} 9 | baseSubnode 10 | 11 | shapeStyle 12 | 13 | borderStrokeStyle 14 | 15 | color 16 | {0.494000, 0.757000, 0.921000, 1.000000} 17 | dash 18 | 0 19 | width 20 | 6 21 | 22 | fillColor 23 | {1.000000, 1.000000, 1.000000, 1.000000} 24 | shapeType 25 | 0 26 | 27 | strokeStyle 28 | 29 | color 30 | {0.494000, 0.757000, 0.921000, 1.000000} 31 | dash 32 | 0 33 | width 34 | 6 35 | 36 | titleStyle 37 | 38 | alignment 39 | 0 40 | bold 41 | 42 | color 43 | {0.275000, 0.082000, 0.208000, 1.000000} 44 | fontName 45 | ArialRoundedMTBold 46 | fontSize 47 | 18 48 | italic 49 | 50 | 51 | 52 | crossConnections 53 | 54 | 55 | arrowStyle 56 | 57 | endArrow 58 | 3 59 | startArrow 60 | 3 61 | 62 | pathStyle 63 | 64 | strokeStyle 65 | 66 | color 67 | {0.992000, 0.357000, 0.227000, 1.000000} 68 | dash 69 | 0 70 | width 71 | 3 72 | 73 | 74 | titleStyle 75 | 76 | alignment 77 | 0 78 | bold 79 | 80 | color 81 | {0.000000, 0.000000, 0.000000, 1.000000} 82 | fontName 83 | HelveticaNeue 84 | fontSize 85 | 14 86 | italic 87 | 88 | strikethrough 89 | 90 | underline 91 | 92 | 93 | 94 | 95 | mainNodes 96 | 97 | 98 | shapeStyle 99 | 100 | borderStrokeStyle 101 | 102 | color 103 | {1.000000, 1.000000, 1.000000, 1.000000} 104 | dash 105 | 0 106 | width 107 | 2 108 | 109 | fillColor 110 | {0.908000, 0.060000, 0.276000, 1.000000} 111 | shapeType 112 | 3 113 | 114 | strokeStyle 115 | 116 | color 117 | {0.908000, 0.060000, 0.276000, 1.000000} 118 | dash 119 | 0 120 | width 121 | 4 122 | 123 | titleStyle 124 | 125 | alignment 126 | 1 127 | bold 128 | 129 | color 130 | {1.000000, 1.000000, 1.000000, 1.000000} 131 | fontName 132 | Helvetica 133 | fontSize 134 | 20 135 | italic 136 | 137 | 138 | 139 | 140 | subnodeColors 141 | 142 | 143 | shapeStyle 144 | 145 | borderStrokeStyle 146 | 147 | color 148 | {0.566, 0.812, 0.406, 1.000} 149 | 150 | fillColor 151 | {1.000, 1.000, 1.000, 1.000} 152 | 153 | strokeStyle 154 | 155 | color 156 | {0.566, 0.812, 0.406, 1.000} 157 | 158 | titleStyle 159 | 160 | color 161 | {0.275, 0.082, 0.208, 1.000} 162 | 163 | 164 | 165 | shapeStyle 166 | 167 | borderStrokeStyle 168 | 169 | color 170 | {0.227, 0.749, 0.737, 1.000} 171 | 172 | fillColor 173 | {1.000, 1.000, 1.000, 1.000} 174 | 175 | strokeStyle 176 | 177 | color 178 | {0.227, 0.749, 0.737, 1.000} 179 | 180 | titleStyle 181 | 182 | color 183 | {0.275, 0.082, 0.208, 1.000} 184 | 185 | 186 | 187 | shapeStyle 188 | 189 | borderStrokeStyle 190 | 191 | color 192 | {0.494, 0.757, 0.921, 1.000} 193 | 194 | fillColor 195 | {1.000, 1.000, 1.000, 1.000} 196 | 197 | strokeStyle 198 | 199 | color 200 | {0.494, 0.757, 0.921, 1.000} 201 | 202 | titleStyle 203 | 204 | color 205 | {0.275, 0.082, 0.208, 1.000} 206 | 207 | 208 | 209 | shapeStyle 210 | 211 | borderStrokeStyle 212 | 213 | color 214 | {0.559, 0.437, 0.964, 1.000} 215 | 216 | fillColor 217 | {1.000, 1.000, 1.000, 1.000} 218 | 219 | strokeStyle 220 | 221 | color 222 | {0.559, 0.437, 0.964, 1.000} 223 | 224 | titleStyle 225 | 226 | color 227 | {0.275, 0.082, 0.208, 1.000} 228 | 229 | 230 | 231 | shapeStyle 232 | 233 | borderStrokeStyle 234 | 235 | color 236 | {0.820, 0.127, 0.858, 1.000} 237 | 238 | fillColor 239 | {1.000, 1.000, 1.000, 1.000} 240 | 241 | strokeStyle 242 | 243 | color 244 | {0.820, 0.127, 0.858, 1.000} 245 | 246 | titleStyle 247 | 248 | color 249 | {0.275, 0.082, 0.208, 1.000} 250 | 251 | 252 | 253 | shapeStyle 254 | 255 | borderStrokeStyle 256 | 257 | color 258 | {0.781, 0.054, 0.301, 1.000} 259 | 260 | fillColor 261 | {1.000, 1.000, 1.000, 1.000} 262 | 263 | strokeStyle 264 | 265 | color 266 | {0.781, 0.054, 0.301, 1.000} 267 | 268 | titleStyle 269 | 270 | color 271 | {0.275, 0.082, 0.208, 1.000} 272 | 273 | 274 | 275 | subnodeLevels 276 | 277 | 278 | 279 | -------------------------------------------------------------------------------- /MindNote/迭代器(iterators).mindnode/style.mindnodestyle/contents.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | allowNodeStrokeColorVariation 6 | 7 | backgroundColor 8 | {0.983000, 0.970000, 0.973000, 1.000000} 9 | baseSubnode 10 | 11 | shapeStyle 12 | 13 | borderStrokeStyle 14 | 15 | color 16 | {0.820000, 0.127000, 0.858000, 1.000000} 17 | dash 18 | 0 19 | width 20 | 6 21 | 22 | fillColor 23 | {1.000000, 1.000000, 1.000000, 1.000000} 24 | shapeType 25 | 0 26 | 27 | strokeStyle 28 | 29 | color 30 | {0.820000, 0.127000, 0.858000, 1.000000} 31 | dash 32 | 0 33 | width 34 | 6 35 | 36 | titleStyle 37 | 38 | alignment 39 | 0 40 | bold 41 | 42 | color 43 | {0.275000, 0.082000, 0.208000, 1.000000} 44 | fontName 45 | ArialRoundedMTBold 46 | fontSize 47 | 18 48 | italic 49 | 50 | 51 | 52 | crossConnections 53 | 54 | 55 | arrowStyle 56 | 57 | endArrow 58 | 3 59 | startArrow 60 | 3 61 | 62 | pathStyle 63 | 64 | strokeStyle 65 | 66 | color 67 | {0.992000, 0.357000, 0.227000, 1.000000} 68 | dash 69 | 0 70 | width 71 | 3 72 | 73 | 74 | titleStyle 75 | 76 | alignment 77 | 0 78 | bold 79 | 80 | color 81 | {0.000000, 0.000000, 0.000000, 1.000000} 82 | fontName 83 | HelveticaNeue 84 | fontSize 85 | 14 86 | italic 87 | 88 | strikethrough 89 | 90 | underline 91 | 92 | 93 | 94 | 95 | mainNodes 96 | 97 | 98 | shapeStyle 99 | 100 | borderStrokeStyle 101 | 102 | color 103 | {1.000000, 1.000000, 1.000000, 1.000000} 104 | dash 105 | 0 106 | width 107 | 2 108 | 109 | fillColor 110 | {0.908000, 0.060000, 0.276000, 1.000000} 111 | shapeType 112 | 3 113 | 114 | strokeStyle 115 | 116 | color 117 | {0.908000, 0.060000, 0.276000, 1.000000} 118 | dash 119 | 0 120 | width 121 | 4 122 | 123 | titleStyle 124 | 125 | alignment 126 | 1 127 | bold 128 | 129 | color 130 | {1.000000, 1.000000, 1.000000, 1.000000} 131 | fontName 132 | Helvetica 133 | fontSize 134 | 20 135 | italic 136 | 137 | 138 | 139 | 140 | subnodeColors 141 | 142 | 143 | shapeStyle 144 | 145 | borderStrokeStyle 146 | 147 | color 148 | {0.566, 0.812, 0.406, 1.000} 149 | 150 | fillColor 151 | {1.000, 1.000, 1.000, 1.000} 152 | 153 | strokeStyle 154 | 155 | color 156 | {0.566, 0.812, 0.406, 1.000} 157 | 158 | titleStyle 159 | 160 | color 161 | {0.275, 0.082, 0.208, 1.000} 162 | 163 | 164 | 165 | shapeStyle 166 | 167 | borderStrokeStyle 168 | 169 | color 170 | {0.227, 0.749, 0.737, 1.000} 171 | 172 | fillColor 173 | {1.000, 1.000, 1.000, 1.000} 174 | 175 | strokeStyle 176 | 177 | color 178 | {0.227, 0.749, 0.737, 1.000} 179 | 180 | titleStyle 181 | 182 | color 183 | {0.275, 0.082, 0.208, 1.000} 184 | 185 | 186 | 187 | shapeStyle 188 | 189 | borderStrokeStyle 190 | 191 | color 192 | {0.494, 0.757, 0.921, 1.000} 193 | 194 | fillColor 195 | {1.000, 1.000, 1.000, 1.000} 196 | 197 | strokeStyle 198 | 199 | color 200 | {0.494, 0.757, 0.921, 1.000} 201 | 202 | titleStyle 203 | 204 | color 205 | {0.275, 0.082, 0.208, 1.000} 206 | 207 | 208 | 209 | shapeStyle 210 | 211 | borderStrokeStyle 212 | 213 | color 214 | {0.559, 0.437, 0.964, 1.000} 215 | 216 | fillColor 217 | {1.000, 1.000, 1.000, 1.000} 218 | 219 | strokeStyle 220 | 221 | color 222 | {0.559, 0.437, 0.964, 1.000} 223 | 224 | titleStyle 225 | 226 | color 227 | {0.275, 0.082, 0.208, 1.000} 228 | 229 | 230 | 231 | shapeStyle 232 | 233 | borderStrokeStyle 234 | 235 | color 236 | {0.820, 0.127, 0.858, 1.000} 237 | 238 | fillColor 239 | {1.000, 1.000, 1.000, 1.000} 240 | 241 | strokeStyle 242 | 243 | color 244 | {0.820, 0.127, 0.858, 1.000} 245 | 246 | titleStyle 247 | 248 | color 249 | {0.275, 0.082, 0.208, 1.000} 250 | 251 | 252 | 253 | shapeStyle 254 | 255 | borderStrokeStyle 256 | 257 | color 258 | {0.781, 0.054, 0.301, 1.000} 259 | 260 | fillColor 261 | {1.000, 1.000, 1.000, 1.000} 262 | 263 | strokeStyle 264 | 265 | color 266 | {0.781, 0.054, 0.301, 1.000} 267 | 268 | titleStyle 269 | 270 | color 271 | {0.275, 0.082, 0.208, 1.000} 272 | 273 | 274 | 275 | subnodeLevels 276 | 277 | 278 | 279 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # STL 学习笔记 2 | 3 | 这是我学习 STL 的笔记。 4 | 5 | **更新日志** 6 | 7 | - 2019-03-04 8 | 9 | 新增了[STL 概述与版本简介](#STL 概述与版本简介)、[空间分配器(allocators)](#空间分配器(allocators))、[迭代器(iterators)](#迭代器(iterators))、[序列式容器-vector](#vector) 10 | 11 | - 2019-03-05 12 | 13 | 增加了[list](#list) 14 | 15 | - 2019-03-06 16 | 17 | 增加了 [deque](#deque)、[heap](#heap)、[priority_queue](#priority_queue)、[slist](#slist) 18 | 19 | # 目录 20 | 21 | - [STL 概述与版本简介](#STL概述与版本简介) 22 | - [STL 的历史](#STL的历史) 23 | - [STL 与 C++ 标准链接库](#STL与C++标准链接库) 24 | - [STL 六大组件](#STL六大组件) 25 | - [GNU 源码开放精神](#GNU源码开放精神) 26 | - [HP 版本](#HP版本) 27 | - [SGI STL 版本](#SGI-STL版本) 28 | - [空间分配器(allocators)](#空间分配器(allocators)) 29 | - [分配器的标准接口](#分配器的标准接口) 30 | - [设计分配器](#设计分配器) 31 | - [二级分配(sub-allocation)的 SGI 空间分配器](#二级分配(sub-allocation)的SGI空间分配器) 32 | - [内存基本处理工具](#内存基本处理工具) 33 | - [迭代器(iterators)](#迭代器(iterators)) 34 | - [迭代器的设计思维——STL 的关键](#迭代器的设计思维——STL的关键) 35 | - [迭代器是一种 smart pointer](#迭代器是一种smart-pointer) 36 | - [迭代器相应类型](#迭代器相应类型) 37 | - [iterator 源码](#iterator源码) 38 | - [序列式容器(sequence containers)](#序列式容器(sequence-containers)) 39 | - [vector](#vector) 40 | - [vector 的迭代器](#vector的迭代器) 41 | - [vector 的数据结构](#vector的数据结构) 42 | - [vector 的构造与内存管理 constructor, push_back](#vector的构造与内存管理constructor,push_back) 43 | - [vector 的元素操作 pop_back, erase, clear, insert](#vector的元素操作pop_back,erase,clear,insert) 44 | - [list](#list) 45 | - [list的节点Node](#list的节点Node) 46 | - [list的迭代器](list的迭代器) 47 | - [list的数据结构](#list的数据结构) 48 | - [list的构造与内存管理:constructor, push_bask,insert](#list的构造与内存管理:constructor, push_bask,insert) 49 | - [list的元素操作](#list的元素操作) 50 | - [deque](#deque) 51 | - [deque的中控件](#deque的中控件) 52 | - [deque的迭代器](#deque的迭代器) 53 | - [deque的数据结构](#deque的数据结构) 54 | - [deque的构造与内存管理](#deque的构造与内存管理) 55 | - [deque的元素操作pop_back,pop_front,clear,erase,insert](#deque的元素操作pop_back,pop_front,clear,erase,insert) 56 | - [stack](#stack) 57 | - [stack定义式完整列表](#stack定义式完整列表) 58 | - [stack没有迭代器](#stack没有迭代器) 59 | - [以list为stack的底层容器](#以list为stack的底层容器) 60 | - [queue](#queue) 61 | - [queue定义式完整列表](#queue定义式完整列表) 62 | - [queue没有迭代器](#queue没有迭代器) 63 | - [以list做为queue的底层容器](#以list做为queue的底层容器) 64 | - [heap](#heap) 65 | - [heap算法](#heap算法) 66 | - [heap也没有迭代器](#heap也没有迭代器) 67 | - [priority_queue](#priority_queue) 68 | - [priority_queue也没有迭代器](#priority_queue也没有迭代器) 69 | - [slist](#slist) 70 | - [slist的节点](#slist的节点) 71 | - [slist的迭代器](#slist的迭代器) 72 | - [slist的数据结构](#slist的数据结构) 73 | 74 | --- 75 | 76 | # STL源码剖析 77 | 78 | ![](images/stl-overview.png) 79 | 80 | SGI STL 版本源码的可读性极佳,运用也最为广泛,是 GNU C++ 的标准链接库,并且开放自由。 81 | 82 | 日常编程广泛运用的各种数据结构(data structures)和算法(algorithms)在 STL 中有良好的实现,连内存配置与管理也都重重考虑了最佳效能。 83 | 84 | STL 源码中有着 vector、list、heap、deque、RB-tree、hash-table、set/map,以及各种算法(排序、搜索、排列组合……)的底层实现。 85 | 86 | 从技术研究与本质提升的角度看,探究 STL 的细节可以帮助彻底的掌握一切,获得深厚扎实的基础。 87 | 88 | SGI STL 称得上是一个一流作品,追踪一流作品并且吸取养分,远比自己关起门来写个三流作品,价值高得多。 89 | 90 | ## STL概述与版本简介 91 | 92 | ![](images/1-1.png) 93 | 94 | 为了建立数据结构和算法的一套标准,并且降低其间的耦合(coupling)关系以提升各自的独立性、弹性、交互操作性(相互合作性,interoperability),STL 诞生了。 95 | 96 | STL 带来了一个高层次的、以泛型思维(Generic Paradigm)为基础的、系统化的、条理分明的「软件组件分类学(components taxonomy)」。 97 | 98 | ### STL的历史 99 | 100 | STL 的创始人:Alexander Stepanov。 101 | 102 | Alexander Stepanov 分别􏰄实验了多种架构和算法公式,先以 C 完成,而后再以 C++ 完成。1993 年 11 月完成正式提案,STL 成为 C++ 标准规格的一部分。 103 | 104 | ### STL与C++标准链接库 105 | 106 | Alexander 向 C++ 标准委员提交提案后,STL 在会议中取得了压倒性的胜利。STL 进入了 C++ 标准化的正式流程,C++ 链接库如 stream, string 等也都以template 重新写过 。 107 | 108 | ### STL六大组件 109 | 110 | 1. 容器(containers) 111 | 112 | 各种数据结构,如 vector, list, deque, set, map。可以理解为包含对象的类。 113 | 114 | 2. 算法(algorithms) 115 | 116 | 各种常用算法如 sort, search, copy, erase。适用于不同类型容器的函数。 117 | 118 | 3. 迭代器(iterators) 119 | 120 | 容器中的“指针”。 121 | 122 | 4. 仿函式(functors) 123 | 124 | STL 包括重载函数调用操作符的类。类的实例称为函数对象或仿函数。函数允许在传递参数的帮助下自定义相关函数的工作。 125 | 126 | 5. 适配器(adapters) 127 | 128 | 修饰容器(containers)或仿函式(functors)或迭代器(iterators)。 129 | 130 | 6. 分配器(allocators) 131 | 132 | 负责空间分配与管理,即用于分配空间的对象。 133 | 134 | ![](images/1-2.png) 135 | 136 | #### C++规范 137 | 138 | 使用无拓展名的头文件。 139 | 140 | ```c++ 141 | #include 142 | ``` 143 | 144 | ### GNU源码开放精神 145 | 146 | STL 源码属于 HP 公司拥有,每一个头文件重都有声明。开放源码的精神,一般统称为 open source。 147 | 148 | Stallman 于 1984 创立自由软件基金会(Free Software Foundation),简称FSF。 149 | 150 | ### HP版本 151 | 152 | 每一个 HP STL 头文件都有如下一份声明。 153 | 154 | ``` 155 | * Copyright (c) 1994 156 | * Hewlett-Packard Company 157 | ``` 158 | 159 | ### SGI-STL版本 160 | 161 | SGI 版􏰁由 Silicon Graphics Computer Systems, Inc. 公司发展,承继 HP 版􏰁。它的每一个头文件也都有 HP 的版􏰁本声明。 162 | 163 | ``` 164 | * Copyright (c) 1996 165 | * Silicon Graphics Computer Systems, Inc. 166 | ``` 167 | 168 | 在我的设备上,STL 源码位于以下目录: 169 | 170 | ``` 171 | /usr/include/c++/4.2.1 172 | ``` 173 | 174 | 每一份 STL 源码都包含三个版权声明,如下: 175 | 176 | ```c++ 177 | // Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. 178 | 179 | * Copyright (c) 1994 180 | * Hewlett-Packard Company 181 | 182 | * Copyright (c) 1996 183 | * Silicon Graphics Computer Systems, Inc. 184 | 185 | /** @file include/vector 186 | * This is a Standard C++ Library header. 187 | */ 188 | ``` 189 | 190 | ## 空间分配器(allocators) 191 | 192 | ![](images/2.png) 193 | 194 | 整个 STL 的操作对象(所有的数值)都存放在容器之内,而容器一定需要分配空间以置放数据。 195 | 196 | ``` 197 | array_allocator.h 198 | bitmap_allocator.h 199 | debug_allocator.h # 可以包装任意其它的allocato 200 | malloc_allocator.h # 包装malloc和free 201 | mt_allocator.h 202 | new_allocator.h # 默认使用的allocator 203 | pool_allocator.h # 唯一一个带内存池的allocator 204 | throw_allocator.h 205 | ``` 206 | 207 | ### 分配器的标准接口 208 | 209 | 打开 new_allocator.h,可以看到 allocator 所提供的接口。 210 | 211 | ![](images/2-2.png) 212 | 213 | ### 设计分配器 214 | 215 | ```c++ 216 | src/my_allocator.h 217 | 218 | src/test_my_allocator.cc 219 | ``` 220 | 221 | ### 二级分配(sub-allocation)的SGI空间分配器 222 | 223 | ``` 224 | vector > iv; 225 | ``` 226 | 227 | #### SGI标准的空间分配器std::allocator 228 | 229 | SGI 定义有一个符合部分标准、名为 allocator 的分配器,但是效率不高,只把 C++ 的 ::operator new 和 ::operator delete 做一层封装而已。 230 | 231 | #### SGI特殊的空间分配器std::alloc 232 | 233 | STL allocator 将内存申请由 alloc:allocate() 负责,内存释放由 alloc::deallocate() 负责,对象构造由::construct() 负责,对象销毁由 ::destroy() 负责。 234 | 235 | 配置器定义于 `` 文件中, `` 中包含: 236 | 237 | ```C++ 238 | #include // 负责内存空间的配置与释放 239 | #include // 负责对象的构建与销毁 240 | ``` 241 | 242 | #### 对象的构造和销毁:construct()和destroy() 243 | 244 | `stl_construct.h` 中包含以下函数: 245 | 246 | ![](images/2-3.png) 247 | 248 | _Construct() 接受一个指针 p 和一个初值 value,此函式的用途就是将初值设定到指针所指的空间上。 249 | 250 | ```c++ 251 | // 销毁将指针所指东西 252 | _Destroy(_Tp* __pointer) 253 | 254 | // 销毁[first, last]之间的东西 255 | _Destroy(_ForwardIterator __first, _ForwardIterator __last) 256 | ``` 257 | 258 | #### 空间的申请与释放std::alloc 259 | 260 | 空间的申请、释放由 `` 负责。 261 | 262 | SGI 设计了双层级分配器,第一级分配器直接使用 malloc() 和 free(),第二级分配器则视情况采用不同的策略:当分配空间超过 128bytes,便呼叫第一级分配器;当分配空间小于 128bytes,为了降低额外负担,便采用复杂的 memory pool 整理方式,而不再求助于第一级分配器。 263 | 264 | #### 第一级分配器 265 | 266 | 第一级分配器直接使用 `malloc()`,SGI 以 malloc 而非 ::operator new 来分配内存。 267 | 268 | #### 第二级分配器 269 | 270 | 第二级分配器多了一些机制,避免􏰃多小额区块造成内存的碎片。当区块小于 128 bytes,则以 **memory pool** 管理,此法又称为二级分配(sub-allocation):每次配置一大块内存,并维护对应之自由表(free-list)。下次若再有相同大小的内存需求,就直接从 free-lists 中分出。 271 | 272 | ```c++ 273 | // pool_allocator.h 274 | union _Obj 275 | { 276 | union _Obj* _M_free_list_link; 277 | char _M_client_data[1]; // The client sees this. 278 | }; 279 | ``` 280 | 281 | #### 控件分配函数allocate() 282 | 283 | 此函数首先判断区块大小,大于 128 bytes 就调用第一级分配器,小于 128 bytes 就检查对应的 free list。如果 free list 中有可用的区块,就直接拿来用,如果没有可用区块,就将区块大小上调至 8 倍数边界,然后呼叫refill(),准备为 free list 重新填充空间。 284 | 285 | #### 控件释放函数deallocate() 286 | 287 | 此函数首先判断区块大小,大于 128 bytes 就调用第一级分配器,小于 128 bytes 就找出对应的 free list,将区块回收。 288 | 289 | #### 重新填充free list 290 | 291 | free list 中没有可用区块了,就呼叫 refill() 为 free list 重新填充空间。 292 | 293 | #### 内存池(memory pool) 294 | 295 | 判断内存池的剩余容量,然后将空间分配给 free list。 296 | 297 | ```C++ 298 | // 判断内存池的剩余容量 299 | end_free - start_free 300 | ``` 301 | 302 | ### 内存基本处理工具 303 | 304 | STL 定义有五个函数,作用于􏰅初始化空间上。 305 | 306 | 前两个是 construct() 和 destroy(),另外三个函数位于 `` 中。 307 | 308 | ![](images/2-4.png) 309 | 310 | **uninitialized_copy()** 311 | 312 | 将内存的分配与对象的构造行为分离开来。 313 | 314 | 它接收 3 个参数: 315 | 316 | 1. 迭代器 first 指向输入端的起始位置 317 | 2. 迭代器 last 指向输入端的结束位置 318 | 3. 迭代器 result 指向输出端(欲初始化空间)的起始处 319 | 320 | **uninitialized_fill()** 321 | 322 | 将内存的分配与对象的构造行为分离开来,它要不就产生出所有必要元素,要不就不产生任何元素。 323 | 324 | 它接收 3 个参数: 325 | 326 | 1. 迭代器 first 指向输出端(欲初始化空间)的起始处 327 | 2. 迭代器 last 指向输出端(欲初始化空间)的结束处 328 | 3. x 表示初值 329 | 330 | **uninitialized_fill_n()** 331 | 332 | 将内存的分配与对象的构造行为分离开来,它会为指定范围内的所有元素设定相同的初值。 333 | 334 | 它接收 3 个参数: 335 | 336 | 1. first:指向欲初始化空间的起始处 337 | 2. n:表示欲初始化空间的大小 338 | 3. x:初值 339 | 340 | ## 迭代器(iterators) 341 | 342 | ![](images/3-1.png) 343 | 344 | iterator:提供一种方法,是的得可以按顺序访问某个聚合物(容器)所􏰈的各个元素,而又不会暴露该聚合物(容器)的内部实现。 345 | 346 | ### 迭代器的设计思维——STL的关键 347 | 348 | STL 的中心思想在于,将数据容器(containers)和算法(algorithms)分开,彼此独立设计,最后再以一种粘合剂将它们联系在一起。迭代器(iterators)就是联系容器(containers)和算法(algorithms)的粘合剂。 349 | 350 | ### 迭代器是一种smart-pointer 351 | 352 | 迭代器是一种行为类似指针的对象,而指针的各种行为中最常见也最重要的便是内容提领(dereference)和成员取用(member access)。迭代器最重要的编程工作就是对 operator* 和 operator-> 进行重载(overloading)工程。 353 | 354 | auto_ptr 的源码在头文件 `` 中。 355 | 356 | ```c++ 357 | // memory 358 | template 359 | class auto_ptr 360 | { 361 | private: 362 | _Tp* _M_ptr; 363 | 364 | public: 365 | //.... 366 | } 367 | ``` 368 | 369 | 每一种 STL 容器都提供有专属迭代器,目的就是为了封装细节不被使用者所看到。 370 | 371 | ### 迭代器相应类型 372 | 373 | 算法之中运用迭代器时,很可能会用到其相应类型􏰄(associated type)。 374 | 375 | 可以使用利用 function template 的自变量推导(argument deducation)机制。 376 | 377 | ### Traits编程技巧 378 | 379 | ``` 380 | src/my_iter.cc 381 | ``` 382 | 383 | func() 的回返型􏰄必须加上关键词 typename,关键词 typename 的用意在告诉编译器说这是一个类型􏰄。 384 | 385 | #### Partial Specialization(偏特化)的意义 386 | 387 | ```c++ 388 | template 389 | class C { ... }; 390 | ``` 391 | 392 | ```c++ 393 | template 394 | struct iterator_traits { 395 | // 当迭代器是个pointer-to-const 396 | // 萃取出来的类型应该是 T 而非 const T 397 | typedef value_type; 398 | }; 399 | 400 | template 401 | typename iterator_traits::value_type 402 | func(I ite) { 403 | return *ite; 404 | } 405 | ``` 406 | 407 | 根据经验,最常用到的迭代器相应型􏰄有五种:value type, difference type, pointer, 408 | reference,iterator catagoly。 409 | 410 | ```c++ 411 | // stl_iterator.h 412 | typename iterator_traits<_Iterator>::iterator_category, 413 | typename iterator_traits<_Iterator>::value_type, 414 | typename iterator_traits<_Iterator>::difference_type, 415 | typename iterator_traits<_Iterator>::pointer, 416 | typename iterator_traits<_Iterator>::reference 417 | ``` 418 | 419 | **value_type** 420 | 421 | 指迭代器所指对象的类型。 422 | 423 | **difference_type** 424 | 425 | 表示两个迭代器之间的距离。因此,它可以用来表示一个容器的最大容量,因为对于连续空间的容器而言,头尾之间的距离就是其最大容量。 426 | 427 | **reference** 428 | 429 | C++ 的函数如果要传回左值,都是以 by reference 的方式进行。 430 | 431 | **pointer** 432 | 433 | 能够传回一个 pointer,指向迭代器所指之物。 434 | 435 | ```C++ 436 | Item& operator*() const { return *ptr; } 437 | Item* operator->() const { return ptr; } 438 | ``` 439 | 440 | `Item&` 便是 reference type , `Item*` 是 pointer type。 441 | 442 | **iterator_category** 443 | 444 | 迭代器的分类: 445 | 446 | - Input Iterator:这种迭代器所指对象,不允许外界改变 447 | - Output Iterator:只能写(write only) 448 | - Forward Iterator:读写动作 449 | - Bidirectional Iterator:可双向移动 450 | - Random Access Iterator:涵盖所有算术能力 451 | 452 | ![](images/3-2.png) 453 | 454 | ### iterator 源码 455 | 456 | ``` 457 | iterator 458 | stl_iterator.h 459 | stl_iterator_base_funcs.h 460 | stl_iterator_base_types.h 461 | stl_raw_storage_iter.h 462 | stream_iterator.h 463 | streambuf_iterator.h 464 | ``` 465 | 466 | ## 序列式容器(sequence containers) 467 | 468 | ![](images/4-1.png) 469 | 470 | 容器是大多数人对 STL 的第一印象。 471 | 472 | **序列式容器**,其中的元素都可序(ordered),但􏰅未排序(sorted)。C++ 语言本􏰁身提供了一个序列式容器 array,STL 另外再提供 vector, list, deque, stack, queue, priority-queue 等等序列式容器。其中 stack 和 queue 由是将 deque 改头换面而成,技术上被归类为一种适配器(adapter)。 473 | 474 | ### vector 475 | 476 | vector 的数据安排以及操作方式,与 array 非常像似。它们之间的差别在于: 477 | 478 | - array 是静态空间,扩容和缩容操作首先配置一块新空间,然后将元素从旧空间一一搬往新空间,然后再把原来的空间释还给系统。 479 | 480 | - vector 是动态空间,随着元素的加入,它的内部机制会自行扩充空间以容纳新元素。 481 | 482 | ```c++ 483 | // stl_vector.h 484 | ``` 485 | 486 | ![](images/4-2.png) 487 | 488 | #### vector的迭代器 489 | 490 | ```c++ 491 | typedef __gnu_cxx::__normal_iterator iterator; 492 | typedef __gnu_cxx::__normal_iterator const_iterator; 493 | typedef std::reverse_iterator const_reverse_iterator; 494 | typedef std::reverse_iterator reverse_iterator; 495 | ``` 496 | 497 | vector 支持随机存取,提供的是 Random Access Iterators。 498 | 499 | #### vector的数据结构 500 | 501 | vector 所采用的数据结构非常简单:线性连续空间。 502 | 503 | ```c++ 504 | struct _Vector_impl : public _Tp_alloc_type 505 | { 506 | _Tp* _M_start; // 表示目前使用空间的头 507 | _Tp* _M_finish; // 表示目前使用空间的尾 508 | _Tp* _M_end_of_storage; // 表示目前可用空间的尾 509 | }; 510 | ``` 511 | 512 | vector 实际配置的大小可能比客端需求量更大一些,以备将来可能的扩充。 513 | 514 | size 表示元素的个数,capacity 表示 vector 的容量。当增加新元素时,size 增加,当 size 超过容量(capacity)的时候,vector 的容量会增加两倍。如果两倍容量仍不足,就扩张至足够大的容量。 515 | 516 | 例如下面的例子: 517 | 518 | ```c++ 519 | #include 520 | #include 521 | 522 | using std::vector; 523 | 524 | int main() { 525 | vector vec; 526 | for (int i = 0; i < 10; ++i) { 527 | vec.push_back(i); 528 | printf("capacity=%d, size=%d\n", vec.capacity(), vec.size()); 529 | } 530 | return 0; 531 | } 532 | ``` 533 | 534 | ```shell 535 | // 运行结果 536 | capacity=1, size=1 537 | capacity=2, size=2 538 | capacity=4, size=3 539 | capacity=4, size=4 540 | capacity=8, size=5 541 | capacity=8, size=6 542 | capacity=8, size=7 543 | capacity=8, size=8 544 | capacity=16, size=9 545 | capacity=16, size=10 546 | ``` 547 | 548 | #### vector的构造与内存管理constructor,push_back 549 | 550 | vector 提供许多 constructors,其中一个允许我们指定空间大小及初值: 551 | 552 | ```c++ 553 | vector(size_type n, const T& value) { 554 | fill_initialize(n, value); 555 | } 556 | ``` 557 | 558 | 当我们以 push_back() 将新元素安插于 vector 尾端,该函式首先检查是否还有备用空间?如果有就直接在备用空间上建构元素,并调整迭代器 finish,使 vector 变大。如果没有备用空间了,就扩充空间(重新分配、搬移数据、释放原空间)。 559 | 560 | ```C++ 561 | // stl_bvector.h 562 | void _M_insert_aux(iterator __position, bool __x) { 563 | // 检查是否还有备用空间 564 | if (this->_M_impl._M_finish._M_p != this->_M_impl._M_end_of_storage) 565 | { 566 | // 构造一个新元素 567 | std::copy_backward(__position, this->_M_impl._M_finish, 568 | this->_M_impl._M_finish + 1); 569 | *__position = __x; 570 | // 调整 finish 571 | ++this->_M_impl._M_finish; 572 | } 573 | else 574 | { 575 | // 如果原大小不为 0,则配置原大小的两倍 576 | const size_type __len = size() ? 2 * size() 577 | : static_cast(_S_word_bit); 578 | _Bit_type * __q = this->_M_allocate(__len); 579 | iterator __i = _M_copy_aligned(begin(), __position, 580 | iterator(__q, 0)); 581 | *__i++ = __x; 582 | this->_M_impl._M_finish = std::copy(__position, end(), __i); 583 | this->_M_deallocate(); 584 | this->_M_impl._M_end_of_storage = (__q + ((__len 585 | + int(_S_word_bit) - 1) 586 | / int(_S_word_bit))); 587 | this->_M_impl._M_start = iterator(__q, 0); 588 | } 589 | } 590 | ``` 591 | 592 | 所谓动态增加大小,并不是在原空间之后接续新空间(因为无法保证原空间之后尚有可供插入的空间),而是以原大小的两倍另外分配一块空间,然后将原内容拷贝过来,然后才开始在原内容之后插入新元素,并释放原空间。 593 | 594 | #### vector的元素操作pop_back,erase,clear,insert 595 | 596 | **pop_back** 597 | 598 | ```c++ 599 | // stl_bvector.h 600 | 601 | // 将尾部元素拿掉,并调整大小(finish减小) 602 | void pop_back() { 603 | --this->_M_impl._M_finish; 604 | } 605 | 606 | 607 | size_type size() const { 608 | return size_type(end() - begin()); 609 | } 610 | 611 | iterator end() { 612 | return this->_M_impl._M_finish; 613 | } 614 | 615 | ``` 616 | 617 | **erase** 618 | 619 | ```C++ 620 | // stl_bvector.h 621 | 622 | // 清除[first, finish]中的所有元素 623 | // 使用后面的元素覆盖要删除的区间,然后修改 finish 指针 624 | iterator erase(iterator __first, iterator __last) 625 | { 626 | _M_erase_at_end(std::copy(__last, end(), __first)); 627 | return __first; 628 | } 629 | 630 | void _M_erase_at_end(iterator __pos) 631 | { 632 | this->_M_impl._M_finish = __pos; 633 | } 634 | 635 | // 清除某个位置上的元素 636 | iterator erase(iterator __position) 637 | { 638 | if (__position + 1 != end()) 639 | std::copy(__position + 1, end(), __position); 640 | --this->_M_impl._M_finish; 641 | return __position; 642 | } 643 | ``` 644 | 645 | **clear** 646 | 647 | ```c++ 648 | // stl_bvector.h 649 | 650 | // 清除所有元素 651 | void clear() 652 | { 653 | _M_erase_at_end(begin()); 654 | } 655 | 656 | void _M_erase_at_end(iterator __pos) 657 | { 658 | this->_M_impl._M_finish = __pos; 659 | } 660 | ``` 661 | 662 | **insert** 663 | 664 | ```c++ 665 | void _M_insert_aux(iterator __position, bool __x) 666 | { 667 | if (this->_M_impl._M_finish._M_p != this->_M_impl._M_end_of_storage) 668 | { 669 | // 元素后移 670 | std::copy_backward(__position, this->_M_impl._M_finish, 671 | this->_M_impl._M_finish + 1); 672 | // /从安插点开始填入新值 673 | *__position = __x; 674 | // 修改 finish 指针 675 | ++this->_M_impl._M_finish; 676 | } 677 | else 678 | { 679 | // 申请 2 倍的空间 680 | // ... 681 | } 682 | } 683 | ``` 684 | 685 | ### list 686 | 687 | list 每次插入或删除一个元素,就立即分配或释放一个元素空间。list 对于空间的运用有绝对的精准,一点也不浪费。对于任何位置的元素插入或元素删除,list 永远是常数时间。可以这么理解:vector 对应数组,list 对应链表。 688 | 689 | #### list的节点Node 690 | 691 | ```c++ 692 | // stl_list.h 693 | struct _List_node_base 694 | { 695 | _List_node_base* _M_next; ///< Self-explanatory 696 | _List_node_base* _M_prev; ///< Self-explanatory 697 | }; 698 | 699 | /// @if maint An actual node in the %list. @endif 700 | template 701 | struct _List_node : public _List_node_base 702 | { 703 | _Tp _M_data; ///< User's data. 704 | }; 705 | ``` 706 | 707 | #### list的迭代器 708 | 709 | STL 的 list 是一个双向链表(double linked-list),迭代器必须具备前移、后移的能力。所以 list 提供的是 Bidirectional Iterators。 710 | 711 | list 的一个重要性质:插入(insert)、连接(splice)不会造成原有的 list 迭代器失效。这在 vector 中是不成立的。 712 | 713 | ```c++ 714 | // stl_list.h 715 | 716 | template 717 | struct _List_iterator 718 | { 719 | typedef _List_iterator<_Tp> _Self; 720 | typedef _List_node<_Tp> _Node; 721 | 722 | typedef ptrdiff_t difference_type; 723 | typedef std::bidirectional_iterator_tag iterator_category; 724 | typedef _Tp value_type; 725 | typedef _Tp* pointer; 726 | typedef _Tp& reference; 727 | 728 | 729 | // 对于迭代器的取值,取的是节点的 data 730 | reference operator*() const 731 | { 732 | return static_cast<_Node*>(_M_node)->_M_data; 733 | } 734 | // 迭代器的成员存取 735 | pointer operator->() const 736 | { 737 | return &static_cast<_Node*>(_M_node)->_M_data; 738 | } 739 | 740 | 741 | // 跌打器加1,就是前进一个节点 742 | _Self& operator++() 743 | { 744 | _M_node = _M_node->_M_next; 745 | return *this; 746 | } 747 | 748 | // 迭代器减1,就是后退一个节点 749 | _Self& operator--() 750 | { 751 | _M_node = _M_node->_M_prev; 752 | return *this; 753 | } 754 | 755 | }; // struct _List_iterator 756 | ``` 757 | 758 | #### list的数据结构 759 | 760 | list 是一个双向的循环链表。 761 | 762 | ![](images/4-3.png) 763 | 764 | `_Node` 可以转换为迭代器类型: 765 | 766 | ```c++ 767 | protected: 768 | // Note that pointers-to-_Node's can be ctor-converted to 769 | // iterator types. 770 | typedef _List_node<_Tp> _Node; 771 | ``` 772 | 773 | ```c++ 774 | // 取头节点的数值 775 | reference front() 776 | { 777 | return *begin(); 778 | } 779 | ``` 780 | 781 | #### list的构造与内存管理:constructor, push_bask,insert 782 | 783 | list 使用 Alloc 做为空间分配器,并另外定义了 `_Node_alloc_type` ,为的是更方便的以节点大小为分配单位。 784 | 785 | ```C++ 786 | // 使用 Alloc 做为空间分配器 787 | template 788 | 789 | // 每次配置一个节点大小 790 | typedef typename _Alloc::template rebind<_List_node<_Tp> >::other 791 | _Node_alloc_type; 792 | ``` 793 | 794 | ```c++ 795 | // 分配一个节点并返回 796 | _List_node<_Tp>* _M_get_node() 797 | { return _M_impl._Node_alloc_type::allocate(1); } 798 | 799 | // 释放一个节点 800 | void _M_put_node(_List_node<_Tp>* __p) 801 | { _M_impl._Node_alloc_type::deallocate(__p, 1); } 802 | 803 | // 分配一个节点,并赋初值 804 | _Node* _M_create_node(const value_type& __x) 805 | { 806 | _Node* __p = this->_M_get_node(); 807 | try 808 | { 809 | _M_get_Tp_allocator().construct(&__p->_M_data, __x); 810 | } 811 | catch(...) 812 | { 813 | _M_put_node(__p); 814 | __throw_exception_again; 815 | } 816 | return __p; 817 | } 818 | 819 | 820 | // 删除一个节点 821 | // Erases element at position given. 822 | void _M_erase(iterator __position) 823 | { 824 | __position._M_node->unhook(); 825 | _Node* __n = static_cast<_Node*>(__position._M_node); 826 | _M_get_Tp_allocator().destroy(&__n->_M_data); 827 | _M_put_node(__n); 828 | } 829 | // new_allocator.h 830 | void destroy(pointer __p) { __p->~_Tp(); } 831 | ``` 832 | 833 | list 提供了很多 constructors: 834 | 835 | ```C++ 836 | explicit list(const allocator_type& __a = allocator_type()) 837 | : _Base(__a) { } 838 | ``` 839 | 840 | push_back() 将新元素插入到 list 的尾部: 841 | 842 | ```c++ 843 | void push_back(const value_type& __x) 844 | { 845 | this->_M_insert(end(), __x); 846 | } 847 | 848 | // Inserts new element at position given and with value given. 849 | void _M_insert(iterator __position, const value_type& __x) 850 | { 851 | _Node* __tmp = _M_create_node(__x); 852 | __tmp->hook(__position._M_node); 853 | } 854 | ``` 855 | 856 | 在 list 内的某处插入新节点,首先必须确定安插位置。 857 | 858 | ```c++ 859 | void insert(iterator __position, size_type __n, const value_type& __x) 860 | { 861 | list __tmp(__n, __x, _M_get_Node_allocator()); 862 | splice(__position, __tmp); 863 | } 864 | 865 | // example: 在ls链表头插入 866 | ls.insert(ls.begin(), 6); 867 | ``` 868 | 869 | list 不像 vector 那样有可能在空间不足时做重新分配、数据迁移的动作,所以插入前的所有迭代器在插入动作之后都仍然有效。 870 | 871 | #### list的元素操作 872 | 873 | ```C++ 874 | // 插入一个节点,作为头节点 875 | void push_front(const value_type& __x) 876 | { this->_M_insert(begin(), __x); } 877 | 878 | // 插入一个节点,作为尾节点 879 | void push_back(const value_type& __x) 880 | { this->_M_insert(end(), __x); } 881 | 882 | // 删除迭代器 position 所指节点 883 | iterator erase(iterator __position); 884 | 885 | // 删除头节点 886 | void pop_front() 887 | { this->_M_erase(begin()); } 888 | 889 | // 删除尾节点 890 | void pop_back() 891 | { 892 | this->_M_erase(iterator(this->_M_impl._M_node._M_prev)); } 893 | 894 | ``` 895 | 896 | list 内部提供一个所谓的迁移动作(transfer),将某连续范围的元素迁移到某个特定位置之前。 897 | 898 | ```c++ 899 | // Moves the elements from [first,last) before position. 900 | void _M_transfer(iterator __position, iterator __first, iterator __last) 901 | { 902 | __position._M_node->transfer(__first._M_node, __last._M_node); 903 | } 904 | ``` 905 | 906 | list 公开提供的是所谓的接合动作(splice):将某连续范围的元素从一个 list 搬移到另一个(或同一个)list 的某个定点。 907 | 908 | ```C++ 909 | // 将x连接到position所指的位置之前 910 | void splice(iterator __position, list& __x) 911 | { 912 | if (!__x.empty()) 913 | { 914 | _M_check_equal_allocators(__x); 915 | this->_M_transfer(__position, __x.begin(), __x.end()); 916 | } 917 | } 918 | 919 | // 将i所指元素连接到__position所指位置之前 920 | void splice(iterator __position, list& __x, iterator __i) 921 | { 922 | iterator __j = __i; 923 | ++__j; 924 | if (__position == __i || __position == __j) 925 | return; 926 | 927 | if (this != &__x) 928 | _M_check_equal_allocators(__x); 929 | 930 | this->_M_transfer(__position, __i, __j); 931 | } 932 | 933 | // 将 [first,last) 内的所有元素连接接于 position所指位置之前。 934 | void splice(iterator __position, list& __x, iterator __first, iterator __last) 935 | { 936 | if (__first != __last) 937 | { 938 | if (this != &__x) 939 | _M_check_equal_allocators(__x); 940 | 941 | this->_M_transfer(__position, __first, __last); 942 | } 943 | } 944 | ``` 945 | 946 | 有了 transfer(),merge()、reverse() 和 sort() 的源码并不难实现。 947 | 948 | ```c++ 949 | template 950 | void list<_Tp, _Alloc>:: 951 | merge(list& __x) 952 | { 953 | // _GLIBCXX_RESOLVE_LIB_DEFECTS 954 | // 300. list::merge() specification incomplete 955 | if (this != &__x) 956 | { 957 | _M_check_equal_allocators(__x); 958 | 959 | iterator __first1 = begin(); 960 | iterator __last1 = end(); 961 | iterator __first2 = __x.begin(); 962 | iterator __last2 = __x.end(); 963 | while (__first1 != __last1 && __first2 != __last2) 964 | if (*__first2 < *__first1) 965 | { 966 | iterator __next = __first2; 967 | _M_transfer(__first1, __first2, ++__next); 968 | __first2 = __next; 969 | } 970 | else 971 | ++__first1; 972 | if (__first2 != __last2) 973 | _M_transfer(__last1, __first2, __last2); 974 | } 975 | } 976 | ``` 977 | 978 | ### deque 979 | 980 | vector 是单向开口的连续线性空间,也就是说,只能从一端进行插入。deque 则是一种双向开口的连续线性空间,可以在头尾两端分别􏰁做元素的插入和删除动作。 981 | 982 | ![](images/4-4.png) 983 | 984 | deque 在两端插入或删除,时间复杂度都是常数级的。不同于 vector,如果在头插入,需要将所有元素后移,时间复杂度是线性级别的。 985 | 986 | 应尽可能选择使用 vector 而非 deque。对 deque 进行的排序动作,为了最高效率,可将 deque 先完整复制到一个 vector 身上,将 vector 排序后(利用 STL sort 算法),再复制回 deque。 987 | 988 | #### deque的中控件 989 | 990 | deque 由一段一段的定量连续空间构成。一旦有必要在 deque 的前端或尾端增加新空间,便配置一段定量连续空间,串接在整个 deque 的头端或尾端。 991 | 992 | 为了维护整体连续的假象,数据结构的设计及迭代器前进后退等动作都颇为繁琐。deque 的代码量远比 vector 或 list 多得多。 993 | 994 | deque 采用一块 map(一小块连续的控件),其中的每个元素指向另一段较大的连续线性空间,成为缓冲区。缓冲区是 deque 的存储空间主体。 995 | 996 | ```C++ 997 | protected: 998 | // 元素的指针的指针 999 | typedef pointer* _Map_pointer; 1000 | 1001 | 1002 | // 每个node都指向一块缓冲区 1003 | _Map_pointer _M_node; 1004 | ``` 1005 | 1006 | ![](images/4-5.png) 1007 | 1008 | #### deque的迭代器 1009 | 1010 | deque 是分段连续空间。 1011 | 1012 | ```c++ 1013 | template 1014 | struct _Deque_iterator // 未继承 std::iterator 1015 | { 1016 | typedef _Deque_iterator<_Tp, _Tp&, _Tp*> iterator; 1017 | typedef _Deque_iterator<_Tp, const _Tp&, const _Tp*> const_iterator; 1018 | 1019 | static size_t _S_buffer_size() 1020 | { return __deque_buf_size(sizeof(_Tp)); } 1021 | 1022 | // 自行撰写 5 个必要的跌打器类型 1023 | typedef std::random_access_iterator_tag iterator_category; //(1) 1024 | typedef _Tp value_type; // (2) 1025 | typedef _Ptr pointer; // (3) 1026 | typedef _Ref reference; // (4) 1027 | typedef size_t size_type; 1028 | typedef ptrdiff_t difference_type; // (5) 1029 | typedef _Tp** _Map_pointer; 1030 | typedef _Deque_iterator _Self; 1031 | 1032 | _Tp* _M_cur; // 此迭代器所指缓冲区的当前(current)元素 1033 | _Tp* _M_first; // 指向缓冲区的头 1034 | _Tp* _M_last; // 指向缓冲区的尾 1035 | _Map_pointer _M_node; // 指向控制中心 1036 | 1037 | // ... 1038 | }; 1039 | ``` 1040 | 1041 | ```C++ 1042 | // 决定缓冲区大小的函数 1043 | static size_t _S_buffer_size() 1044 | { return __deque_buf_size(sizeof(_Tp)); } 1045 | 1046 | // 如果 sz(元素大小,sizeof(value_type))小于 512,传回 512/sz, 1047 | // 如果 sz 不小于 512,传回 1。 1048 | inline size_t 1049 | __deque_buf_size(size_t __size) 1050 | { return __size < 512 ? size_t(512 / __size) : size_t(1); } 1051 | ``` 1052 | 1053 | ![](images/4-6.png) 1054 | 1055 | begin() 和 end() 所传回的两个迭代器如下图: 1056 | 1057 | ![](images/4-7.png) 1058 | 1059 | 一旦行进时遇到缓冲区边缘,视前进或后退而定,可能需要调用 set_node() 切换缓冲区。 1060 | 1061 | ```C++ 1062 | void _M_set_node(_Map_pointer __new_node) 1063 | { 1064 | _M_node = __new_node; 1065 | _M_first = *__new_node; 1066 | _M_last = _M_first + difference_type(_S_buffer_size()); 1067 | } 1068 | 1069 | _Self& operator++() 1070 | { 1071 | ++_M_cur; 1072 | if (_M_cur == _M_last) 1073 | { 1074 | // 切换下一个节点(即下一个缓冲区) 1075 | _M_set_node(_M_node + 1); 1076 | _M_cur = _M_first; 1077 | } 1078 | return *this; 1079 | } 1080 | ``` 1081 | 1082 | #### deque的数据结构 1083 | 1084 | deque 维护 start, finish 两个迭代器,分􏰁指向第一缓冲区的第一个元素和最后缓冲区的最后一个元素(的下一位置)。 1085 | 1086 | ``` 1087 | struct _Deque_impl 1088 | : public _Tp_alloc_type 1089 | { 1090 | _Tp** _M_map; // 指向map,一块连续的空间 1091 | size_t _M_map_size; // map内的节点数 1092 | iterator _M_start; // 第一个节点 1093 | iterator _M_finish; // 最后一个节点 1094 | 1095 | _Deque_impl(const _Tp_alloc_type& __a) 1096 | : _Tp_alloc_type(__a), _M_map(0), _M_map_size(0), 1097 | _M_start(), _M_finish() 1098 | { } 1099 | }; 1100 | ``` 1101 | 1102 | 有了以上的结构,很多操作便可以轻易完成: 1103 | 1104 | ```C++ 1105 | // iterators 1106 | /** 1107 | * Returns a read/write iterator that points to the first element in the 1108 | * %deque. Iteration is done in ordinary element order. 1109 | */ 1110 | iterator 1111 | begin() 1112 | { return this->_M_impl._M_start; } 1113 | 1114 | /** 1115 | * Returns a read/write iterator that points one past the last 1116 | * element in the %deque. Iteration is done in ordinary 1117 | * element order. 1118 | */ 1119 | iterator 1120 | end() 1121 | { return this->_M_impl._M_finish; } 1122 | ``` 1123 | 1124 | #### deque的构造与内存管理 1125 | 1126 | deque自行定义了两个专属的空间配置器: 1127 | 1128 | ```C++ 1129 | // 每次分配一个元素大小 1130 | typedef _Deque_base<_Tp, _Alloc> _Base; 1131 | // 每次分配一个指针大小 1132 | typedef typename _Base::_Tp_alloc_type _Tp_alloc_type; 1133 | ``` 1134 | 1135 | 并提供 constructor: 1136 | 1137 | ```c++ 1138 | explicit deque(size_type __n, const value_type& __value = value_type(), 1139 | const allocator_type& __a = allocator_type()) 1140 | : _Base(__a, __n) 1141 | { _M_fill_initialize(__value); } 1142 | ``` 1143 | 1144 | `_M_fill_initialize()`产生并初始化后 deque 的结构: 1145 | 1146 | ```C++ 1147 | template 1148 | void 1149 | deque<_Tp, _Alloc>:: 1150 | _M_fill_initialize(const value_type& __value) 1151 | { 1152 | _Map_pointer __cur; 1153 | try 1154 | { 1155 | // 为每个节点的缓冲区设定初值 1156 | for (__cur = this->_M_impl._M_start._M_node; 1157 | __cur < this->_M_impl._M_finish._M_node; 1158 | ++__cur) 1159 | std::__uninitialized_fill_a(*__cur, *__cur + _S_buffer_size(), 1160 | __value, _M_get_Tp_allocator()); 1161 | // 最后一个节点设定不同,尾端可能有备用空间,不必设初值 1162 | std::__uninitialized_fill_a(this->_M_impl._M_finish._M_first, 1163 | this->_M_impl._M_finish._M_cur, 1164 | __value, _M_get_Tp_allocator()); 1165 | } 1166 | catch(...) 1167 | { 1168 | std::_Destroy(this->_M_impl._M_start, iterator(*__cur, __cur), 1169 | _M_get_Tp_allocator()); 1170 | __throw_exception_again; 1171 | } 1172 | } 1173 | ``` 1174 | 1175 | push_back() 函数 1176 | 1177 | ```C++ 1178 | void push_back(const value_type& __x) 1179 | { 1180 | if (this->_M_impl._M_finish._M_cur 1181 | != this->_M_impl._M_finish._M_last - 1) 1182 | { 1183 | // 最后缓冲区尚有一个以上的备用空间 1184 | this->_M_impl.construct(this->_M_impl._M_finish._M_cur, __x); //直接在备用空间上建构元素 1185 | ++this->_M_impl._M_finish._M_cur; //调整最后缓冲区的使用状态 1186 | } 1187 | else // 最后缓冲区已无(或只剩一个)元素备用空间。 1188 | _M_push_back_aux(__x); 1189 | } 1190 | 1191 | 1192 | // 只有当 finish.cur == finish.last – 1时才会被调用。 1193 | // 即:当最后一个缓冲区只剩一个备用元素空间时才会被呼叫。 1194 | template 1195 | void deque<_Tp, _Alloc>:: 1196 | _M_push_back_aux(const value_type& __t) 1197 | { 1198 | value_type __t_copy = __t; 1199 | _M_reserve_map_at_back(); // // 如果 map尾端的节点备用空间不足,则必须重换一个map 1200 | *(this->_M_impl._M_finish._M_node + 1) = this->_M_allocate_node(); //配置一个新节点(缓冲区) 1201 | try 1202 | { 1203 | this->_M_impl.construct(this->_M_impl._M_finish._M_cur, __t_copy); //针对标的元素设值 1204 | this->_M_impl._M_finish._M_set_node(this->_M_impl._M_finish._M_node 1205 | + 1); //改变 finish,令其指向新节点 1206 | this->_M_impl._M_finish._M_cur = this->_M_impl._M_finish._M_first; //设定finish的状态 1207 | } 1208 | catch(...) 1209 | { 1210 | _M_deallocate_node(*(this->_M_impl._M_finish._M_node + 1)); 1211 | __throw_exception_again; 1212 | } 1213 | } 1214 | ``` 1215 | 1216 | `push_front()` 函数: 1217 | 1218 | ```C++ 1219 | void push_front(const value_type& __x) 1220 | { 1221 | //第一缓冲区尚有备用空间 1222 | if (this->_M_impl._M_start._M_cur != this->_M_impl._M_start._M_first) 1223 | { 1224 | // 直接在备用空间上建构元素 1225 | this->_M_impl.construct(this->_M_impl._M_start._M_cur - 1, __x); 1226 | //调整第一缓冲区的使用状态 1227 | --this->_M_impl._M_start._M_cur; 1228 | } 1229 | // 第一缓冲区已无备用空间 1230 | else 1231 | _M_push_front_aux(__x); 1232 | } 1233 | ``` 1234 | 1235 | #### deque的元素操作pop_back,pop_front,clear,erase,insert 1236 | 1237 | 所谓 pop,是将元素拿掉。无论从 deque 的最前端或最尾端取元素,都需考虑在某种条件下,将缓冲区释放掉: 1238 | 1239 | ```C++ 1240 | void pop_front() 1241 | { 1242 | // 第一缓冲区有一个(或更多)元素 1243 | if (this->_M_impl._M_start._M_cur 1244 | != this->_M_impl._M_start._M_last - 1) 1245 | { 1246 | // 将第一元素销毁 1247 | this->_M_impl.destroy(this->_M_impl._M_start._M_cur); 1248 | // //调整指针,相当于排除了第一元素 1249 | ++this->_M_impl._M_start._M_cur; 1250 | } 1251 | // 第一缓冲区仅有一个元素,进行缓冲区的释放工作 1252 | else 1253 | _M_pop_front_aux(); 1254 | } 1255 | 1256 | //只有当 start.cur == start.last - 1 时才会被呼叫。 1257 | template 1258 | void deque<_Tp, _Alloc>:: 1259 | _M_pop_front_aux() 1260 | { 1261 | // 将第一缓冲区的第一个元素解构 1262 | this->_M_impl.destroy(this->_M_impl._M_start._M_cur); 1263 | // //释放第一缓冲区。 1264 | _M_deallocate_node(this->_M_impl._M_start._M_first); 1265 | //调整 start的状态 1266 | this->_M_impl._M_start._M_set_node(this->_M_impl._M_start._M_node + 1); 1267 | // 下一个缓冲区的第一个元素。 1268 | this->_M_impl._M_start._M_cur = this->_M_impl._M_start._M_first; 1269 | } 1270 | ``` 1271 | 1272 | `clear()`,用来清除整个 deque。请注意,deque 的最初状态(无任何元素时)保有一个缓冲区,因此 clear() 完成之后回复初始状态,也一样要 1273 | 保留一个缓冲区: 1274 | 1275 | ```C++ 1276 | void clear() 1277 | { _M_erase_at_end(begin()); } 1278 | 1279 | // Called by erase(q1, q2), resize(), clear(), _M_assign_aux, 1280 | // _M_fill_assign, operator=. 1281 | void _M_erase_at_end(iterator __pos) 1282 | { 1283 | _M_destroy_data(__pos, end(), _M_get_Tp_allocator()); 1284 | // +1 的目的是:保留头尾缓冲区 1285 | _M_destroy_nodes(__pos._M_node + 1, 1286 | this->_M_impl._M_finish._M_node + 1); 1287 | this->_M_impl._M_finish = __pos; 1288 | } 1289 | ``` 1290 | 1291 | `insert()` 1292 | 1293 | ```C++ 1294 | template 1295 | typename deque<_Tp, _Alloc>::iterator 1296 | deque<_Tp, _Alloc>:: 1297 | insert(iterator __position, const value_type& __x) 1298 | { 1299 | // 如果插入点是 deque最前端 1300 | if (__position._M_cur == this->_M_impl._M_start._M_cur) 1301 | { 1302 | push_front(__x); 1303 | return this->_M_impl._M_start; 1304 | } 1305 | // 如果插入点是 deque最尾端 1306 | else if (__position._M_cur == this->_M_impl._M_finish._M_cur) 1307 | { 1308 | push_back(__x); 1309 | iterator __tmp = this->_M_impl._M_finish; 1310 | --__tmp; 1311 | return __tmp; 1312 | } 1313 | else 1314 | return _M_insert_aux(__position, __x); 1315 | } 1316 | 1317 | 1318 | 1319 | template 1320 | typename deque<_Tp, _Alloc>::iterator 1321 | deque<_Tp, _Alloc>:: 1322 | _M_insert_aux(iterator __pos, const value_type& __x) 1323 | { 1324 | // 安插点之前的元素个数 1325 | difference_type __index = __pos - this->_M_impl._M_start; 1326 | value_type __x_copy = __x; // XXX copy 1327 | // 如果安插点之前的元素个数比较少 1328 | if (static_cast(__index) < size() / 2) 1329 | { 1330 | // 在最前端加入与第一元素同值的元素。 1331 | push_front(front()); 1332 | // 以下标示记号,然后进行元素搬移... 1333 | iterator __front1 = this->_M_impl._M_start; 1334 | ++__front1; 1335 | iterator __front2 = __front1; 1336 | ++__front2; 1337 | __pos = this->_M_impl._M_start + __index; 1338 | iterator __pos1 = __pos; 1339 | ++__pos1; 1340 | // 元素搬移 1341 | std::copy(__front2, __pos1, __front1); 1342 | } 1343 | else //安插点之后的元素个数比较少 1344 | { 1345 | push_back(back()); // 最尾端插入与最后元素同值的元素 1346 | iterator __back1 = this->_M_impl._M_finish; 1347 | --__back1; 1348 | iterator __back2 = __back1; 1349 | --__back2; 1350 | __pos = this->_M_impl._M_start + __index; 1351 | // 元素搬移 1352 | std::copy_backward(__pos, __back2, __back1); 1353 | } 1354 | // 在插入点设定新值 1355 | *__pos = __x_copy; 1356 | return __pos; 1357 | } 1358 | ``` 1359 | 1360 | ### stack 1361 | 1362 | stack 是一种先进后出(First In Last Out,FILO)的数据结构,它只有一个出口。stack 允许新增元素、移除元素、取得最顶端元素。但除了最顶端外,没有任何其它方法可以存取 stack 的其它元素。 1363 | 1364 | ![](images/4-8.png) 1365 | 1366 | #### stack定义式完整列表 1367 | 1368 | 以某种既有容器做为底部结构,将其接口改变,使符合「先进后出」的特性,形 1369 | 成一个 stack,是很容易做到的。deque 是双向开口的数据结构,若以 deque 为 1370 | 底部结构并封闭其头端开口,便轻而易举地形成了一个 stack。 1371 | 1372 | ``` 1373 | template > 1374 | class stack 1375 | { 1376 | protected: 1377 | // 底层容器 1378 | _Sequence c; 1379 | }; 1380 | ``` 1381 | 1382 | ![](images/4-9.png) 1383 | 1384 | ```C++ 1385 | /** Returns true if the %stack is empty. */ 1386 | bool empty() const 1387 | { return c.empty(); } 1388 | 1389 | /** Returns the number of elements in the %stack. */ 1390 | size_type size() const 1391 | { return c.size(); } 1392 | 1393 | ``` 1394 | 1395 | #### stack没有迭代器 1396 | 1397 | stack 所有元素的进出都必须符合「先进后出」的条件,只有 stack 顶端的元素,才有机会被外界取用。 不提供迭代器。 1398 | 1399 | #### 以list为stack的底层容器 1400 | 1401 | 除了deque 之外,list 也是双向开口的数据结构。上述 stack 源码中使用的底层容器的函数有 empty, size, back, push_back, pop_back,list 都具备。 1402 | 1403 | ### queue 1404 | 1405 | queue 是一种先进先出(First In First Out,FIFO)的数据结构,它有两个出口。 1406 | 1407 | ![](images/4-10.png) 1408 | 1409 | queue 只能从一端插入,另一端删除。除了最底端可以加入、最顶端可以取出,没有任何其它方法可以存取 queue 的其它元素。 1410 | 1411 | #### queue定义式完整列表 1412 | 1413 | SGI STL 便以 deque 做为预设情况下的 queue 底层结构。 1414 | 1415 | ```C++ 1416 | template > 1417 | class queue 1418 | { 1419 | protected: 1420 | // 底层容器 1421 | _Sequence c; 1422 | }; 1423 | ``` 1424 | 1425 | ![](images/4-11.png) 1426 | 1427 | ```C++ 1428 | void push(const value_type& __x) 1429 | { 1430 | c.push_back(__x); 1431 | } 1432 | 1433 | void pop() 1434 | { 1435 | __glibcxx_requires_nonempty(); 1436 | c.pop_front(); 1437 | } 1438 | ``` 1439 | 1440 | #### queue没有迭代器 1441 | 1442 | queue 所有元素的进出都必须符合「先进先出」的条件,只有 queue 顶端的元素,才有机会被外界取用。 1443 | 1444 | #### 以list做为queue的底层容器 1445 | 1446 | 除了deque 之外,list 也是双向开口的数据结构。上述 queue 源码中使用的底层容器的函数有 empty, size, back, push_back, pop_back,list 都具备。 1447 | 1448 | ### heap 1449 | 1450 | heap 并不归属于 STL 容器组件,它的背后是 priority queue(优先队列)。priority queue 允许使用者以任何次序将任何元素推入容器内,但取出时一定是从优先权最高的元素开始取。 1451 | 1452 | 使用 list 做为 priority queue 的底层机制,元素插入动作可享常数时间。但是要找到 list 中的极值,却需要对整个 list 进行线性扫描。 1453 | 1454 | 使用 binary search tree 做为 priority queue 的底层机制,元素的插入和极值的取得就有 O(logN) 的表现。但是这需要确保输入数据的随机性。 1455 | 1456 | priority queue 的复杂度,最好介于 queue 和 binary search tree之间,才算适得其所。binary heap 便是这种条件下的适当候选人。 1457 | 1458 | binary heap 是一颗完全二叉树。当完全二叉树中的某个节点位于 array 的 i 处,其左子节点必位于 array 的 2i+1 处,其右子节点必位于 array 的 2i+2 处(这里的索引从 0 开始)。 1459 | 1460 | ![](images/4-12.png) 1461 | 1462 | 其父节点必定是 ⌊(i - 1)/2⌋。 1463 | 1464 | 根据元素排列方式,heap 可分为 max-heap 和 min-heap 两种,max-heap 的最大值在根节点,min-heap 的最小值在根节点。 1465 | 1466 | #### heap算法 1467 | 1468 | **push_heap** 1469 | 1470 | 为了保持完全二叉树的性质,应该将新元素插入在底层 vector 的 end() 处。 1471 | 1472 | ```C++ 1473 | template 1474 | inline void 1475 | push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) 1476 | { 1477 | std::__push_heap(__first, _DistanceType((__last - __first) - 1), 1478 | _DistanceType(0), _ValueType(*(__last - 1))); 1479 | } 1480 | 1481 | 1482 | template 1483 | inline void 1484 | push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, 1485 | _Compare __comp) 1486 | { 1487 | // 值必置于底部 -> 容器的最尾端 1488 | std::__push_heap(__first, _DistanceType((__last - __first) - 1), 1489 | _DistanceType(0), _ValueType(*(__last - 1)), __comp); 1490 | } 1491 | 1492 | // 不允许指定,(大小比较标准) 1493 | template 1495 | void 1496 | __push_heap(_RandomAccessIterator __first, _Distance __holeIndex, 1497 | _Distance __topIndex, _Tp __value, _Compare __comp) 1498 | { 1499 | _Distance __parent = (__holeIndex - 1) / 2; // 父节点 1500 | while (__holeIndex > __topIndex 1501 | && __comp(*(__first + __parent), __value)) 1502 | { 1503 | // 当尚􏰃到达顶端,且父节点小于新值 1504 | *(__first + __holeIndex) = *(__first + __parent); 1505 | __holeIndex = __parent; 1506 | __parent = (__holeIndex - 1) / 2; 1507 | } 1508 | *(__first + __holeIndex) = __value; 1509 | } 1510 | 1511 | ``` 1512 | 1513 | **pop_heap** 1514 | 1515 | pop 动作取走根节点,必须将最下一层最右边的叶节点拿来填补跟节点的位置,并维护堆的性质。 1516 | ```C++ 1517 | template 1518 | inline void 1519 | pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) 1520 | { 1521 | std::__pop_heap(__first, __last - 1, __last - 1, 1522 | _ValueType(*(__last - 1))); 1523 | } 1524 | 1525 | template 1526 | inline void 1527 | pop_heap(_RandomAccessIterator __first, 1528 | _RandomAccessIterator __last, _Compare __comp) 1529 | { 1530 | std::__pop_heap(__first, __last - 1, __last - 1, 1531 | _ValueType(*(__last - 1)), __comp); 1532 | } 1533 | 1534 | template 1535 | inline void 1536 | __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, 1537 | _RandomAccessIterator __result, _Tp __value) 1538 | { 1539 | typedef typename iterator_traits<_RandomAccessIterator>::difference_type 1540 | _Distance; 1541 | // 设定尾值为首值,于是尾值即为欲求结果 1542 | // 可由客端稍后再以底层容器之 pop_back() 取出尾值。 1543 | *__result = *__first; 1544 | // 以上欲重新调整 heap 1545 | std::__adjust_heap(__first, _Distance(0), _Distance(__last - __first), 1546 | __value); 1547 | } 1548 | 1549 | 1550 | template 1552 | void 1553 | __adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex, 1554 | _Distance __len, _Tp __value, _Compare __comp) 1555 | { 1556 | const _Distance __topIndex = __holeIndex; 1557 | _Distance __secondChild = 2 * __holeIndex + 2; // 右节点 1558 | while (__secondChild < __len) 1559 | { 1560 | if (__comp(*(__first + __secondChild), 1561 | *(__first + (__secondChild - 1)))) 1562 | __secondChild--; // 减1后为左节点 1563 | 1564 | // secondChild代表较大子节点 1565 | *(__first + __holeIndex) = *(__first + __secondChild); 1566 | __holeIndex = __secondChild; 1567 | __secondChild = 2 * (__secondChild + 1); 1568 | } 1569 | // 如果没有右节点,只有左子节点 1570 | if (__secondChild == __len) 1571 | { 1572 | *(__first + __holeIndex) = *(__first + (__secondChild - 1)); 1573 | __holeIndex = __secondChild - 1; 1574 | } 1575 | std::__push_heap(__first, __holeIndex, __topIndex, __value, __comp); 1576 | } 1577 | ``` 1578 | 1579 | pop_heap 之后,最大元素只是被置放于底部容器的最尾端,尚􏰃被取走。如果要取其值,可使用底部容器(vector)所提供的 back() 操作函数。如果要移除它,可使用底部容器(vector)所提供的 pop_back() 操作函式。 1580 | 1581 | **sort_heap** 1582 | 排序过后,原来的 heap 就不再是个合法的 heap 了。 1583 | ```C++ 1584 | // 每执行一次 pop_heap(),极值(在 STL heap 中为极大值)即被放在尾端。 1585 | // 扣除尾端再执行一次 pop_heap(),次极值又被放在新尾端。一直下去,最后即得 1586 | // 排序结果。 1587 | template 1588 | void 1589 | sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) 1590 | { 1591 | while (__last - __first > 1) 1592 | std::pop_heap(__first, _RandomAccessIterator(__last--)); 1593 | } 1594 | ``` 1595 | 1596 | **make_heap** 1597 | 这个算法用来将一段现有的数据转化为一个 heap。 1598 | ``` 1599 | template 1600 | void 1601 | make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) 1602 | { 1603 | // 如果长度为 0或 1,不必重新排列。 1604 | if (__last - __first < 2) 1605 | return; 1606 | 1607 | const _DistanceType __len = __last - __first; 1608 | _DistanceType __parent = (__len - 2) / 2; 1609 | while (true) 1610 | { 1611 | std::__adjust_heap(__first, __parent, __len, 1612 | _ValueType(*(__first + __parent))); 1613 | if (__parent == 0) 1614 | return; 1615 | __parent--; 1616 | } 1617 | } 1618 | ``` 1619 | 1620 | #### heap也没有迭代器 1621 | 1622 | ### priority_queue 1623 | priority_queue 是一个拥有权值观念的 queue,它允许加入新元素、移除旧元素,审视元素值等功能。由于这是一个 queue,所以只允许在底端加入元素,并从顶端取出元素,除此之外􏰁无其它存取元素的途径。 1624 | 1625 | ``` 1626 | template, 1627 | typename _Compare = less > 1628 | class priority_queue 1629 | { 1630 | protected: 1631 | // vector为底层容器 1632 | _Sequence c; 1633 | _Compare comp; // 元素大小的比较标准 1634 | 1635 | // .... 1636 | }; 1637 | ``` 1638 | ![](images/4-13.png) 1639 | #### priority_queue也没有迭代器 1640 | 1641 | ### slist 1642 | STL list 是个双向链表(double linked list)。SGI STL 另提供了一个单向串行(single linked list),名为slist。 1643 | slist 和 list 的主要差􏰁在于,前者的迭代器属于单向的 Forward Iterator,后者的迭代器属于双向的 Bidirectional Iterator。 1644 | slist 和 list 共同具有的一个相同特色是,它们的插入(insert)、移除(erase)、接合(splice)等动作并不会造成原有的迭代器失效。 1645 | 1646 | 基于效率考虑,slist 不提供 push_back(),只提供 push_front()。 1647 | 1648 | #### slist的节点 1649 | ```C++ 1650 | // 单向串行的节点基􏰀结构 1651 | struct _Slist_node_base 1652 | { 1653 | _Slist_node_base* _M_next; 1654 | }; 1655 | 1656 | // 单向串行的节点结构 1657 | template 1658 | struct _Slist_node : public _Slist_node_base 1659 | { 1660 | _Tp _M_data; 1661 | }; 1662 | 1663 | //已知某一节点,安插新节点于其后。 1664 | inline _Slist_node_base* 1665 | __slist_make_link(_Slist_node_base* __prev_node, 1666 | _Slist_node_base* __new_node) 1667 | { 1668 | __new_node->_M_next = __prev_node->_M_next; 1669 | __prev_node->_M_next = __new_node; 1670 | return __new_node; 1671 | } 1672 | 1673 | // 反转一个链表 1674 | inline _Slist_node_base* 1675 | __slist_reverse(_Slist_node_base* __node) 1676 | { 1677 | _Slist_node_base* __result = __node; 1678 | __node = __node->_M_next; 1679 | __result->_M_next = 0; 1680 | while(__node) 1681 | { 1682 | _Slist_node_base* __next = __node->_M_next; 1683 | __node->_M_next = __result; 1684 | __result = __node; 1685 | __node = __next; 1686 | } 1687 | return __result; 1688 | } 1689 | 1690 | ``` 1691 | ### slist的迭代器 1692 | ```C++ 1693 | //单向串行的迭代器基􏰀结构 1694 | struct _Slist_iterator_base 1695 | { 1696 | typedef size_t size_type; 1697 | typedef ptrdiff_t difference_type; 1698 | typedef std::forward_iterator_tag iterator_category; // 单向 1699 | 1700 | _Slist_node_base* _M_node; //指向节点基􏰀结构 1701 | 1702 | void _M_incr() // // 前进一个节点 1703 | { _M_node = _M_node->_M_next; } 1704 | 1705 | // .... 1706 | }; 1707 | 1708 | //单向串行的迭代器结构 1709 | template 1710 | struct _Slist_iterator : public _Slist_iterator_base 1711 | { 1712 | typedef _Slist_iterator<_Tp, _Tp&, _Tp*> iterator; 1713 | typedef _Slist_iterator<_Tp, const _Tp&, const _Tp*> const_iterator; 1714 | typedef _Slist_iterator<_Tp, _Ref, _Ptr> _Self; 1715 | 1716 | _Self& 1717 | operator++() 1718 | { 1719 | _M_incr(); // //前进一个节点 1720 | return *this; 1721 | } 1722 | 1723 | _Self 1724 | operator++(int) 1725 | { 1726 | _Self __tmp = *this; 1727 | _M_incr(); // //前进一个节点 1728 | return __tmp; 1729 | } 1730 | }; 1731 | ``` 1732 | 1733 | #### slist的数据结构 1734 | ```C++ 1735 | template > 1736 | class slist : private _Slist_base<_Tp,_Alloc> 1737 | { 1738 | // concept requirements 1739 | __glibcxx_class_requires(_Tp, _SGIAssignableConcept) 1740 | 1741 | private: 1742 | typedef _Slist_base<_Tp,_Alloc> _Base; 1743 | 1744 | public: 1745 | typedef _Tp value_type; 1746 | typedef value_type* pointer; 1747 | typedef const value_type* const_pointer; 1748 | typedef value_type& reference; 1749 | typedef const value_type& const_reference; 1750 | typedef size_t size_type; 1751 | typedef ptrdiff_t difference_type; 1752 | 1753 | typedef _Slist_iterator<_Tp, _Tp&, _Tp*> iterator; 1754 | typedef _Slist_iterator<_Tp, const _Tp&, const _Tp*> const_iterator; 1755 | 1756 | typedef typename _Base::allocator_type allocator_type; 1757 | private: 1758 | typedef _Slist_node<_Tp> _Node; 1759 | typedef _Slist_node_base _Node_base; 1760 | typedef _Slist_iterator_base _Iterator_base; 1761 | 1762 | _Node* 1763 | _M_create_node(const value_type& __x) 1764 | { 1765 | // 配置空间 1766 | _Node* __node = this->_M_get_node(); 1767 | try 1768 | { 1769 | // 构造元素 1770 | get_allocator().construct(&__node->_M_data, __x); 1771 | __node->_M_next = 0; 1772 | } 1773 | catch(...) 1774 | { 1775 | this->_M_put_node(__node); 1776 | __throw_exception_again; 1777 | } 1778 | return __node; 1779 | } 1780 | }; 1781 | 1782 | iterator 1783 | begin() 1784 | { return iterator((_Node*)this->_M_head._M_next); } 1785 | 1786 | iterator 1787 | end() 1788 | { return iterator(0); } 1789 | 1790 | bool 1791 | empty() const 1792 | { return this->_M_head._M_next == 0; } 1793 | 1794 | void 1795 | swap(slist& __x) 1796 | { std::swap(this->_M_head._M_next, __x._M_head._M_next); } 1797 | 1798 | // 取头部元素 1799 | reference 1800 | front() 1801 | { return ((_Node*) this->_M_head._M_next)->_M_data; } 1802 | 1803 | // 删除头部元素 1804 | void 1805 | pop_front() 1806 | { 1807 | _Node* __node = (_Node*) this->_M_head._M_next; 1808 | this->_M_head._M_next = __node->_M_next; 1809 | get_allocator().destroy(&__node->_M_data); 1810 | this->_M_put_node(__node); 1811 | } 1812 | }; 1813 | ``` 1814 | 1815 | --------------------------------------------------------------------------------