STL Containers Inside Peter Sikachev Institute of Computer

  • Slides: 59
Download presentation
STL Containers Inside Peter Sikachev Institute of Computer Graphics and Algorithms Vienna University of

STL Containers Inside Peter Sikachev Institute of Computer Graphics and Algorithms Vienna University of Technology

Overview Introduction Iterators vector list set and map Performance Overview Peter Sikachev 1

Overview Introduction Iterators vector list set and map Performance Overview Peter Sikachev 1

What is a Container? Container is a class, a data structure, or an abstract

What is a Container? Container is a class, a data structure, or an abstract data type whose instances are collections of other objects Peter Sikachev 2

What is a Container? Container is a class, a data structure, or an abstract

What is a Container? Container is a class, a data structure, or an abstract data type whose instances are collections of other objects std: : vector<int> vec. Numbers; Peter Sikachev 3

Types of the Containers contiguous memory • vector • string • deque … Peter

Types of the Containers contiguous memory • vector • string • deque … Peter Sikachev associative • set, map • multiset, multimap • hash_set … 4 lists • list …

Iterator is an object that allows a programmer to traverse through all the elements

Iterator is an object that allows a programmer to traverse through all the elements of a collection, regardless of its specific implementation Peter Sikachev 5

Iterator vector elem for (int* i = &Number[0]; i < &Number + Number. size();

Iterator vector elem for (int* i = &Number[0]; i < &Number + Number. size(); i++) { *i = …; } Peter Sikachev 6

Iterator vector elem for (std: : vector<int>: : iterator i = Numbers. begin(); i

Iterator vector elem for (std: : vector<int>: : iterator i = Numbers. begin(); i < Numbers. end(); i++) { *i = …; } Peter Sikachev 7

Iterator list vector prev elem next elem prev next elem for (std: : list<int>:

Iterator list vector prev elem next elem prev next elem for (std: : list<int>: : iterator i = Numbers. begin(); i < Numbers. end(); i++) { *i = …; } Peter Sikachev 8

Iterator vector list set for (std: : set<int>: : iterator i = Numbers. begin();

Iterator vector list set for (std: : set<int>: : iterator i = Numbers. begin(); i < Numbers. end(); i++) { *i = …; } Peter Sikachev 9

Iterator Categories Iterators input output x=*i, ++ forward bidirectional -- random acess +n, -n,

Iterator Categories Iterators input output x=*i, ++ forward bidirectional -- random acess +n, -n, += n, -= n, <, >, <=, >= Peter Sikachev 10

Iterator Adapters • Insert • Reverse • Stream (for input and output) Peter Sikachev

Iterator Adapters • Insert • Reverse • Stream (for input and output) Peter Sikachev 11

Iterator Adapters • Insert • Reverse • Stream (for input and output) Peter Sikachev

Iterator Adapters • Insert • Reverse • Stream (for input and output) Peter Sikachev 12

Inserter values results Peter Sikachev 1 2 3 … … 13

Inserter values results Peter Sikachev 1 2 3 … … 13

Inserter values results 1 2 3 … … int Multiply. By. Ten(int x); vector

Inserter values results 1 2 3 … … int Multiply. By. Ten(int x); vector <int> values; … vector <int> results; transform(values. begin(), values. end(), results. end(), transmogrify); Peter Sikachev 14

Inserter values results 1 2 3 … … Runtime error! int Multiply. By. Ten(int

Inserter values results 1 2 3 … … Runtime error! int Multiply. By. Ten(int x); vector <int> values; … vector <int> results; transform(values. begin(), values. end(), results. end(), transmogrify); Peter Sikachev 15

Inserter values results 1 2 3 … … int Multiply. By. Ten(int x); vector

Inserter values results 1 2 3 … … int Multiply. By. Ten(int x); vector <int> values; … vector <int> results; transform(values. begin(), values. end(), back_inserter(results), transmogrify); Peter Sikachev 16 10 20 30

Inserter values results 1 2 3 30 20 10 … int Multiply. By. Ten(int

Inserter values results 1 2 3 30 20 10 … int Multiply. By. Ten(int x); vector <int> values; … list <int> results; transform(values. begin(), values. end(), front_inserter(results), transmogrify); Peter Sikachev 17 … … …

Inserter values results 1 2 3 10 20 30 … int Multiply. By. Ten(int

Inserter values results 1 2 3 10 20 30 … int Multiply. By. Ten(int x); vector <int> values; … list <int> results; transform(values. rbegin(), values. rend(), front_inserter(results), transmogrify); Peter Sikachev 18 … … …

Inserter values results 1 2 3 … … 10 20 30 … … int

Inserter values results 1 2 3 … … 10 20 30 … … int Multiply. By. Ten(int x); vector <int> values; … vector <int> results; transform(values. begin(), values. end(), inserter(results, results. begin() + results. size() / 2), transmogrify); Peter Sikachev 19

vector • “Growing Array” vec. Numbers. size(); elem vec. Numbers. capacity(); Costs • Find

vector • “Growing Array” vec. Numbers. size(); elem vec. Numbers. capacity(); Costs • Find – O(n) • Insert – O(n) • Random Access – O(1) • Erase – O(n) Peter Sikachev 20

vector • “Growing Array” vec. Numbers. size(); elem vec. Numbers. capacity(); std: : vector<int>

vector • “Growing Array” vec. Numbers. size(); elem vec. Numbers. capacity(); std: : vector<int> vec. Numbers; int k; … vec. Numbers. push_back(k); Peter Sikachev 21

vector • “Growing Array” vec. Numbers. size(); elem elem vec. Numbers. capacity(); std: :

vector • “Growing Array” vec. Numbers. size(); elem elem vec. Numbers. capacity(); std: : vector<int> vec. Numbers; int k; … vec. Numbers. push_back(k); Peter Sikachev 22

vector • “Growing Array” vec. Numbers. size(); elem elem vec. Numbers. capacity(); std: :

vector • “Growing Array” vec. Numbers. size(); elem elem vec. Numbers. capacity(); std: : vector<int> vec. Numbers; int k; … vec. Numbers. push_back(k); Peter Sikachev 23 elem

vector • “Growing Array” What next? vec. Numbers. size(); elem elem vec. Numbers. capacity();

vector • “Growing Array” What next? vec. Numbers. size(); elem elem vec. Numbers. capacity(); std: : vector<int> vec. Numbers; int k; … vec. Numbers. push_back(k); Peter Sikachev 24 elem

vector • Reallocation • New size may vary (typically 1. 5 -2 old size)

vector • Reallocation • New size may vary (typically 1. 5 -2 old size) • Problems? elem Peter Sikachev elem elem 25

Reallocation Problems • Copying (copy constructors) • Iterators invalidation • Unused capacity Peter Sikachev

Reallocation Problems • Copying (copy constructors) • Iterators invalidation • Unused capacity Peter Sikachev 26

Avoiding Reallocations std: : vector<int> vec. Numbers; for (int i = 0; i <

Avoiding Reallocations std: : vector<int> vec. Numbers; for (int i = 0; i < 1000; i++) { vec. Numbers. push_back(…); } Peter Sikachev 27

Avoiding Reallocations std: : vector<int> vec. Numbers; for (int i = 0; i <

Avoiding Reallocations std: : vector<int> vec. Numbers; for (int i = 0; i < 1000; i++) { vec. Numbers. push_back(i); } Up to 18 reallocations! Peter Sikachev 28

Avoiding Reallocations std: : vector<int> vec. Numbers; vec. Numbers. reserve(1000); for (int i =

Avoiding Reallocations std: : vector<int> vec. Numbers; vec. Numbers. reserve(1000); for (int i = 0; i < 1000; i++) { vec. Numbers. push_back(i); } Peter Sikachev 29

Unused Capacity • “The swap trick” { vector<int>(vec. Numbers. begin(), vec. Numbers. end()). swap(vec.

Unused Capacity • “The swap trick” { vector<int>(vec. Numbers. begin(), vec. Numbers. end()). swap(vec. Numbers); } Peter Sikachev 30

“Swap Trick” Step-by-Step { vector<int>(vec. Numbers. begin(), vec. Numbers. end()). swap(vec. Numbers); } •

“Swap Trick” Step-by-Step { vector<int>(vec. Numbers. begin(), vec. Numbers. end()). swap(vec. Numbers); } • Create temporary object Peter Sikachev 31

“Swap Trick” Step-by-Step { vector<int>(vec. Numbers. begin(), vec. Numbers. end()). swap(vec. Numbers); } •

“Swap Trick” Step-by-Step { vector<int>(vec. Numbers. begin(), vec. Numbers. end()). swap(vec. Numbers); } • Create temporary object • Initialize with the old vector values Peter Sikachev 32

“Swap Trick” Step-by-Step { vector<int>(vec. Numbers. begin(), vec. Numbers. end()). swap(vec. Numbers); } •

“Swap Trick” Step-by-Step { vector<int>(vec. Numbers. begin(), vec. Numbers. end()). swap(vec. Numbers); } • Create temporary object • Initialize with the old vector values • Swap pointers Peter Sikachev 33

“Swap Trick” Step-by-Step { vector<int>(vec. Numbers. begin(), vec. Numbers. end()). swap(vec. Numbers); } •

“Swap Trick” Step-by-Step { vector<int>(vec. Numbers. begin(), vec. Numbers. end()). swap(vec. Numbers); } • Create temporary object • Initialize with the old vector values • Swap pointers • Delete old vector Peter Sikachev 34

Removing the Elements • It should be straightforward, isn’t it? Peter Sikachev 35

Removing the Elements • It should be straightforward, isn’t it? Peter Sikachev 35

Removing the Elements • It should be straightforward, isn’t it? • No, it isn’t!

Removing the Elements • It should be straightforward, isn’t it? • No, it isn’t! Peter Sikachev 36

Removing the Elements vector <int> v; v. reserve(10); for (int i = 1; i

Removing the Elements vector <int> v; v. reserve(10); for (int i = 1; i <= 10; i++) { v. push_back(i); } v[3] = v[5] = v[9] = 99; remove(v. begin(), v. end(), 99); Peter Sikachev 37

Removing the Elements vector <int> v; v. reserve(10); for (int i = 1; i

Removing the Elements vector <int> v; v. reserve(10); for (int i = 1; i <= 10; i++) { v. push_back(i); } v[3] = v[5] = v[9] = 99; remove(v. begin(), v. end(), 99); v. begin() 1 2 Peter Sikachev v. end() 3 99 5 99 7 8 9 38 99

Removing the Elements vector <int> v; v. reserve(10); for (int i = 1; i

Removing the Elements vector <int> v; v. reserve(10); for (int i = 1; i <= 10; i++) { v. push_back(i); } v[3] = v[5] = v[9] = 99; vector <int>: : iterator new. End(remove(v. begin(), v. end(), 99)); v. begin() 1 2 v. end() 3 5 7 8 9 ? ? new. End Peter Sikachev 39 ?

Removing the Elements vector <int> v; v. reserve(10); for (int i = 1; i

Removing the Elements vector <int> v; v. reserve(10); for (int i = 1; i <= 10; i++) { v. push_back(i); } v[3] = v[5] = v[9] = 99; remove(v. begin(), v. end(), 99); v. begin() 1 2 Peter Sikachev v. end() 3 5 7 8 9 40 99

Removing the Elements vector <int> v; v. reserve(10); for (int i = 1; i

Removing the Elements vector <int> v; v. reserve(10); for (int i = 1; i <= 10; i++) { v. push_back(i); } v[3] = v[5] = v[9] = 99; v. erase(remove(v. begin(), v. end(), 99), v. end()); v. begin() 1 2 Peter Sikachev v. end() 3 5 7 8 9 41

list • just a list (hence the name!) prev next elem Costs • Find

list • just a list (hence the name!) prev next elem Costs • Find – O(n) • Insert – O(1) • Random Access – O(n) • Erase – O(1) Peter Sikachev 42

Checking the Emptiness if (c. size() == 0)… Peter Sikachev if (c. empty())… 43

Checking the Emptiness if (c. size() == 0)… Peter Sikachev if (c. empty())… 43

Checking the Emptiness if (c. size() == 0)… if (c. empty())… bad Peter Sikachev

Checking the Emptiness if (c. size() == 0)… if (c. empty())… bad Peter Sikachev good 44

Checking the Emptiness if (c. size() == 0)… if (c. empty())… bad – O(n)

Checking the Emptiness if (c. size() == 0)… if (c. empty())… bad – O(n) Peter Sikachev good – O(1) 45

Why? list <int> list 1; list <int> list 2; … list 1. splice( list

Why? list <int> list 1; list <int> list 2; … list 1. splice( list 1. end(), list 2, find(list 2. begin(), list 2. end(), 5), find(list 2. rbegin(), list 2. rend(), 10). base() ); /* move all nodes in list 2 from the first occurrence of 5 through the last occurrence of 10 to the end of list 1. “base()” converts a reverse_iterator into the “corresponding” iterator */ Peter Sikachev 46

Why? list <int> list 1; list <int> list 2; … list 1. splice( list

Why? list <int> list 1; list <int> list 2; … list 1. splice( list 1. end(), list 2, find(list 2. begin(), list 2. end(), 5), find(list 2. rbegin(), list 2. rend(), 10). base() ); size unknown! /* move all nodes in list 2 from the first occurrence of 5 through the last occurrence of 10 to the end of list 1. “base()” converts a reverse_iterator into the “corresponding” iterator */ Peter Sikachev 47

set and map • Organized as a binary search tree • node. value >

set and map • Organized as a binary search tree • node. value > node. left. Subtree. values • node. value < node. right. Subtree. values • both the left and right subtrees must also be binary search trees. Costs • Find – O(log(n)) • Insert – O(log(n)) • Random Access(? ) – O(log(n)) • Erase – O(log(n)) Peter Sikachev 48

Inserting a new element 1 Peter Sikachev 49

Inserting a new element 1 Peter Sikachev 49

Inserting a new element 1 2 Peter Sikachev 50

Inserting a new element 1 2 Peter Sikachev 50

Inserting a new element 1 2 3 Peter Sikachev 51

Inserting a new element 1 2 3 Peter Sikachev 51

Inserting a new element 1 2 3 4 Peter Sikachev 52

Inserting a new element 1 2 3 4 Peter Sikachev 52

Inserting a new element 1 2 3 4 5 Peter Sikachev 53

Inserting a new element 1 2 3 4 5 Peter Sikachev 53

Inserting a new element • Limiting subtree height is needed 1 2 3 4

Inserting a new element • Limiting subtree height is needed 1 2 3 4 Costs • Find – O(n) • Insert – O(n) • Random Access(? ) – O(n) • Erase – O(n) Peter Sikachev 5 6 54

Red-Black Tree 1. 2. 3. 4. 5. A node is either red or black.

Red-Black Tree 1. 2. 3. 4. 5. A node is either red or black. The root is black. All leaves are black. Both children of every red node are black. Every simple path from a given node to any of its descendant leaves contains the same number of black nodes. => height < 2 lg (n+1) Peter Sikachev 55

Red-Black Tree • New element added is red • Adding may violate ONLY rules

Red-Black Tree • New element added is red • Adding may violate ONLY rules 2 and 4 • Rule 2 => just repaint • Otherwise… Peter Sikachev 56

Red-Black Tree • Case 1 • Case 2 (after that apply 3) • Case

Red-Black Tree • Case 1 • Case 2 (after that apply 3) • Case 3 • The similar stuff for deleting Peter Sikachev 57

Consequences • No key modifications in place! Peter Sikachev 58

Consequences • No key modifications in place! Peter Sikachev 58