+ All Categories
Home > Documents > Containers - web.stanford.edu

Containers - web.stanford.edu

Date post: 11-Apr-2022
Category:
Upload: others
View: 2 times
Download: 0 times
Share this document with a friend
77
Containers How do we handle data in the STL? CS 106L, Fall ‘21
Transcript
Page 1: Containers - web.stanford.edu

Containers

How do we handle data in the STL?

CS 106L, Fall ‘21

Page 2: Containers - web.stanford.edu

• What makes a container?

• The Standard Template Library (STL)

• Containers (Stanford vs STL)

• Sequence

• Associative

• How do they actually work?

Today’s agenda

2

Page 3: Containers - web.stanford.edu

3

How do we store data in programs?

What do we need in order to do so?

Page 4: Containers - web.stanford.edu

4

Python and Stanford Library

lst = [] dictionary = {} hash_table = set() string = "adc"

Vector<int> lst;Map<int, int> dictionary;Set<int> hash_table;std::string str = "adc";

Classic examples of data structures:

Page 5: Containers - web.stanford.edu

• Let’s design one! We’ll be making a queue.

What makes a container?

5

Page 6: Containers - web.stanford.edu

• Let’s design one! We’ll be making a queue.

What makes a container?

6

Page 7: Containers - web.stanford.edu

• Let’s design one! We’ll be making a queue.

What makes a container?

7

Page 8: Containers - web.stanford.edu

• Let’s design one! We’ll be making a queue.

What makes a container?

8

Page 9: Containers - web.stanford.edu

• Let’s design one! We’ll be making a queue.

What makes a container?

9

Page 10: Containers - web.stanford.edu

• Let’s design one! We’ll be making a queue.

What makes a container?

10

Page 11: Containers - web.stanford.edu

• What if I have to make a queue for a movie ticket line?

• for a car wash?

• for a burst of API requests?

• We need a place to store common definitions for data structures.

This seems like a pretty common problem, right?

11

Page 12: Containers - web.stanford.edu

Standard Template Library

The core of modern C++!

12

Page 13: Containers - web.stanford.edu

What’s in the STL?

13

Containers Iterators

Functions Algorithms

Page 14: Containers - web.stanford.edu

What’s in the STL?

14

Containers Iterators

Functions Algorithms

Classes and Template Classes!

Page 15: Containers - web.stanford.edu

What’s in the STL?

15

Containers Iterators

Functions Algorithms

Classes and Template Classes!

Adaptors

Page 16: Containers - web.stanford.edu

• All containers can hold almost all elements.

Types of containers

16

Page 17: Containers - web.stanford.edu

• All containers can hold almost all elements.

Types of containers

17

Sequence Containers Associative Containers

Simple Adaptors Ordered Unordered

Page 18: Containers - web.stanford.edu

• All containers can hold almost all elements.

Types of containers

18

Sequence Containers Associative Containers

Simple Adaptors Ordered Unordered

<> vector

⇅ deque

↓ list

(adding + removing elements at end)

(adding + removing elements anywhere but end)

(adding + removing elements anywhere, but no random access)

() tuple (different data types, but immutable)

Page 19: Containers - web.stanford.edu

19

How do we use the STL? (and an aside on “::”)

#import <vector>

int main () {std::vector<int> vec;...

}

“::” -> Scope Resolution Operator

For heavily used items, we can use certain classes and datatypes in the std namespace, e.g. “using std::string;”

Just two steps!

1. Import the relevant STL feature

2. Use it with “std::<STL feature name here>”

using namespace std;

Page 20: Containers - web.stanford.edu

20

Live Demo!Let’s compare the Stanford’s Vector and STL’s vector:

(QT Creator Project)

Page 21: Containers - web.stanford.edu

21

Stanford “Vector” vs STL “vector”What you want to do Stanford Vector<int> std::vector<int>

Create a new, empty vector Vector<int> vec; std::vector<int> vec;

Create a vector with n copies of 0 Vector<int> vec(n); std::vector<int> vec(n);

Create a vector with n copies of a value k Vector<int> vec(n, k); std::vector<int> vec(n, k);

