Skip to content

Commit 27f2fa8

Browse files
Merge pull request wangzheng0822#79 from Liam0205/12_sorts
[C++][12_sorts] 归并排序和快速排序
2 parents 42b6fd1 + a72dbfc commit 27f2fa8

File tree

5 files changed

+186
-0
lines changed

5 files changed

+186
-0
lines changed

c-cpp/12_sorts/.gitkeep

Whitespace-only changes.

c-cpp/12_sorts/merge_sort.hpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/**
2+
* Created by Liam Huang (Liam0205) on 2018/10/17.
3+
*/
4+
5+
#ifndef SORTS_MERGE_SORT_HPP_
6+
#define SORTS_MERGE_SORT_HPP_
7+
8+
#include <functional>
9+
#include <algorithm>
10+
#include <iterator>
11+
#include <vector>
12+
13+
namespace detail {
14+
template <typename InputIt1, typename InputIt2, typename OutputIt,
15+
typename BinaryPred = std::less<typename std::iterator_traits<InputIt1>::value_type>>
16+
OutputIt merge(InputIt1 first1, InputIt1 last1,
17+
InputIt2 first2, InputIt2 last2,
18+
OutputIt d_first,
19+
BinaryPred comp = BinaryPred()) {
20+
for (; first1 != last1; ++d_first) {
21+
if (first2 == last2) {
22+
return std::copy(first1, last1, d_first);
23+
}
24+
if (comp(*first2, *first1)) {
25+
*d_first = *first2;
26+
++first2;
27+
} else {
28+
*d_first = *first1;
29+
++first1;
30+
}
31+
}
32+
return std::copy(first2, last2, d_first);
33+
}
34+
} // namespace detail
35+
36+
template <typename FrwdIt,
37+
typename BinaryPred = std::less<typename std::iterator_traits<FrwdIt>::value_type>>
38+
void merge_sort(FrwdIt first, FrwdIt last, BinaryPred comp = BinaryPred()) {
39+
const auto len = std::distance(first, last);
40+
if (len <= 1) { return; }
41+
auto cut = first + len / 2;
42+
merge_sort(first, cut, comp);
43+
merge_sort(cut, last, comp);
44+
std::vector<typename std::iterator_traits<FrwdIt>::value_type> tmp;
45+
tmp.reserve(len);
46+
detail::merge(first, cut, cut, last, std::back_inserter(tmp), comp);
47+
std::copy(tmp.begin(), tmp.end(), first);
48+
}
49+
50+
template <typename BidirIt,
51+
typename BinaryPred = std::less<typename std::iterator_traits<BidirIt>::value_type>>
52+
void inplace_merge_sort(BidirIt first, BidirIt last, BinaryPred comp = BinaryPred()) {
53+
const auto len = std::distance(first, last);
54+
if (len <= 1) { return; }
55+
auto cut = first + len / 2;
56+
merge_sort(first, cut, comp);
57+
merge_sort(cut, last, comp);
58+
std::inplace_merge(first, cut, last, comp);
59+
}
60+
61+
#endif // SORTS_MERGE_SORT_HPP_
62+

c-cpp/12_sorts/merge_sort_test.cc

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* Created by Liam Huang (Liam0205) on 2018/10/17.
3+
*/
4+
5+
#include <iostream>
6+
#include <vector>
7+
#include "merge_sort.hpp"
8+
9+
int main() {
10+
const std::vector<int> test_data{0, -1, 3, 190, -500};
11+
12+
std::vector<int> a{test_data};
13+
merge_sort(a.begin(), a.end());
14+
for (auto i : a) {
15+
std::cout << i << ' ';
16+
}
17+
std::cout << std::endl;
18+
19+
std::vector<int> b{test_data};
20+
inplace_merge_sort(b.begin(), b.end());
21+
for (auto i : b) {
22+
std::cout << i << ' ';
23+
}
24+
std::cout << std::endl;
25+
26+
return 0;
27+
}
28+

