CPP09 1.0
読み取り中…
検索中…
一致する文字列を見つけられません
PmergeMe_count_ver.cpp
[詳解]
1#include "PmergeMe.hpp"
2#include <algorithm> // for std::distance
3#include <climits>
4#include <cstdlib>
5#include <utility>
6
7// --- Orthodox Canonical Form & Constructor ---
8PmergeMe::PmergeMe() : _comparisonCount(0) {}
10PmergeMe::PmergeMe(const PmergeMe &src) { (void)src; }
11PmergeMe &PmergeMe::operator=(const PmergeMe &rhs) {
12 (void)rhs;
13 return *this;
14}
15
16// --- Counter Methods ---
17void PmergeMe::resetCounter() { _comparisonCount = 0; }
18long PmergeMe::getComparisonCount() const { return _comparisonCount; }
19
20// --- Timing Helper ---
21long PmergeMe::getTimeStamp() {
22 struct timeval tv;
23 gettimeofday(&tv, NULL);
24 return tv.tv_sec * 1000000 + tv.tv_usec;
25}
26
27// --- Custom Binary Search with Counter ---
28// vector
29std::vector<int>::iterator PmergeMe::counting_lower_bound(std::vector<int> &vec, int value) {
34 count = std::distance(first, last);
35
36 while (count > 0) {
37 it = first;
38 step = count / 2;
39 std::advance(it, step);
40
41 // ここで比較を行う
42 _comparisonCount++;
43 if (*it < value) {
44 first = ++it;
45 count -= step + 1;
46 } else {
47 count = step;
48 }
49 }
50 return first;
51}
52
53// deque
54std::deque<int>::iterator PmergeMe::counting_lower_bound(std::deque<int> &deq, int value) {
55 std::deque<int>::iterator first = deq.begin();
56 std::deque<int>::iterator last = deq.end();
59 count = std::distance(first, last);
60
61 while (count > 0) {
62 it = first;
63 step = count / 2;
64 std::advance(it, step);
65
66 // ここで比較を行う
67 _comparisonCount++;
68 if (*it < value) {
69 first = ++it;
70 count -= step + 1;
71 } else {
72 count = step;
73 }
74 }
75 return first;
76}
77
78// --- Vector Implementation (with Counter) ---
79// void PmergeMe::mergeInsertSort(std::vector<int> &vec) {
80// if (vec.size() <= 1)
81// return;
82//
83// // 1. Create pair, sort in each pair.
84// std::vector<std::pair<int, int> > pairs;
85// int straggler = -1;
86// bool hasStraggler = vec.size() % 2 != 0;
87// if (hasStraggler) {
88// straggler = vec.back();
89// vec.pop_back();
90// }
91//
92// for (size_t i = 0; i < vec.size(); i += 2) {
93// _comparisonCount++; // Compair in pair.
94// if (vec[i] < vec[i + 1]) {
95// pairs.push_back(std::make_pair(vec[i + 1], vec[i]));
96// } else {
97// pairs.push_back(std::make_pair(vec[i], vec[i + 1]));
98// }
99// }
100//
101// // 2. Recursively sort the sequence of larger elements in pairs (main chain)
102// std::vector<int> mainChain;
103// for (size_t i = 0; i < pairs.size(); ++i) {
104// mainChain.push_back(pairs[i].first);
105// }
106// mergeInsertSort(mainChain); // recursive call
107//
108// // ... (Insertion logic) ...
109// // ヤコブスタール数を使った挿入ロジック
110// // この部分は簡略化せず、元のロジックをそのまま使います
111// // ただし、std::lower_boundを自前のものに置き換えます
112//
113// // Find the first pend element to insert
114// int first_pend = -1;
115// for (size_t i = 0; i < pairs.size(); ++i) {
116// if (pairs[i].first == mainChain[0]) {
117// first_pend = pairs[i].second;
118// break;
119// }
120// }
121// if (first_pend != -1) {
122// mainChain.insert(mainChain.begin(), first_pend);
123// }
124//
125// size_t lastInserted = 1;
126// for (size_t k = 2;; ++k) {
127// long jacobsthal_k = (1L << k) - ((k % 2 == 0) ? 1 : -1);
128// jacobsthal_k /= 3;
129//
130// size_t insertCount = jacobsthal_k - lastInserted;
131// if (static_cast<size_t>(jacobsthal_k) > pairs.size()) {
132// insertCount = pairs.size() - lastInserted;
133// }
134//
135// for (size_t i = 0; i < insertCount; ++i) {
136// size_t pairIndex = jacobsthal_k - i - 1;
137// if (pairIndex >= pairs.size() || pairIndex < 1)
138// continue;
139//
140// int valueToInsert = pairs[pairIndex].second;
141// // std::lower_boundの代わりに自前の関数を使用
142// std::vector<int>::iterator it = counting_lower_bound(mainChain, valueToInsert);
143// mainChain.insert(it, valueToInsert);
144// }
145//
146// lastInserted += insertCount;
147// if (lastInserted >= pairs.size())
148// break;
149// }
150//
151// if (hasStraggler) {
152// std::vector<int>::iterator it = counting_lower_bound(mainChain, straggler);
153// mainChain.insert(it, straggler);
154// }
155//
156// vec = mainChain;
157//}
158
159// Deque implementation is omitted for brevity, but would be modified similarly.
160// void PmergeMe::mergeInsertSort(std::deque<int> &deq) {
161// if (deq.size() <= 1)
162// return;
163//
164// // 1. Create pair, sort in each pair.
165// std::deque<std::pair<int, int> > pairs;
166// int straggler = -1;
167// bool hasStraggler = deq.size() % 2 != 0;
168// if (hasStraggler) {
169// straggler = deq.back();
170// deq.pop_back();
171// }
172//
173// for (size_t i = 0; i < deq.size(); i += 2) {
174// _comparisonCount++; // Compair in pair.
175// if (deq[i] < deq[i + 1]) {
176// pairs.push_back(std::make_pair(deq[i + 1], deq[i]));
177// } else {
178// pairs.push_back(std::make_pair(deq[i], deq[i + 1]));
179// }
180// }
181//
182// // 2. Recursively sort the sequence of larger elements in pairs (main chain)
183// std::deque<int> mainChain;
184// for (size_t i = 0; i < pairs.size(); ++i) {
185// mainChain.push_back(pairs[i].first);
186// }
187// mergeInsertSort(mainChain); // recursive call
188//
189// // ... (Insertion logic) ...
190// // ヤコブスタール数を使った挿入ロジック
191// // この部分は簡略化せず、元のロジックをそのまま使います
192// // ただし、std::lower_boundを自前のものに置き換えます
193//
194// // Find the first pend element to insert
195// int first_pend = -1;
196// for (size_t i = 0; i < pairs.size(); ++i) {
197// if (pairs[i].first == mainChain[0]) {
198// first_pend = pairs[i].second;
199// break;
200// }
201// }
202// if (first_pend != -1) {
203// mainChain.insert(mainChain.begin(), first_pend);
204// }
205//
206// size_t lastInserted = 1;
207// for (size_t k = 2;; ++k) {
208// long jacobsthal_k = (1L << k) - ((k % 2 == 0) ? 1 : -1);
209// jacobsthal_k /= 3;
210//
211// size_t insertCount = jacobsthal_k - lastInserted;
212// if (static_cast<size_t>(jacobsthal_k) > pairs.size()) {
213// insertCount = pairs.size() - lastInserted;
214// }
215//
216// for (size_t i = 0; i < insertCount; ++i) {
217// size_t pairIndex = jacobsthal_k - i - 1;
218// if (pairIndex >= pairs.size() || pairIndex < 1)
219// continue;
220//
221// int valueToInsert = pairs[pairIndex].second;
222// // std::lower_boundの代わりに自前の関数を使用
223// std::deque<int>::iterator it = counting_lower_bound(mainChain, valueToInsert);
224// mainChain.insert(it, valueToInsert);
225// }
226//
227// lastInserted += insertCount;
228// if (lastInserted >= pairs.size())
229// break;
230// }
231//
232// if (hasStraggler) {
233// std::deque<int>::iterator it = counting_lower_bound(mainChain, straggler);
234// mainChain.insert(it, straggler);
235// }
236//
237// deq = mainChain;
238//}
239
240// The original sortAndCompare is not needed for this specific test.
241// void PmergeMe::sortAndCompare(int argc, char **argv) {
242// (void)argc;
243// (void)argv;
244//}
245
246// #include "PmergeMe.hpp"
247// #include <climits> // for LONG_MAX
248// #include <cstdlib> // for strtol
249// #include <utility> // for std::pair
250//
252//
253// PmergeMe::PmergeMe() {}
254//
255// PmergeMe::~PmergeMe() {}
256//
257// PmergeMe::PmergeMe(const PmergeMe &src) { (void)src; }
258//
259// PmergeMe &PmergeMe::operator=(const PmergeMe &rhs) {
260// (void)rhs;
261// return *this;
262//}
263//
265//
266// long PmergeMe::getTimeStamp() {
267// struct timeval tv;
268// gettimeofday(&tv, NULL);
269// return tv.tv_sec * 1000000 + tv.tv_usec;
270//}
271//
273//
274// vector用のマージ挿入ソート
276 if (vec.size() <= 1)
277 return;
278
279 // 1. ペアを作成し、各ペア内をソート
281 int straggler = -1;
282 bool hasStraggler = vec.size() % 2 != 0;
283 if (hasStraggler) {
284 straggler = vec.back();
285 vec.pop_back();
286 }
287
288 for (size_t i = 0; i < vec.size(); i += 2) {
289 if (vec[i] < vec[i + 1]) {
290 pairs.push_back(std::make_pair(vec[i + 1], vec[i]));
291 } else {
292 pairs.push_back(std::make_pair(vec[i], vec[i + 1]));
293 }
294 }
295
296 // 2. ペアの大きい要素のシーケンス(main chain)を再帰的にソート
297 std::vector<int> mainChain;
298 for (size_t i = 0; i < pairs.size(); ++i) {
299 mainChain.push_back(pairs[i].first);
300 }
301 mergeInsertSort(mainChain);
302
303 // 3. main chainに小さい要素(pend elements)を挿入
304 // まず、最初のペアの小さい要素を先頭に挿入
305 for (size_t i = 0; i < pairs.size(); ++i) {
306 if (pairs[i].first == mainChain[0]) {
307 mainChain.insert(mainChain.begin(), pairs[i].second);
308 break;
309 }
310 }
311
312 // ヤコブスタール数を利用して最適な順序で挿入
313 // C++98ではラムダや複雑なイテレータ操作が使えないため、インデックスベースで処理
314 size_t lastInserted = 1;
315 for (size_t k = 2;; ++k) {
316 // ヤコブスタール数 J(k) を計算 (簡易的な方法)
317 long jacobsthal_k = (1L << k) - ((k % 2 == 0) ? 1 : -1);
318 jacobsthal_k /= 3;
319
320 size_t insertCount = jacobsthal_k - lastInserted;
321 if (static_cast<size_t>(jacobsthal_k) > pairs.size()) {
322 insertCount = pairs.size() - lastInserted;
323 }
324
325 for (size_t i = 0; i < insertCount; ++i) {
326 size_t pairIndex = jacobsthal_k - i - 1;
327 if (pairIndex >= pairs.size())
328 continue;
329
330 int valueToInsert = pairs[pairIndex].second;
331 std::vector<int>::iterator it = std::lower_bound(mainChain.begin(), mainChain.end(), valueToInsert);
332 mainChain.insert(it, valueToInsert);
333 }
334
335 lastInserted += insertCount;
336 if (lastInserted >= pairs.size())
337 break;
338 }
339
340 // 4. はぐれた要素(straggler)があれば挿入
341 if (hasStraggler) {
342 std::vector<int>::iterator it = std::lower_bound(mainChain.begin(), mainChain.end(), straggler);
343 mainChain.insert(it, straggler);
344 }
345
346 vec = mainChain;
347}
348//
350//
353 if (deq.size() <= 1)
354 return;
355
357 int straggler = -1;
358 bool hasStraggler = deq.size() % 2 != 0;
359 if (hasStraggler) {
360 straggler = deq.back();
361 deq.pop_back();
362 }
363
364 for (size_t i = 0; i < deq.size(); i += 2) {
365 if (deq[i] < deq[i + 1]) {
366 pairs.push_back(std::make_pair(deq[i + 1], deq[i]));
367 } else {
368 pairs.push_back(std::make_pair(deq[i], deq[i + 1]));
369 }
370 }
371
372 std::deque<int> mainChain;
373 for (size_t i = 0; i < pairs.size(); ++i) {
374 mainChain.push_back(pairs[i].first);
375 }
376 mergeInsertSort(mainChain);
377
378 for (size_t i = 0; i < pairs.size(); ++i) {
379 if (pairs[i].first == mainChain[0]) {
380 mainChain.insert(mainChain.begin(), pairs[i].second);
381 break;
382 }
383 }
384
385 size_t lastInserted = 1;
386 for (size_t k = 2;; ++k) {
387 long jacobsthal_k = (1L << k) - ((k % 2 == 0) ? 1 : -1);
388 jacobsthal_k /= 3;
389
390 size_t insertCount = jacobsthal_k - lastInserted;
391 if (static_cast<size_t>(jacobsthal_k) > pairs.size()) {
392 insertCount = pairs.size() - lastInserted;
393 }
394
395 for (size_t i = 0; i < insertCount; ++i) {
396 size_t pairIndex = jacobsthal_k - i - 1;
397 if (pairIndex >= pairs.size())
398 continue;
399
400 int valueToInsert = pairs[pairIndex].second;
401 std::deque<int>::iterator it = std::lower_bound(mainChain.begin(), mainChain.end(), valueToInsert);
402 mainChain.insert(it, valueToInsert);
403 }
404
405 lastInserted += insertCount;
406 if (lastInserted >= pairs.size())
407 break;
408 }
409
410 if (hasStraggler) {
411 std::deque<int>::iterator it = std::lower_bound(mainChain.begin(), mainChain.end(), straggler);
412 mainChain.insert(it, straggler);
413 }
414
415 deq = mainChain;
416}
417//
419//
420void PmergeMe::sortAndCompare(int argc, char **argv) {
422 std::deque<int> deq;
423
424 // 1. 引数のパースと検証
425 for (int i = 1; i < argc; ++i) {
426 char *end;
427 long val = std::strtol(argv[i], &end, 10);
428 if (*end != '\0' || val <= 0 || val > INT_MAX) {
429 throw std::invalid_argument("Error: Invalid input.");
430 }
431 vec.push_back(static_cast<int>(val));
432 deq.push_back(static_cast<int>(val));
433 }
434
435 // 2. ソート前のシーケンスを表示
436 std::cout << "Before: ";
437 for (size_t i = 0; i < vec.size(); ++i) {
438 std::cout << vec[i] << (i == vec.size() - 1 ? "" : " ");
439 }
441
442 // 3. vectorのソートと時間計測
443 long startVec = getTimeStamp();
444 mergeInsertSort(vec);
445 long endVec = getTimeStamp();
446 double timeVec = static_cast<double>(endVec - startVec);
447
448 // 4. ソート後のシーケンスを表示
449 std::cout << "After: ";
450 for (size_t i = 0; i < vec.size(); ++i) {
451 std::cout << vec[i] << (i == vec.size() - 1 ? "" : " ");
452 }
454
455 // 5. dequeのソートと時間計測
456 long startDeq = getTimeStamp();
457 mergeInsertSort(deq);
458 long endDeq = getTimeStamp();
459 double timeDeq = static_cast<double>(endDeq - startDeq);
460
461 // 6. 結果の表示
462 std::cout << "Time to process a range of " << argc - 1 << " elements with std::vector : " << timeVec << " us"
463 << std::endl;
464 std::cout << "Time to process a range of " << argc - 1 << " elements with std::deque : " << timeDeq << " us"
465 << std::endl;
466}
マージ挿入ソートアルゴリズムを実装し、異なるコンテナでのパフォーマンスを比較するPmergeMeクラスを提供します。
T advance(T... args)
T back(T... args)
T begin(T... args)
マージ挿入ソート(フォード・ジョンソンアルゴリズム)を用いて数値シーケンスをソートするクラス。
Definition PmergeMe.hpp:38
void sortAndCompare(int argc, char **argv)
コマンドライン引数をパースし、ソートを実行して結果を比較・表示します。
Definition PmergeMe.cpp:190
void mergeInsertSort(std::vector< int > &arr)
std::vectorに対してマージ挿入ソートを実行します。
Definition PmergeMe.cpp:58
PmergeMe()
デフォルトコンストラクタ。
Definition PmergeMe.cpp:37
~PmergeMe()
デストラクタ。
Definition PmergeMe.cpp:39
T count(T... args)
T distance(T... args)
T end(T... args)
T endl(T... args)
T insert(T... args)
T lower_bound(T... args)
T make_pair(T... args)
T pop_back(T... args)
T push_back(T... args)
T size(T... args)
T strtol(T... args)