Add a value k to the end of a vector vec.add(k); vec.push_back(k);

Remove all elements of a vector vec.clear(); vec.clear();

Get the element at index i int k = vec[i]; int k = vec[i]; (does not bounds check)

Check size of vector vec.size(); vec.size();

Loop through vector by index i for (int i = 0; i < vec.size(); ++i) ...

for (std::size_t i = 0; i < vec.size(); ++i) ...

Replace the element at index i vec[i] = k; vec[i] = k; (does not bounds check)

Page 22: Containers - web.stanford.edu

22

Stanford “Vector” vs STL “vector”What you want to do Stanford Vector<int> std::vector<int>

Insert k at some index i vec.insert(i, k); vec.insert(vec.begin() + i, k);

Remove the element at index i vec.remove(i); vec.erase(vec.begin() + i);

Get the sublist in range [i, j) v.subList(i, j); std::vector<int> sum (vec.begin() + i, vec.begin() + j);

Create a vector that is two vectors appended to each other

Vector<int> v = v1 + v2; // pretty complicated ngl

Add j to the front of a vector vec.insert(0, i); vec.insert(vec.begin(), k);

We need iterators to understand these. Next Lecture!

Page 23: Containers - web.stanford.edu

• In general, how do we pick between containers?

Types of containers

23

Sequence Containers Associative Containers

Simple Adaptors Ordered Unordered

<> vector

⇅ deque

↓ list

(adding + removing elements at end)

(adding + removing elements anywhere but end)

(adding + removing elements anywhere, but no random access)

() tuple (different data types, but immutable)

Page 24: Containers - web.stanford.edu

24

Live Demo!Why can’t we just use a vector for everything?

vector_time_trials.cpp

Page 25: Containers - web.stanford.edu

• Because it’s super slow!

• This is what is happening to the elements inside the vector:

Why is there no std::vector::push_front()?

1 6 1 8 0 3

1 6 1 8 0 30

(in general, if something is extremely inefficient, C++ does not expose a method for it!)

25

Page 26: Containers - web.stanford.edu

• In general, how do we pick between containers?

Types of containers

26

Sequence Containers Associative Containers

Simple Adaptors Ordered Unordered

<> vector

⇅ deque

↓ list

(adding + removing elements at end)

(adding + removing elements anywhere but end)

(adding + removing elements anywhere, but no random access)

() tuple (different data types, but immutable)

Page 27: Containers - web.stanford.edu

27

Live Demo!Let’s compare speeds of several operations!

vector_list_deque.cpp

Page 28: Containers - web.stanford.edu

• Internally, a std::vector consists of a fixed-sized array

• It automatically resizes for you! (Arrays will be discussed in CS 106B after week 5)

How is a vector actually implemented?

28

Page 29: Containers - web.stanford.edu

• Internally, a std::vector consists of a fixed-sized array

• It automatically resizes for you! (Arrays will be discussed in CS 106B after week 5)

size = number of elements in a vector

capacity = amount of space saved for a vector

How is a vector actually implemented?

1 6 1 8 0 3size = 6

capacity = 8

29

Page 30: Containers - web.stanford.edu

• There’s no single, common implementation of a deque, but a common one looks like this:

How is a deque actually implemented?

30

Page 31: Containers - web.stanford.edu

• There’s no single, common implementation of a deque, but a common one looks like this:

How is a deque actually implemented?

NULL

3 1 4 1 5 9 2 6 5

31

Page 32: Containers - web.stanford.edu

• So how do we push_back(3)?

How is a deque actually implemented?

NULL

3 1 4 1 5 9 2 6 5

32

Page 33: Containers - web.stanford.edu

• So how do we push_back(3)?

How is a deque actually implemented?

NULL

3 1 4 1 5 9 2 6 5 3

33

Page 34: Containers - web.stanford.edu

• So how do we push_front(1)?

How is a deque actually implemented?

NULL

3 1 4 1 5 9 2 6 5 3

34

Page 35: Containers - web.stanford.edu

• So how do we push_front(1)?

