Skip to content

Commit 7f18b9e

Browse files
committed
cpp: algorithm: split heap, improve style
1 parent 15cbc6e commit 7f18b9e

3 files changed

Lines changed: 170 additions & 214 deletions

File tree

cpp/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
1. [atomic<bool>](atomic_bool.cpp.off)
8383
1. [mutex](mutex.cpp)
8484
1. [algorithm](algorithm.cpp)
85+
1. [heap](heap.cpp)
8586
1. [functional](functional.cpp)
8687
1. [iterator](iterator.cpp)
8788
1. [limits](limits.cpp)

cpp/algorithm.cpp

Lines changed: 78 additions & 214 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
/*
2-
# algorithm
3-
*/
4-
51
#include "common.hpp"
62

73
int main() {
@@ -25,22 +21,21 @@ int main() {
2521
assert((v == std::vector<int>{1, 0, 2}));
2622
}
2723

28-
/*
29-
# swap
30-
31-
Does things equivalent to:
32-
33-
template <class T> void swap (T& a, T& b)
34-
{
35-
T c(a); a=b; b=c;
36-
}
37-
38-
However stdlib can specialize it to do operations more efficiently.
39-
40-
Some stdlib classes implement swap as a method.
41-
42-
Particularly important because of the copy and swap idiom.
43-
*/
24+
/* # swap
25+
*
26+
* Does things equivalent to:
27+
*
28+
* template <class T> void swap (T& a, T& b)
29+
* {
30+
* T c(a); a=b; b=c;
31+
* }
32+
*
33+
* However stdlib can specialize it to do operations more efficiently.
34+
*
35+
* Some stdlib classes implement swap as a method.
36+
*
37+
* Particularly important because of the copy and swap idiom.
38+
*/
4439

4540
// # randomize
4641
{
@@ -56,24 +51,22 @@ int main() {
5651
assert(v2 == std::vector<int>({3, 2, 0, 1, 3}));
5752
}
5853

59-
/*
60-
# equal
61-
62-
Compares ranges of two containers.
63-
*/
54+
/* # equal
55+
*
56+
* Compares ranges of two containers.
57+
*/
6458
{
6559
std::vector<int> v {0, 1, 2 };
6660
std::vector<int> v2{ 1, 2, 3};
6761
assert(std::equal(v.begin() + 1, v.end(), v2.begin()));
6862
}
6963

70-
/*
71-
# accumulate
72-
73-
Sum over range with operator+
74-
75-
Also has functional versions http://www.cplusplus.com/reference/numeric/accumulate/
76-
*/
64+
/* # accumulate
65+
*
66+
* Sum over range with operator+
67+
*
68+
* Also has functional versions http://www.cplusplus.com/reference/numeric/accumulate/
69+
*/
7770
{
7871
{
7972
std::vector<int> v{2, 0, 1};
@@ -89,11 +82,10 @@ int main() {
8982
}
9083
}
9184

92-
/*
93-
# find
94-
95-
Return iterator to first found element.
96-
*/
85+
/* # find
86+
*
87+
* Return iterator to first found element.
88+
*/
9789
{
9890
std::vector<int> v{2,0,1};
9991
unsigned int pos;
@@ -111,29 +103,27 @@ int main() {
111103
assert(pos == v.size());
112104
}
113105

114-
/*
115-
# find_if
116-
117-
Like find, but using an arbitrary condition on each element instead of equality.
118-
119-
Consider usage with C++11 lambdas and functional.
120-
*/
106+
/* # find_if
107+
*
108+
* Like find, but using an arbitrary condition on each element instead of equality.
109+
*
110+
* Consider usage with C++11 lambdas and functional.
111+
*/
121112
{
122113
std::vector<int> v{2, 0, 1};
123114
assert(std::find_if (v.begin(), v.end(), odd) == --v.end());
124115
}
125116

126-
/*
127-
# binary_search
128-
129-
Container must be already sorted.
130-
131-
Log complexity.
132-
133-
Only states if the element is present or not, but does not get its position.
134-
135-
If you want to get the position of those items, use `equal_range`, `lower_bound` or `upper_bound`.
136-
*/
117+
/* # binary_search
118+
*
119+
* Container must be already sorted.
120+
*
121+
* Log complexity.
122+
*
123+
* Only states if the element is present or not, but does not get its position.
124+
*
125+
* If you want to get the position of those items, use `equal_range`, `lower_bound` or `upper_bound`.
126+
*/
137127
{
138128

139129
std::vector<int> v{0, 1, 2};
@@ -142,37 +132,34 @@ int main() {
142132
assert(std::binary_search(v.begin(), v.end() - 1, 2) == false);
143133
}
144134

145-
/*
146-
# lower_bound
147-
148-
Finds first element in container which is not less than val.
149-
*/
135+
/* # lower_bound
136+
*
137+
* Finds first element in container which is not less than val.
138+
*/
150139
{
151140
std::vector<int> v{0, 2, 3};
152141
auto it = std::lower_bound(v.begin(), v.end(), 1);
153142
assert(it - v.begin() == 1);
154143
}
155144

156-
/*
157-
# upper_bound
158-
159-
Finds first element in container is greater than val.
160-
*/
145+
/* # upper_bound
146+
*
147+
* Finds first element in container is greater than val.
148+
*/
161149
{
162150
std::vector<int> v{0, 1, 2};
163151
auto it = std::upper_bound(v.begin(), v.end(), 1);
164152
assert(it - v.begin() == 2);
165153
}
166154

167-
/*
168-
# equal_range
169-
170-
Finds first and last location of a value iniside a ranged container.
171-
172-
Return values are the same as lower_bound and upper_bound.
173-
174-
log complexity.
175-
*/
155+
/* # equal_range
156+
*
157+
* Finds first and last location of a value iniside a ranged container.
158+
*
159+
* Return values are the same as lower_bound and upper_bound.
160+
*
161+
* log complexity.
162+
*/
176163
{
177164
std::vector<int> v{0, 1, 1, 2};
178165
std::vector<int>::iterator begin, end;
@@ -197,20 +184,19 @@ int main() {
197184
assert(*std::min_element(v.begin(), v.end()) == 0);
198185
}
199186

200-
/*
201-
# advance
202-
203-
Advance iterator by given number.
204-
205-
If random access, simply adds + N.
206-
207-
Else, calls `++` N times.
208-
209-
Advantage over `+`: only random access containers support `+`,
210-
but this works for any container, allowing one to write more general code.
211-
212-
Beware however that this operation will be slow for non random access containers.
213-
*/
187+
/* # advance
188+
*
189+
* Advance iterator by given number.
190+
*
191+
* If random access, simply adds + N.
192+
*
193+
* Else, calls `++` N times.
194+
*
195+
* Advantage over `+`: only random access containers support `+`,
196+
* but this works for any container, allowing one to write more general code.
197+
*
198+
* Beware however that this operation will be slow for non random access containers.
199+
*/
214200
{
215201
std::vector<int> v{0, 1, 2};
216202
auto it = v.begin();
@@ -219,11 +205,10 @@ int main() {
219205
}
220206

221207
#if __cplusplus >= 201103L
222-
/*
223-
# next
224-
225-
Same as advance, but returns a new iterator instead of modifying the old one.
226-
*/
208+
/* # next
209+
*
210+
* Same as advance, but returns a new iterator instead of modifying the old one.
211+
*/
227212
{
228213
std::vector<int> v{0, 1, 2};
229214
auto it(v.begin());
@@ -232,125 +217,4 @@ int main() {
232217
assert(*itNext == 2);
233218
}
234219
#endif
235-
236-
/*
237-
# priority queue
238-
239-
Offers `O(1)` access to the smalles element.
240-
241-
Other operatoins vary between `O(n)` and `O(1).
242-
243-
Most common implementaions are via:
244-
245-
- binary heap
246-
- fibonacci heap
247-
248-
Boost offers explicit heap types: fibonacci, binary and others.
249-
250-
But no guarantees are made.
251-
252-
As of C++11, does not support the increase key operation.
253-
254-
A binary heap without increase key can be implemented via the heap function family under algorithm.
255-
*/
256-
257-
/*
258-
# heap
259-
260-
Binary heap implementation.
261-
262-
<http://en.wikipedia.org/wiki/Heap_%28data_structure%29>
263-
264-
In short:
265-
266-
- getting largest element is O(1)
267-
- removing the largest element is O(lg) for all implementation
268-
- other operations (insertion) may be O(1) or O(lg) depending on the implementation.
269-
270-
this makes for a good priority queue.
271-
Exact heap type is not guaranteed. As of 2013, it seems that most implementations use binary heaps.
272-
273-
For specific heaps such as Fibonacci, consider [Boost](http://www.boost.org/doc/libs/1_49_0/doc/html/heap.html).
274-
275-
<http://stackoverflow.com/questions/14118367/stl-for-fibonacci-heap>
276-
277-
There is no concrete heap data structure in C++:
278-
only heap operations over random access data structures.
279-
This is why this is under algoritms and is not a data structure of its own.
280-
281-
There is however a `priority_queue` stdlib container.
282-
283-
Why random access structure is needed: <https://github.com/cirosantilli/comp-sci/blob/1.0/src/heap.md#array-implementation>
284-
*/
285-
{
286-
int myints[]{10, 20, 30, 5, 15};
287-
std::vector<int> v(myints, myints + 5);
288-
289-
/*
290-
# make_heap
291-
292-
Make random access data structure into a heap.
293-
294-
This changes the element order so that the range has heap properties
295-
296-
Worst case time: $O(n)$.
297-
*/
298-
std::make_heap(v.begin(), v.end());
299-
assert(v.front() == 30);
300-
301-
/*
302-
# pop_heap
303-
304-
Remove the largest element from the heap.
305-
306-
That element is moved to the end of the data structure, but since the
307-
heap should have its length reduced by one, that element will then be out of the heap.
308-
309-
Assumes that the input range is already a heap (made with `make_heap` for example).
310-
*/
311-
std::pop_heap(v.begin(), v.end());
312-
313-
//the element still exists on the data structure
314-
assert(v.back() == 30);
315-
316-
//the second largest element hat become the largets
317-
assert(v.front() == 20);
318-
319-
//remove the element from the data structure definitively
320-
v.pop_back();
321-
322-
/*
323-
# push_heap
324-
325-
Insert element into a heap.
326-
327-
Assumes that:
328-
329-
- the range 0 - (end - 1) was already a heap
330-
- the new element to be inserted into that heap is at end.
331-
*/
332-
333-
//add the new element to the data structure
334-
v.push_back(99);
335-
336-
//reorganize the data so that the last element will be placed in the heap
337-
std::push_heap(v.begin(), v.end());
338-
339-
assert(v.front() == 99);
340-
341-
/*
342-
# sort_heap
343-
344-
Assumes that the input range is a heap, and sorts it in increasing order.
345-
346-
The assumption that we have a heap allows for $O(ln)$ sorting,
347-
much faster than the optimal bound $O(n log n)$.
348-
349-
This is exactly what the heapsort alrotithm does: make_heap and then sort_heap.
350-
*/
351-
352-
std::sort_heap(v.begin(), v.end());
353-
//assert(v)
354-
//v == 5 10 15 20 99
355-
}
356220
}

0 commit comments

Comments
 (0)