Skip to content

Commit 98a67f1

Browse files
committed
corrections to chapter 18 from email
1 parent a0a77f9 commit 98a67f1

File tree

3 files changed

+47
-13
lines changed

3 files changed

+47
-13
lines changed

18_binary_insertion_sort.md

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ which would indicate what mood I'm in.
1010
This is a very great song by [Franz Schubert][schubert] but it also
1111
perfectly reflects what will go on with the course in how I feel.
1212
The song is called ["The Organ Grinder"][winter-journey] (Der Leiermann).
13-
The singer is [Dietrich fischer-dieskau][dietrich] maybe the greatest
13+
The singer is [Dietrich Fischer-Dieskau][dietrich] maybe the greatest
1414
leader, or art song singer of the last 50, 60, or 70 years.
1515
He started singing in the late forties.
1616
Let us spend a couple of minutes and listen to it... ([Video here][organ-grinder])
@@ -263,25 +263,23 @@ That's the invariant on which we rely.
263263

264264
### Rotate for bidirectional iterators
265265

266-
Once we find where it goes, how do we make room for it?
266+
Once we find where it goes (the element to insert), how do we make room for it?
267267
We "rotate" to the right by one.
268-
If it was a bidirectional iterator there is a beautiful algorithm.
269-
Copy is the wrong thing, because it will overwrite everything
270-
with the same value.
271-
What we want is copying from the back.
268+
If it is a bidirectional iterator there is a beautiful algorithm, copying from the back.
272269
The algorithm is called: [`std::copy_backward`][cpp-copy-back].
273270

274271
template <typename I>
275272
// I is BidirectionalIterator
276273
void rotate_right_by_one(I first, I last, std::bidirectional_iterator_tag) {
277274
typedef typename std::iterator_traits<I>::value_type T;
278-
T butlast = last;
275+
I butlast = last;
279276
--butlast;
280277
T x = *butlast;
281278
std::copy_backward(first, butlast, last);
282279
*first = x;
283280
}
284281

282+
Note that forward copy is the wrong thing, because it will overwrite everything with the same value (namely the first value).
285283

286284
### Rotate for forward iterators
287285

@@ -349,16 +347,16 @@ It might not be the fastest, but it is going to be much more elegant.
349347
void rotate_right_by_one(I first, I last, std::forward_iterator_tag) {
350348
if (first == last) return;
351349
I current = first;
352-
while (++current != last) std::swap(first, current);
350+
while (++current != last) std::swap(*first, *current);
353351
}
354352

355353
Let's write a dispatch for both versions,
356354
it will compile to no code[^concepts-in-standard-soon].
357355

358356
template <typename I>
359357
inline
360-
void rotate_right_by_one(I first, I butlast, I last) {
361-
rotate_right_by_one(first, butlast, last, typename std::iterator_traits<I>::iterator_category());
358+
void rotate_right_by_one(I first, I last) {
359+
rotate_right_by_one(first, last, typename std::iterator_traits<I>::iterator_category());
362360
}
363361

364362

code/binary_insertion_sort.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ template <typename I>
1111
void rotate_right_by_one(I first, I last, std::forward_iterator_tag) {
1212
if (first == last) return;
1313
I current = first;
14-
while (++current != last) std::swap(first, current);
14+
while (++current != last) std::swap(*first, *current);
1515
}
1616

1717
template <typename I>

code/test_insertion_sort.cpp

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,57 @@
11
#include <functional>
22
#include <iostream>
3+
#include <cassert>
34
#include "insertion_sort.h"
5+
#include "list_pool.h"
46
#include "algorithm.h"
57

68
int main() {
9+
10+
// test binary insertion sort
711
{
812
int nums[] = {5, 3, 10, 1, 2};
9-
print_range(nums, nums + 5);
1013
binary_insertion_sort_n(nums, 5, std::less<int>());
1114
print_range(nums, nums + 5);
15+
assert(is_sorted(nums, nums + 5));
1216
}
17+
// test linear insertion sort
1318
{
1419
int nums[] = {5, 3, 10, 1, 2};
15-
print_range(nums, nums + 5);
1620
linear_insertion_sort_n(nums, 5, std::less<int>());
1721
print_range(nums, nums + 5);
22+
23+
assert(is_sorted(nums, nums + 5));
1824
}
25+
// test for forward iterators
26+
{
27+
// std::list provides bidirectional iterators and
28+
// std::forward_list is in C++11, so we will use
29+
// our list pool to test this.
30+
31+
list_pool<int, int> pool;
32+
33+
// Create a list "1 2 3",
34+
typename list_pool<int, int>::list_type l = pool.end();
35+
l = pool.allocate(3, l);
36+
l = pool.allocate(2, l);
37+
l = pool.allocate(1, l);
38+
39+
typedef typename list_pool<int, int>::iterator I;
40+
I first(pool, l);
41+
I last(pool);
42+
43+
// do a few rotates and print the results
44+
rotate_right_by_one(first, last);
45+
print_range(first, last);
46+
47+
rotate_right_by_one(first, last);
48+
print_range(first, last);
49+
50+
rotate_right_by_one(first, last);
51+
print_range(first, last);
52+
}
53+
54+
1955
return 0;
2056
}
2157

0 commit comments

Comments
 (0)