How is a deque actually implemented?

NULL

1 3 1 4 1 5 9 2 6 5 3

35

Page 36: Containers - web.stanford.edu

• Now, how do we push_back(7)? Haven’t we run out of space in the last array?

How is a deque actually implemented?

NULL

1 3 1 4 1 5 9 2 6 5 3

36

Page 37: Containers - web.stanford.edu

• Now, how do we push_back(7)? Haven’t we run out of space in the last array?

How is a deque actually implemented?

1 3 1 4 1 5 9 2 6 5 3

37

Page 38: Containers - web.stanford.edu

• Now, how do we push_back(7)? Haven’t we run out of space in the last array?

How is a deque actually implemented?

1 3 1 4 1 5 9 2 6 5 3

7

38

Page 39: Containers - web.stanford.edu

• Lastly, how can we push_front(8) and then push_front(0)?

How is a deque actually implemented?

1 3 1 4 1 5 9 2 6 5 3

7

39

Page 40: Containers - web.stanford.edu

• Lastly, how can we push_front(8) and then push_front(0)?

How is a deque actually implemented?

1 3 1 4 1 5 9 2 6 5 3

7

40

Page 41: Containers - web.stanford.edu

• Lastly, how can we push_front(8) and then push_front(0)?

How is a deque actually implemented?

8 1 3 1 4 1 5 9 2 6 5 3

7

41

Page 42: Containers - web.stanford.edu

How is a deque actually implemented?

8 1 3 1 4 1 5 9 2 6 5 3

7

42

Page 43: Containers - web.stanford.edu

How is a deque actually implemented?

8 1 3 1 4 1 5 9 2 6 5 3

43

NULL NULL NULL NULL NULL NULLNULL NULL

7

Page 44: Containers - web.stanford.edu

How is a deque actually implemented?

8 1 3 1 4 1 5 9 2 6 5 3

44

NULL NULLNULL NULL

7

Page 45: Containers - web.stanford.edu

How is a deque actually implemented?

8 1 3 1 4 1 5 9 2 6 5 3

45

NULL NULLNULL

7

Page 46: Containers - web.stanford.edu

How is a deque actually implemented?

1 3 1 4 1 5 9 2 6 5 3

46

NULL NULLNULL

7

0

8

Page 47: Containers - web.stanford.edu

• Recap: a list provides fast insertion anywhere, but no random (indexed) access

How is a list actually implemented?

47

Page 48: Containers - web.stanford.edu

• Recap: a list provides fast insertion anywhere, but no random (indexed) access

How is a list actually implemented?

48

std::list<int> list{5, 6}; // {5, 6}list.push_front(3); // {3, 5, 6}list.pop_back(); // {3, 5}

Usually a doubly linked list. There’s also a forward_list that’s singly linked. Linked lists will be covered at the end of 106B, so don’t fret if this footnote is unfamiliar to you!

Page 49: Containers - web.stanford.edu

49

When to use which sequence container?What you want to do std::vector std::deque std::list

Insert/remove in the front Slow Fast Fast

Insert/remove in the back Super Fast Very Fast Fast

Indexed Access Super Fast Fast Impossible

Insert/remove in the middle Slow Fast Very Fast

Memory usage Low High High

Combining (splicing/joining) Slow Very Slow Fast

Stability* (iterators/concurrency) Bad Very Bad Good

Don’t worry if you don’t know what stability means! It’s a fairly advanced concept that you don’t need to understand in order to grasp the core of this slide.

These two are the most common!

Page 50: Containers - web.stanford.edu

std::vector: use for almost everything std::deque: use if you are frequently inserting/removing at front

std::list: use very rarely, and only if you need to split/join multiple lists

Summary of Sequence Containers

50

Page 51: Containers - web.stanford.edu

51

Container AdaptorsWhat is a container adaptor?

std::stack and std::queue

Page 52: Containers - web.stanford.edu

• All containers can hold almost all elements.

Types of containers

52

Sequence Containers Associative Containers

Simple Adaptors Ordered Unordered

(adding/removing elements from the front)

(adding elements from the front, removing from the back)

