Skip to content
This repository was archived by the owner on Feb 27, 2026. It is now read-only.

Commit 9149bdf

Browse files
Term Entry: load-factor in unordered_map in cpp (#7264)
* Term Entry: load-factor in unordered_map in cpp * content fixes * Update load-factor.md * Update load-factor.md * Update load-factor.md ---------
1 parent 33b7cb2 commit 9149bdf

1 file changed

Lines changed: 330 additions & 0 deletions

File tree

Lines changed: 330 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,330 @@
1+
---
2+
Title: 'load_factor()'
3+
Description: 'Returns the current load factor of the unordered map hash table, which is the ratio of element count to bucket count.'
4+
Subjects:
5+
- 'Computer Science'
6+
- 'Web Development'
7+
Tags:
8+
- 'Data Structures'
9+
- 'Hash Maps'
10+
- 'Map'
11+
- 'STL'
12+
CatalogContent:
13+
- 'learn-c-plus-plus'
14+
- 'paths/computer-science'
15+
---
16+
17+
The **`load_factor()`** is a member function of the `std::unordered_map` container that returns the current load factor of the hash table. `The load factor is the ratio between the number of elements in the container (its size) and the number of buckets (bucket count)`.
18+
19+
The **load factor** is a crucial measure of a hash table's efficiency. It is calculated by dividing the number of stored elements by the number of available buckets.
20+
21+
```plaintext
22+
Load Factor = Number of Elements / Number of Buckets
23+
```
24+
25+
Essentially, the load factor indicates how full the hash table is. A low load factor signifies ample space, leading to faster operations and fewer "collisions" (when multiple items map to the same spot). A high load factor indicates the table is crowded, which can degrade performance because extra work is required to find and store items.
26+
27+
## Syntax
28+
29+
```pseudo
30+
float load_factor() const;
31+
```
32+
33+
**Parameters:**
34+
35+
- None
36+
37+
**Return value:**
38+
39+
- Returns a floating-point value representing the container's current load factor (the ratio of size to bucket count).
40+
41+
## Example 1: Basic Usage of `load_factor()`
42+
43+
This example demonstrates the basic usage of `load_factor()` and how it changes as elements are added:
44+
45+
```cpp
46+
#include <iostream>
47+
#include <unordered_map>
48+
#include <string>
49+
#include <iomanip>
50+
51+
int main() {
52+
// Create an empty unordered_map
53+
std::unordered_map<int, std::string> inventory;
54+
55+
// Display initial stats
56+
std::cout << std::fixed << std::setprecision(3);
57+
std::cout << "Initial state:" << std::endl;
58+
std::cout << "Size: " << inventory.size() << std::endl;
59+
std::cout << "Bucket count: " << inventory.bucket_count() << std::endl;
60+
std::cout << "Load factor: " << inventory.load_factor() << std::endl;
61+
std::cout << "Max load factor: " << inventory.max_load_factor() << std::endl;
62+
std::cout << std::endl;
63+
64+
// Insert elements and observe load factor changes
65+
std::cout << "Inserting inventory items:" << std::endl;
66+
for (int i = 1; i <= 8; ++i) {
67+
inventory[i] = "Item " + std::to_string(i);
68+
std::cout << "After inserting " << i << " items:" << std::endl;
69+
std::cout << " Size: " << inventory.size() << std::endl;
70+
std::cout << " Bucket count: " << inventory.bucket_count() << std::endl;
71+
std::cout << " Load factor: " << inventory.load_factor() << std::endl;
72+
std::cout << std::endl;
73+
}
74+
75+
return 0;
76+
}
77+
```
78+
79+
The output might look something like:
80+
81+
```shell
82+
Initial state:
83+
Size: 0
84+
Bucket count: 1
85+
Load factor: 0.000
86+
Max load factor: 1.000
87+
88+
Inserting inventory items:
89+
After inserting 1 items:
90+
Size: 1
91+
Bucket count: 13
92+
Load factor: 0.077
93+
94+
After inserting 2 items:
95+
Size: 2
96+
Bucket count: 13
97+
Load factor: 0.154
98+
99+
After inserting 3 items:
100+
Size: 3
101+
Bucket count: 13
102+
Load factor: 0.231
103+
104+
After inserting 4 items:
105+
Size: 4
106+
Bucket count: 13
107+
Load factor: 0.308
108+
109+
After inserting 5 items:
110+
Size: 5
111+
Bucket count: 13
112+
Load factor: 0.385
113+
114+
After inserting 6 items:
115+
Size: 6
116+
Bucket count: 13
117+
Load factor: 0.462
118+
119+
After inserting 7 items:
120+
Size: 7
121+
Bucket count: 13
122+
Load factor: 0.538
123+
124+
After inserting 8 items:
125+
Size: 8
126+
Bucket count: 13
127+
Load factor: 0.615
128+
```
129+
130+
The above code shows how the load factor changes as elements are inserted into the container. Initially, the load factor is 0 (empty container). As elements are added, the load factor increases. When it approaches the max load factor, the container automatically rehashes (increases the bucket count), which reduces the load factor.
131+
132+
## Example 2: Performance Analysis with `load_factor()`
133+
134+
This example demonstrates how to use `load_factor()` to analyze and optimize hash table performance:
135+
136+
```cpp
137+
#include <iostream>
138+
#include <unordered_map>
139+
#include <string>
140+
#include <chrono>
141+
#include <vector>
142+
#include <iomanip>
143+
144+
// Function to measure average lookup time
145+
double measureLookupTime(const std::unordered_map<int, std::string>& map, int iterations) {
146+
auto start = std::chrono::high_resolution_clock::now();
147+
148+
// Perform lookups
149+
for (int i = 0; i < iterations; ++i) {
150+
for (int key = 1; key <= 100; ++key) {
151+
map.find(key);
152+
}
153+
}
154+
155+
auto end = std::chrono::high_resolution_clock::now();
156+
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
157+
return static_cast<double>(duration.count()) / (iterations * 100);
158+
}
159+
160+
int main() {
161+
std::unordered_map<int, std::string> cache;
162+
163+
std::cout << std::fixed << std::setprecision(4);
164+
std::cout << "Performance Analysis with Load Factor:" << std::endl;
165+
std::cout << "| Elements | Buckets | Load Factor | Avg Lookup (μs) |" << std::endl;
166+
std::cout << "|----------|---------|-------------|-----------------|" << std::endl;
167+
168+
// Insert elements in batches and measure performance
169+
for (int batch = 0; batch < 10; ++batch) {
170+
// Add 50 elements per batch
171+
for (int i = 1; i <= 50; ++i) {
172+
int key = batch * 50 + i;
173+
cache[key] = "CachedData" + std::to_string(key);
174+
}
175+
176+
// Measure performance
177+
double avgTime = measureLookupTime(cache, 1000);
178+
179+
std::cout << "| " << std::setw(8) << cache.size()
180+
<< " | " << std::setw(7) << cache.bucket_count()
181+
<< " | " << std::setw(11) << cache.load_factor()
182+
<< " | " << std::setw(15) << avgTime << " |" << std::endl;
183+
}
184+
185+
return 0;
186+
}
187+
```
188+
189+
The output will show the relationship between load factor and lookup performance:
190+
191+
```shell
192+
Performance Analysis with Load Factor:
193+
| Elements | Buckets | Load Factor | Avg Lookup (μs) |
194+
|----------|---------|-------------|-----------------|
195+
| 50 | 59 | 0.8475 | 0.1296 |
196+
| 100 | 127 | 0.7874 | 0.0939 |
197+
| 150 | 257 | 0.5837 | 0.0935 |
198+
| 200 | 257 | 0.7782 | 0.0948 |
199+
| 250 | 257 | 0.9728 | 0.0983 |
200+
| 300 | 541 | 0.5545 | 0.0930 |
201+
| 350 | 541 | 0.6470 | 0.0930 |
202+
| 400 | 541 | 0.7394 | 0.0755 |
203+
| 450 | 541 | 0.8318 | 0.0728 |
204+
| 500 | 541 | 0.9242 | 0.0944 |
205+
```
206+
207+
This example demonstrates how monitoring the load factor helps understand performance characteristics. It shows the correlation between load factor and lookup time, revealing that performance generally improves when the load factor decreases due to rehashing.
208+
209+
## Codebyte Example: Smart Cache Management
210+
211+
This interactive example shows how to use `load_factor()` for intelligent cache management and performance optimization:
212+
213+
```codebyte/cpp
214+
#include <iostream>
215+
#include <unordered_map>
216+
#include <string>
217+
#include <vector>
218+
#include <iomanip>
219+
220+
class SmartCache {
221+
private:
222+
std::unordered_map<int, std::string> cache;
223+
static constexpr double OPTIMAL_LOAD_FACTOR = 0.6;
224+
225+
public:
226+
void addItem(int key, const std::string& value) {
227+
cache[key] = value;
228+
229+
// Check if we need to optimize
230+
if (cache.load_factor() > OPTIMAL_LOAD_FACTOR * 1.5) {
231+
optimize();
232+
}
233+
}
234+
235+
void optimize() {
236+
std::cout << "Optimizing cache..." << std::endl;
237+
std::cout << "Before optimization:" << std::endl;
238+
displayStats();
239+
240+
// Set optimal max load factor
241+
cache.max_load_factor(OPTIMAL_LOAD_FACTOR);
242+
243+
std::cout << "After optimization:" << std::endl;
244+
displayStats();
245+
std::cout << std::endl;
246+
}
247+
248+
void displayStats() {
249+
std::cout << std::fixed << std::setprecision(3);
250+
std::cout << " Size: " << cache.size() << std::endl;
251+
std::cout << " Bucket count: " << cache.bucket_count() << std::endl;
252+
std::cout << " Load factor: " << cache.load_factor() << std::endl;
253+
std::cout << " Max load factor: " << cache.max_load_factor() << std::endl;
254+
255+
// Calculate distribution statistics
256+
size_t emptyBuckets = 0;
257+
size_t maxBucketSize = 0;
258+
259+
for (size_t i = 0; i < cache.bucket_count(); ++i) {
260+
size_t bucketSize = cache.bucket_size(i);
261+
if (bucketSize == 0) emptyBuckets++;
262+
if (bucketSize > maxBucketSize) maxBucketSize = bucketSize;
263+
}
264+
265+
double emptyPercent = (static_cast<double>(emptyBuckets) / cache.bucket_count()) * 100;
266+
std::cout << " Empty buckets: " << emptyBuckets << " (" << emptyPercent << "%)" << std::endl;
267+
std::cout << " Max bucket size: " << maxBucketSize << std::endl;
268+
}
269+
270+
std::string get(int key) {
271+
auto it = cache.find(key);
272+
return (it != cache.end()) ? it->second : "Not found";
273+
}
274+
};
275+
276+
int main() {
277+
SmartCache smartCache;
278+
279+
std::cout << "Smart Cache Management Demo" << std::endl;
280+
std::cout << "============================" << std::endl;
281+
282+
// Initial state
283+
std::cout << "Initial cache state:" << std::endl;
284+
smartCache.displayStats();
285+
std::cout << std::endl;
286+
287+
// Add items to trigger optimization
288+
std::cout << "Adding 100 cache entries..." << std::endl;
289+
for (int i = 1; i <= 100; ++i) {
290+
smartCache.addItem(i, "CacheEntry_" + std::to_string(i));
291+
292+
// Show progress at certain intervals
293+
if (i % 25 == 0) {
294+
std::cout << "Progress: " << i << " items added" << std::endl;
295+
smartCache.displayStats();
296+
std::cout << std::endl;
297+
}
298+
}
299+
300+
// Test retrieval
301+
std::cout << "Testing cache retrieval:" << std::endl;
302+
std::cout << "Key 50: " << smartCache.get(50) << std::endl;
303+
std::cout << "Key 999: " << smartCache.get(999) << std::endl;
304+
305+
return 0;
306+
}
307+
```
308+
309+
This example demonstrates a practical scenario where monitoring and managing the load factor is crucial for maintaining optimal performance. The smart cache automatically adjusts its configuration based on the load factor to ensure efficient operations.
310+
311+
## Frequently Asked Questions
312+
313+
### 1. What is an ideal load factor for `unordered_map`?
314+
315+
There's no universally ideal load factor as it depends on the hash function quality, key distribution, and performance requirements. However, most implementations perform well with load factors between 0.5 and 0.75. Values around 0.6-0.7 often provide a good balance between memory usage and performance.
316+
317+
### 2. What is the load factor in C++?
318+
319+
The load factor in C++ (specifically for hash-based containers like `unordered_map` and `unordered_set`) measures how full the hash table is. It’s calculated as:
320+
321+
```tex
322+
load_factor = number_of_elements / number_of_buckets
323+
```
324+
325+
### 3. Is unordered_map faster than map in C++?
326+
327+
Yes, in most cases:
328+
329+
- `unordered_map` is implemented using hash tables, so average time complexity for insert, delete, and find is O(1).
330+
- `map` is implemented using a balanced binary search tree (Red-Black tree), so those operations take O(log n) time.

0 commit comments

Comments
 (0)