c-cpp/12_sorts/quick_sort.hpp

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/**
2+
* Created by Liam Huang (Liam0205) on 2018/10/17.
3+
*/
4+
5+
#ifndef SORTS_QUICK_SORT_HPP_
6+
#define SORTS_QUICK_SORT_HPP_
7+
8+
#include <functional>
9+
#include <iterator>
10+
#include <algorithm>
11+
#include <utility>
12+
13+
namespace detail {
14+
template <typename T, typename Compare = std::less<T>>
15+
const T& median(const T& a, const T& b, const T& c, Compare comp = Compare()) {
16+
if (comp(a, b) and comp(b, c) or comp(c, b) and comp(b, a)) {
17+
return b;
18+
} else if (comp(b, c) and comp(c, a) or comp(a, c) and comp(c, b)) {
19+
return c;
20+
} else {
21+
return a;
22+
}
23+
}
24+
25+
template <typename Iter,
26+
typename T = typename std::iterator_traits<Iter>::value_type,
27+
typename Compare = std::less<T>>
28+
const T& iter_median(Iter a, Iter b, Iter c, Compare comp = Compare()) {
29+
return median(*a, *b, *c, comp);
30+
}
31+
32+
template <typename BidirIt,
33+
typename T = typename std::iterator_traits<BidirIt>::value_type,
34+
typename Compare = std::less<T>>
35+
std::pair<BidirIt, BidirIt> inplace_partition(BidirIt first,
36+
BidirIt last,
37+
const T& pivot,
38+
Compare comp = Compare()) {
39+
BidirIt last_less, last_greater, first_equal, last_equal;
40+
for (last_less = first, last_greater = first, first_equal = last;
41+
last_greater != first_equal; ) {
42+
if (comp(*last_greater, pivot)) {
43+
std::iter_swap(last_greater++, last_less++);
44+
} else if (comp(pivot, *last_greater)) {
45+
++last_greater;
46+
} else { // pivot == *last_greater
47+
std::iter_swap(last_greater, --first_equal);
48+
}
49+
}
50+
const auto cnt = std::distance(first_equal, last);
51+
std::swap_ranges(first_equal, last, last_less);
52+
first_equal = last_less;
53+
last_equal = first_equal + cnt;
54+
return {first_equal, last_equal};
55+
}
56+
} // namespace detail
57+
58+
template <typename BidirIt,
59+
typename T = typename std::iterator_traits<BidirIt>::value_type,
60+
typename Compare = std::less<T>>
61+
void quick_sort(BidirIt first, BidirIt last, Compare comp = Compare()) {
62+
for (auto size = std::distance(first, last); size > 1; size = std::distance(first, last)) {
63+
const T pivot = detail::iter_median(first, last - 1, first + size / 2, comp);
64+
const auto eq = detail::inplace_partition(first, last, pivot, comp);
65+
quick_sort(first, eq.first, comp);
66+
first = eq.second; // Liam Huang: economize half of recursive calling.
67+
}
68+
}
69+
70+
#endif // SORTS_QUICK_SORT_HPP_
71+

c-cpp/12_sorts/quick_sort_test.cc

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
* Created by Liam Huang (Liam0205) on 2018/10/17.
3+
*/
4+
5+
#include <iostream>
6+
#include <vector>
7+
#include <algorithm>
8+
9+
#include "quick_sort.hpp"
10+
11+
void test_quick_sort(std::vector<int> test_data) {
12+
quick_sort(test_data.begin(), test_data.end());
13+
std::transform(test_data.begin(), test_data.end(),
14+
std::ostream_iterator<int>(std::cout, " "), [](int i){ return i; });
15+
std::cout << '\n';
16+
}
17+
18+
int main() {
19+
test_quick_sort({-3, -1, 1, -2, -3, 0, -3, 100, 1, 1, -100});
20+
test_quick_sort({1, 1, 1});
21+
test_quick_sort({1, 0, -1});
22+
test_quick_sort({1});
23+
return 0;
24+
}
25+

0 commit comments

Comments
 (0)