(adding elements with a priority, always removing the highest priority-element)

📚 stack

queue

priority_queue

<> vector

⇅ deque

↓ list

() tuple

Page 53: Containers - web.stanford.edu

53

What is a wrapper?• A wrapper on an object changes how external users can interact

with that object.

Page 54: Containers - web.stanford.edu

vault teller

54

What is a wrapper?• The vault’s owner has access to all possible ways to use the vault!

• Should a vault customer be able to do the same actions as the vault owner?

withdraw_money()

add_money()

remove_all_holdings()self_destruct()

change_lock()

Page 55: Containers - web.stanford.edu

vault teller

55

What is a wrapper?• Of course not! The vault teller limits your access to the vault.

• The teller is in charge of forwarding your requests to the actual vault.

withdraw_money()

add_money()

remove_all_holdings()

self_destruct()

change_lock()

vault user

Page 56: Containers - web.stanford.edu

vault teller

56

What is a wrapper?• Of course not! The vault teller limits your access to the vault.

• The teller is in charge of forwarding your requests to the actual vault.

withdraw_money()

add_money()

remove_all_holdings()

self_destruct()

change_lock()

user can’t change the vault lock!

vault user

Page 57: Containers - web.stanford.edu

57

Container adaptors are wrappers in C++!• Container adaptors provide a different interface for sequence containers.

• You can choose what the underlying container is!

• For instance, let’s choose a deque as our underlying container, and let’s implement a queue!

size()

pop_front()

push_back()at()

push_front()

std::deque

Page 58: Containers - web.stanford.edu

58

Container adaptors are wrappers in C++!• Container adaptors provide a different interface for sequence containers.

• You can choose what the underlying container is!

• For instance, let’s choose a deque as our underlying container, and let’s implement a queue!

std::queue

at()

push_front()

std::deque

size()

pop_front()

push_back()

Page 59: Containers - web.stanford.edu

59

Container adaptors are wrappers in C++!• Container adaptors provide a different interface for sequence containers.

• You can choose what the underlying container is!

• For instance, let’s choose a deque as our underlying container, and let’s implement a queue!

std::queue

at()

push_front()

std::deque

size()

pop_front()

push_back()

queue can’t call push_front()!

Page 60: Containers - web.stanford.edu

std::stack and std::queue

60

Page 61: Containers - web.stanford.edu

Concrete examples with std::queue

std::queue<int> stack_deque; // Container = std::deque

std::queue<int, std::list<int>> stack_list; // Container = std::list

std::queue<int, std::vector<int>> stack_vector; // Container = std::vector?

61

Page 62: Containers - web.stanford.edu

Concrete examples with std::queue

std::queue<int> stack_deque; // Container = std::deque

std::queue<int, std::list<int>> stack_list; // Container = std::list

std::queue<int, std::vector<int>> stack_vector; // Container = std::vector

removing from the front of a vector is slow!

62

Page 63: Containers - web.stanford.edu

Some member functions of std::queue

63

Page 64: Containers - web.stanford.edu

• All containers can hold almost all elements.

Types of containers

64

Sequence Containers Associative Containers

Simple Adaptors Ordered

(adding/removing elements from the front)

(adding elements from the front, removing from the back)

(adding elements with a priority, always removing the highest priority-element)

📚 stack

queue

priority_queue

<> vector

⇅ deque

↓ list

() tuple

Unordered

Page 65: Containers - web.stanford.edu

65

Associative Containersstd::set functions

std::map functions and auto-insertion type requirements

Page 66: Containers - web.stanford.edu

• All containers can hold almost all elements.

Types of containers

66

Sequence Containers Associative Containers

Simple Adaptors Ordered Unordered

{} set

{:} map

(unique elements)

(key value pairs)

📚 stack

queue

priority_queue

<> vector

⇅ deque

↓ list

() tuple

Page 67: Containers - web.stanford.edu

67

Live Demo!Let’s compare the Stanford’s Map/Set and STL’s map/set:

(QT Creator Project)

Page 68: Containers - web.stanford.edu

68

