要求實現插入排序、歸併排序、快速排序三種算法,並編寫測試代碼驗證:
int foo(int x, int y, int z) {
if (z == 0) { x = 1; y = -1; }
if (x > 0) {
if (y > 0) return 1;
else return 2;
} else {
if (y > 0) return 3;
else return 4;
}
}
if/else 兩側各執行一次| 數據特徵 | 測試目的 | 示例 |
|---|---|---|
| 空數組 | 邊界條件、不崩潰 | {} |
| 單元素 | 基線情況 | {42} |
| 已有序 | 最好情況、穩定性 | {1,2,3,4,5} |
| 逆序 | 最壞情況、遞歸深度 | {5,4,3,2,1} |
| 含重複元素 | 穩定性、分區邏輯 | {3,1,4,1,5,9,2,6,5} |
| 大量隨機數 | 平均情況性能 | 10^5 隨機整數 |
| 幾乎有序 | 插入排序優勢場景 | 1,2,3,5,4,6,7... |
#include <vector>
#include <chrono>
#include <algorithm>
#include <iostream>
#include <random>
using Clock = std::chrono::high_resolution_clock;
using Ms = std::chrono::milliseconds;
// 待測算法接口
void insertSort(std::vector<int>& a);
void mergeSort(std::vector<int>& a);
void quickSort(std::vector<int>& a);
// 驗證有序性
bool isSorted(const std::vector<int>& a) {
return std::is_sorted(a.begin(), a.end());
}
// 單次測試
template<typename Fn>
long long benchmark(Fn sortFn, std::vector<int> data, const char* name) {
auto t0 = Clock::now();
sortFn(data);
auto t1 = Clock::now();
bool ok = isSorted(data);
std::cout << name << ": " << (ok ? "PASS" : "FAIL")
<< ", time=" << std::chrono::duration_cast<Ms>(t1-t0).count() << "ms\n";
return ok ? 0 : 1;
}
int main() {
std::vector<std::pair<std::string, std::vector<int>>> testCases = {
{"empty", {}},
{"single", {42}},
{"sorted", {1,2,3,4,5}},
{"reversed", {5,4,3,2,1}},
{"duplicates", {3,1,4,1,5,9,2,6,5}},
{"near_sorted", {1,2,3,5,4,6,7,8,9,10}},
};
// 小規模正確性驗證(含輸出遍歷結果)
for (auto& tc : testCases) {
auto v = tc.second;
insertSort(v);
std::cout << "InsertSort [" << tc.first << "]: ";
for (int x : v) std::cout << x << ' ';
std::cout << '\n';
// 同理 mergeSort, quickSort...
}
// 大規模性能基準
std::mt19937 rng(42);
std::uniform_int_distribution<int> dist(0, 1000000);
std::vector<int> big(100000);
for (int& x : big) x = dist(rng);
benchmark(insertSort, big, "InsertSort");
benchmark(mergeSort, big, "MergeSort");
benchmark(quickSort, big, "QuickSort");
return 0;
}
| 算法 | 平均時間 | 最壞時間 | 空間 | 穩定 | 實測 10^5 隨機數 (ms) |
|---|---|---|---|---|---|
| 插入排序 | O(n²) | O(n²) | O(1) | ✅ | ~1200 |
| 歸併排序 | O(n log n) | O(n log n) | O(n) | ✅ | ~15 |
| 快速排序 | O(n log n) | O(n²) | O(log n) | ❌ | ~10 |
編譯加旗標:g++ -fprofile-arcs -ftest-coverage -O0 test.cpp -o test
運行 ./test 生成 .gcda,用 lcov / gcovr 生成 HTML 報告,直觀查看每個 if/else 是否被執行。
「測試不是為了證明代碼對,而是為了找出代碼錯。構造極端、邊界、惡意數據,比隨機大數據更能暴露缺陷。」