Stanford “Set” vs STL “set”What you want to do Stanford Set<int> std::set<int>

Create an empty set Set<int> s; std::set<int> s;

Add a value k to the set s.add(k); s.insert(k);

Remove value k from the set s.remove(k); s.erase(k);

Check if a value k is in the set if (s.contains(k)) ... if (s.count(k)) ...

Check if vector is empty if (vec.isEmpty()) ... if (vec.empty()) ...

Page 69: Containers - web.stanford.edu

69

Stanford “Map” vs STL “map”What you want to do Stanford Map<int, char> std::map<int, char>

Create an empty map Map<int, char> m; std::map<int, char> m;

Add key k with value v into the mapm.put(k, v);m[k] = v;

m.insert({k, v});m[k] = v;

Remove key k from the map m.remove(k); m.erase(k);

Check if key k is in the map if (m.containsKey(k)) ... if (m.count(k)) ...

Check if the map is empty if (m.isEmpty()) ... if (m.empty()) ...

Retrieve or overwrite value associated with key k (error if key isn’t in map)

Impossible (but does auto-insert)

char c = m.at(k);m.at(k) = v;

Retrieve or overwrite value associated with key k (auto-insert if key isn’t in map)

char c = m[k];m[k] = v;

char c = m[k];m[k] = v;

Page 70: Containers - web.stanford.edu

Every std::map<K, V> is actually backed by:

std::pair<const K, V>

• Why do pairs make sense here?

• Why not just tuples?

• Why is it const K instead of just K?

STL maps actually store pairs!

70

hint: std::pair’s are just two-element tuples!

Page 71: Containers - web.stanford.edu

• Exactly the same as CS106B!

• Because maps are implemented with std::pair, you can use structured binding on them!

Iterating through maps and sets

71

std::set<...> s;std::map<..., ...> m;

for (const auto& element : s) { // do stuff with element

}

for (const auto& [key, value] : m) { // do stuff with key and value

}

Page 72: Containers - web.stanford.edu

• By default, the type (for sets) or key’s type (for maps) must have a comparison operator (<) defined.

Both Stanford and STL sets+maps require comparison operator!

72

std::set<int> set1; // A OK! ints are comparable with <std::set<std::ifstream> set2; // not ok. how do we compare ifstreams with < ?

std::map<int, int> map1; // A OK! ints are comparable with <std::set<std::ifstream, int> map2; // not ok. how do we compare ifstreams with < ?

Page 73: Containers - web.stanford.edu

• All containers can hold almost all elements.

Types of containers

73

Sequence Containers Associative Containers

Simple Adaptors Ordered Unordered

📚 stack

queue

priority_queue

{} set

{:} map

{} unordered_set

{:} unordered_map

(similar to ordered, except faster)

<> vector

⇅ deque

↓ list

() tuple

Page 74: Containers - web.stanford.edu

• Each STL set/map comes with an unordered sibling. They’re almost the same, except:

• Instead of a comparison operator, the set/map type must have a hash function defined for it.

• Simple types, like int, char, bool, double, and even std::string are already supported!

• Any containers/collections need you to provide a hash function to use them.

• unordered_map/unordered_set are generally faster than map/set.

unordered_map and unordered_set

74

Page 75: Containers - web.stanford.edu

• What do they all have in common?

• You can copy all of them!

• You can check if two have the same elements in the same order.

• You can get their size.

• You can use iterators to access them (next lecture).

That’s a lot! Any broad tips for choosing one?

75

Page 76: Containers - web.stanford.edu

• How are they different?

• Most containers can hold any data type.

• Unordered associative containers (sets and maps) are tricky to get working if the element or key is another collection.

That’s a lot! Any broad tips for choosing one?

76

Page 77: Containers - web.stanford.edu

• Sequence Containers

• std::vector - use for almost everything

• std::deque - use when you need fast insertion to front AND back

• Container Adaptors

• std::stack and std::queue

• Associative Containers

• std::map and std::set

• if using simple data types/you’re familiar with hash functions, use std::unordered_map and std::unordered_set

Recap of STL Containers!

77


Recommended