first commit

This commit is contained in:
2025-12-18 16:00:22 +08:00
commit 785f306726
69 changed files with 33171 additions and 0 deletions

View File

@ -0,0 +1,35 @@
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
/*
* function : implement bubble sort
* param nums : the vector to be sorted
* param comp_count : count of comparisons
* param move_count : count of moves
* return : ---
*/
void BubbleSort(vector<int> &nums, long long &comp_count, long long &move_count)
{
bool swapped;
for (int i = 0; i < static_cast<int>(nums.size()) - 1; i++)
{
swapped = false;
for (int j = 0; j < static_cast<int>(nums.size()) - 1 - i; j++)
{
comp_count++;
if (nums[j] > nums[j + 1])
{
swap(nums[j], nums[j + 1]);
move_count += 3; // std::swap is 3 moves
swapped = true;
}
}
if (!swapped)
{
break;
}
}
}

View File

@ -0,0 +1,67 @@
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void dualPivotQuickSortHelper(vector<int>& nums, int left, int right, long long& comp_count, long long& move_count) {
if (left < right) {
comp_count++;
if (nums[left] > nums[right]) {
swap(nums[left], nums[right]);
move_count += 3;
}
int p = nums[left], q = nums[right];
int l = left + 1, g = right - 1, k = l;
while (k <= g) {
comp_count++;
if (nums[k] < p) {
swap(nums[k], nums[l]);
move_count += 3;
l++;
} else {
comp_count++;
if (nums[k] > q) {
while (k < g && (comp_count++, nums[g] > q)) {
g--;
}
swap(nums[k], nums[g]);
move_count += 3;
g--;
comp_count++;
if (nums[k] < p) {
swap(nums[k], nums[l]);
move_count += 3;
l++;
}
}
}
k++;
}
l--;
g++;
swap(nums[left], nums[l]);
move_count += 3;
swap(nums[right], nums[g]);
move_count += 3;
dualPivotQuickSortHelper(nums, left, l - 1, comp_count, move_count);
dualPivotQuickSortHelper(nums, l + 1, g - 1, comp_count, move_count);
dualPivotQuickSortHelper(nums, g + 1, right, comp_count, move_count);
}
}
/*
* function : implement dual pivot quick sort
* param nums : the vector to be sorted
* param comp_count : count of comparisons
* param move_count : count of moves
* return : ---
*/
void DualPivotQuickSort(vector<int>& nums, long long& comp_count, long long& move_count) {
if (nums.empty()) return;
dualPivotQuickSortHelper(nums, 0, nums.size() - 1, comp_count, move_count);
}

View File

@ -0,0 +1,33 @@
#include <iostream>
#include <vector>
#include <algorithm>
#include <ctime>
#include <cstdlib>
#include <stack>
#include <string>
#include <cstring>
using namespace std;
/*
* function : implement insert sort
* param nums : the vector to be sorted
* param comp_count : count of comparisons
* param move_count : count of moves
* return : ---
*/
void InsertSort(vector<int> &nums, long long &comp_count, long long &move_count)
{
for (int i = 1; i < static_cast<int>(nums.size()); i++)
{
int key = nums[i];
int j = i - 1;
while (j >= 0 && (comp_count++, nums[j] > key))
{
nums[j + 1] = nums[j];
move_count++;
j--;
}
nums[j + 1] = key;
move_count++;
}
}

View File

@ -0,0 +1,36 @@
# Compiler and flags
CXX := g++
CXXFLAGS := -std=c++11 -Wall -O2
# Executable name
TARGET := sorting_experiment
# Source files
# Automatically find all .cpp files in the current directory
SRCS := $(wildcard *.cpp)
# Object files
# Replace .cpp extension with .o
OBJS := $(SRCS:.cpp=.o)
# Default target
all: $(TARGET)
# Link the program
$(TARGET): $(OBJS)
$(CXX) $(CXXFLAGS) -o $(TARGET) $(OBJS)
# Compile source files into object files
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $@
# Target to run the experiment
run: all
@./$(TARGET)
# Clean up build files
clean:
rm -f $(TARGET) $(OBJS)
# Phony targets
.PHONY: all clean run

View File

@ -0,0 +1,86 @@
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void merge(vector<int> &nums, int left, int mid, int right, long long &comp_count, long long &move_count)
{
int n1 = mid - left + 1;
int n2 = right - mid;
vector<int> L(n1), R(n2);
for (int i = 0; i < n1; i++)
{
L[i] = nums[left + i];
move_count++;
}
for (int j = 0; j < n2; j++)
{
R[j] = nums[mid + 1 + j];
move_count++;
}
int i = 0;
int j = 0;
int k = left;
while (i < n1 && j < n2)
{
comp_count++;
if (L[i] <= R[j])
{
nums[k] = L[i];
move_count++;
i++;
}
else
{
nums[k] = R[j];
move_count++;
j++;
}
k++;
}
while (i < n1)
{
nums[k] = L[i];
move_count++;
i++;
k++;
}
while (j < n2)
{
nums[k] = R[j];
move_count++;
j++;
k++;
}
}
void mergeSortHelper(vector<int> &nums, int left, int right, long long &comp_count, long long &move_count)
{
if (left < right)
{
int mid = left + (right - left) / 2;
mergeSortHelper(nums, left, mid, comp_count, move_count);
mergeSortHelper(nums, mid + 1, right, comp_count, move_count);
merge(nums, left, mid, right, comp_count, move_count);
}
}
/*
* function : implement merge sort
* param nums : the vector to be sorted
* param comp_count : count of comparisons
* param move_count : count of moves
* return : ---
*/
void MergeSort(vector<int> &nums, long long &comp_count, long long &move_count)
{
if (nums.empty()) return;
mergeSortHelper(nums, 0, nums.size() - 1, comp_count, move_count);
}

View File

@ -0,0 +1,48 @@
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int partition(vector<int> &nums, int low, int high, long long &comp_count, long long &move_count)
{
int pivot = nums[high];
int i = (low - 1);
for (int j = low; j <= high - 1; j++)
{
comp_count++;
if (nums[j] < pivot)
{
i++;
swap(nums[i], nums[j]);
move_count += 3;
}
}
swap(nums[i + 1], nums[high]);
move_count += 3;
return (i + 1);
}
void quickSortHelper(vector<int> &nums, int low, int high, long long &comp_count, long long &move_count)
{
if (low < high)
{
int pi = partition(nums, low, high, comp_count, move_count);
quickSortHelper(nums, low, pi - 1, comp_count, move_count);
quickSortHelper(nums, pi + 1, high, comp_count, move_count);
}
}
/*
* function : implement quick sort
* param nums : the vector to be sorted
* param comp_count : count of comparisons
* param move_count : count of moves
* return : ---
*/
void QuickSort(vector<int> &nums, long long &comp_count, long long &move_count)
{
if (nums.empty()) return;
quickSortHelper(nums, 0, nums.size() - 1, comp_count, move_count);
}

View File

@ -0,0 +1,70 @@
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
/*
* This function partitions the array into three parts:
* a) arr[l..i] contains all elements smaller than pivot
* b) arr[i+1..j-1] contains all elements equal to pivot
* c) arr[j..r] contains all elements greater than pivot
*/
void partition3Way(vector<int> &nums, int l, int r, int &i, int &j, long long &comp_count, long long &move_count)
{
// To handle cases where array is sorted or nearly sorted
int mid = l + (r - l) / 2;
swap(nums[mid], nums[l]);
move_count += 3;
i = l, j = r + 1;
int pivot = nums[l];
while (true)
{
while (comp_count++, nums[++i] < pivot)
if (i == r) break;
while (comp_count++, pivot < nums[--j])
if (j == l) break;
// check if pointers cross
if (i >= j) break;
swap(nums[i], nums[j]);
move_count += 3;
}
swap(nums[l], nums[j]);
move_count += 3;
i = j; // Return the pivot position
}
void quickSort3WayHelper(vector<int> &nums, int low, int high, long long &comp_count, long long &move_count)
{
if (high <= low) return;
int i, j;
partition3Way(nums, low, high, i, j, comp_count, move_count);
quickSort3WayHelper(nums, low, i - 1, comp_count, move_count);
quickSort3WayHelper(nums, i + 1, high, comp_count, move_count);
}
/*
* function : implement 3-way quick sort
* param nums : the vector to be sorted
* param comp_count : count of comparisons
* param move_count : count of moves
* return : ---
*/
void QuickSort3Way(vector<int> &nums, long long &comp_count, long long &move_count)
{
if (nums.empty()) return;
// For better performance on random data, shuffle is recommended, but we'll skip for this experiment
// random_shuffle(nums.begin(), nums.end());
quickSort3WayHelper(nums, 0, nums.size() - 1, comp_count, move_count);
}

View File

@ -0,0 +1,81 @@
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// Helper to find median of three and swap pivot to the end
int medianOfThree(vector<int> &nums, int low, int high, long long &comp_count, long long &move_count)
{
int mid = low + (high - low) / 2;
comp_count++;
if (nums[low] > nums[mid])
{
swap(nums[low], nums[mid]);
move_count += 3;
}
comp_count++;
if (nums[low] > nums[high])
{
swap(nums[low], nums[high]);
move_count += 3;
}
comp_count++;
if (nums[mid] > nums[high])
{
swap(nums[mid], nums[high]);
move_count += 3;
}
// Now nums[low] <= nums[mid] <= nums[high]
// Pivot is nums[mid], but we swap it with nums[high-1] to use in partition
// The partition logic will ignore the already sorted nums[low] and nums[high]
swap(nums[mid], nums[high]); // Move pivot to the end
move_count += 3;
return nums[high];
}
int partition_optimized(vector<int> &nums, int low, int high, long long &comp_count, long long &move_count)
{
int pivot = medianOfThree(nums, low, high, comp_count, move_count);
int i = (low - 1);
for (int j = low; j <= high - 1; j++)
{
comp_count++;
if (nums[j] < pivot)
{
i++;
swap(nums[i], nums[j]);
move_count += 3;
}
}
swap(nums[i + 1], nums[high]);
move_count += 3;
return (i + 1);
}
void quickSortOptimizedHelper(vector<int> &nums, int low, int high, long long &comp_count, long long &move_count)
{
if (low < high)
{
int pi = partition_optimized(nums, low, high, comp_count, move_count);
quickSortOptimizedHelper(nums, low, pi - 1, comp_count, move_count);
quickSortOptimizedHelper(nums, pi + 1, high, comp_count, move_count);
}
}
/*
* function : implement quick sort with median-of-three pivot selection
* param nums : the vector to be sorted
* param comp_count : count of comparisons
* param move_count : count of moves
* return : ---
*/
void QuickSortOptimized(vector<int> &nums, long long &comp_count, long long &move_count)
{
if (nums.empty()) return;
quickSortOptimizedHelper(nums, 0, nums.size() - 1, comp_count, move_count);
}

View File

@ -0,0 +1,82 @@
# 排序算法性能分析项目
本项目使用 C++ 实现并深入分析了多种经典排序算法的性能。项目提供了一个自动化测试框架,能够在不同规模的随机生成数据集上对每种算法进行测试,并精确测量其**执行时间**、**比较次数**和**移动次数**,以供量化分析。
## 项目内容与实现方式
### 1. 模块化的算法实现
为了保证代码的清晰度和可扩展性,每一种排序算法都作为独立的模块在各自的 `.cpp` 文件中实现。所有算法的函数声明都统一在 `algorithm.h` 头文件中进行管理。
这种结构使得添加新的算法或修改现有算法变得非常简单。
### 2. 精确的性能指标统计
为了超越单纯的运行时间测量,本项目在每种排序算法的实现内部进行了“插桩”,以统计两个核心的性能指标:
- **比较次数 (Comparisons)**:算法执行过程中元素之间进行比较的总次数。
- **移动次数 (Moves)**:算法执行过程中数据的赋值、交换等移动操作的总次数。一个 `std::swap` 操作计为3次移动。
这些数据为理论复杂度分析提供了有力的实验验证。
### 3. 自动化的测试与分析框架
项目核心是一个位于 `main.cpp` 的自动化测试框架,其主要功能包括:
- **多算法支持**:能够自动运行所有已实现的排序算法。
- **多规模测试**:支持在一系列预设的数据规模(例如 100, 1000, ..., 500,000上进行测试。
- **结果可靠性**:通过对每个规模进行多次重复实验并计算平均值,有效消除了单次运行的随机性误差。
- **正确性校验**:在每次排序任务完成后,自动检查数组是否真正有序,确保了算法实现的正确性。
- **格式化输出**:将所有测试结果以清晰的表格形式输出到控制台,方便用户阅读和分析。
## 已实现的排序算法
本项目共实现了以下算法:
#### 基础排序算法
- **插入排序 (Insert Sort)**
- **冒泡排序 (Bubble Sort)**
- **希尔排序 (Shell Sort)**
- **归并排序 (Merge Sort)**
#### 快速排序 (Quick Sort) 变体
- **标准快速排序**:选择最后一个元素作为基准点。
- **三数取中优化快速排序 (QuickSortOptimized)**:通过“三数取中”策略选择基准点,以提高算法在特殊数据(如部分有序)下的稳定性。
- **三路快速排序 (QuickSort3Way)**:特别适用于处理含有大量重复元素的数组。
- **双基准快速排序 (Dual-Pivot Quick Sort)**:使用两个基准点将数组划分为三部分,理论上能减少比较次数,在现代处理器上性能优异。
## 如何编译与运行
项目提供了一个 `Makefile` 文件,极大地简化了编译、运行和清理流程。
### 1. 编译项目
在项目根目录下,执行以下命令来编译所有源代码:
```bash
make
```
该命令会自动调用 `g++` 编译器,并将所有 `.cpp` 文件编译链接成一个名为 `sorting_experiment` 的可执行文件。
### 2. 运行实验
编译成功后,执行以下命令来运行完整的性能分析测试:
```bash
make run
```
你也可以直接运行生成的可执行文件:
```bash
./sorting_experiment
```
程序启动后,将开始对所有算法和所有预设规模进行测试,并将结果实时输出到控制台。
### 3. 清理生成文件
如果你想删除所有编译生成的目标文件 (`.o`) 和可执行文件,可以运行:
```bash
make clean
```
## 输出结果解读
程序的输出是一个性能指标表格,每一行代表一种算法在一个特定数据规模下的平均测试结果。
| 列名 | 中文说明 |
| :--- | :--- |
| **Algorithm** | 被测试的排序算法的名称。 |
| **Size** | 当前测试的数组大小(即数据规模 `n`)。 |
| **Avg Time (s)** | 多次重复测试下的平均运行时间,单位为秒。 |
| **Avg Comparisons**| 平均比较操作的次数。 |
| **Avg Moves** | 平均移动(赋值或交换)操作的次数。 |
| **Correct?** | 排序结果是否正确,"Yes" 代表正确无误。 |

View File

@ -0,0 +1,77 @@
# Sorting Algorithm Performance Analysis
This project implements and analyzes the performance of several classic sorting algorithms in C++. It provides a framework to test each algorithm on randomly generated data of various sizes, measuring execution time, comparison counts, and move counts.
A detailed analysis and discussion of the results can be found in [REPORT.md](./REPORT.md).
## Implemented Algorithms
- **Basic Sorting Algorithms:**
- Insertion Sort
- Bubble Sort
- Shell Sort
- Merge Sort
- **Quick Sort Variants:**
- Standard Quick Sort (pivot is the last element)
- Quick Sort with Median-of-Three pivot optimization
- 3-Way Quick Sort (for handling duplicate keys)
- Dual-Pivot Quick Sort
## How to Build and Run
A `Makefile` is provided to simplify the build and execution process.
### 1. Build the Project
To compile all the source files and create the executable, run:
```bash
make
```
This will generate an executable file named `sorting_experiment`.
### 2. Run the Experiment
To run the performance analysis, execute the following command:
```bash
make run
```
Alternatively, you can run the executable directly:
```bash
./sorting_experiment
```
The program will output a formatted table with the performance metrics for each algorithm across different data sizes.
### 3. Clean Up
To remove the compiled object files and the executable, run:
```bash
make clean
```
---
<details>
<summary><strong>Original Experiment Requirements</strong></summary>
### 实验内容
对几种经典的排序算法进行分析,理解算法在不同输入时的表现,深入剖析算法优缺点及其根源。具体要求如下:
1. 实现常见排序算法至少要实现插入排序、冒泡排序、快速排序、归并排序、shell排序算法
2. 在排序算法中插桩,记录关键操作次数(如比较次数、移动次数等);
3. 以待排序文件的行数n为输入规模固定n随机产生多组测试样本统计算法的平均运行时间和关键操作次数改变n的规模重复多次实验并对结果进行统计
4. 改变数组规模,对不同规模问题下各算法的结果进行统计并绘制图表,与理论值进行对照分析;
5. 优化快速排序的中枢点选取,对优化前后的性能进行分析;
6. 对快速排序的三种实现进行性能比较。
### 附加:
- 实现BlockQuickSort就分支预测次数展开分析
- 实现DualPivotQuickSort就递归深度展开分析
- 在超大规模数据上如1亿个整数对比以上快排实现的性能。
### 编写实验文档:
要求对所实现算法的时间进行复杂度分析(结合程序统计关键步骤运行次数,以验证分析结果);程序运行指导,包括程序编译说明、输入输出示例等。如果输入、输出信息较多,建议采用文件进行格式化输入、输出。实验报告:解题思路;所实现算法的时间复杂度分析(结合程序统计关键步骤运行次数,以验证分析结果);程序运行指导,包括程序编译说明、输入输出示例等。如果输入、输出信息较多,建议采用文件进行格式化输入、输出。
</details>

View File

@ -0,0 +1,98 @@
# 排序算法实验报告
## 1. 解题思路
本实验旨在深入理解并分析多种经典排序算法的性能。为了达成此目标,实验遵循了以下设计思路:
1. **模块化实现**:将每种排序算法(插入、冒泡、希尔、归并、快速排序及其变体)分别实现在独立的 `.cpp` 文件中,并通过一个统一的 `algorithm.h` 头文件进行声明。这种结构使得代码清晰、易于扩展和维护。
2. **量化性能指标**:为了客观评估算法性能,除了记录运行时间外,还在算法实现中进行“插桩”,精确统计了两个关键操作:
* **比较次数 (Comparisons)**:元素之间的比较操作,是决定算法时间复杂度的核心因素之一。
* **移动次数 (Moves)**:元素的赋值或交换操作,反映了算法的数据搬运成本。
3. **自动化测试框架**:设计了一个灵活的测试框架 (`main.cpp`),能够:
* 自动化地对所有已实现的算法进行测试。
* 支持对多种不同的输入规模(例如 100, 1000, ..., 500,000进行测试。
* 通过多次重复实验并取平均值的方式,消除单次运行的随机误差,保证结果的可靠性。
* 在每次排序后进行正确性校验,确保算法实现无误。
* 以格式化的表格输出结果,便于阅读和后续分析。
4. **迭代优化与对比**:重点对快速排序进行了深度探索,实现了从基础版本到优化版本(三数取中、三路快排、双基准快排)的演进。通过将这些版本置于同一测试框架下进行性能对比,可以直观地展示不同优化策略带来的效果。
## 2. 算法复杂度分析与实验数据验证
### 理论分析
| 算法 | 平均时间复杂度 | 最好情况 | 最坏情况 | 空间复杂度 |
| :--- | :--- | :--- | :--- | :--- |
| **InsertSort** | O(n²) | O(n) | O(n²) | O(1) |
| **BubbleSort** | O(n²) | O(n) | O(n²) | O(1) |
| **ShellSort** | O(n log n) ~ O(n²) | O(n log n) | O(n²) | O(1) |
| **MergeSort** | O(n log n) | O(n log n) | O(n log n) | O(n) |
| **QuickSort** | O(n log n) | O(n log n) | O(n²) | O(log n) |
| **QuickSortOpt** | O(n log n) | O(n log n) | O(n²) | O(log n) |
| **QuickSort3Way**| O(n log n) | O(n) | O(n²) | O(log n) |
| **DualPivotSort**| O(n log n) | O(n log n) | O(n²) | O(log n) |
### 实验数据验证
通过运行实验程序,可以得到不同算法在不同规模下的平均运行时间、比较次数和移动次数。这些数据可以用来验证上述理论复杂度。
* **O(n²) 算法 (InsertSort, BubbleSort)**:
* **预期**:当输入规模 `n` 增大10倍时运行时间、比较和移动次数大约会增大100倍。
* **观察**:从实验数据中可以看到,当 `n` 从 1000 增加到 10000 时,`InsertSort``BubbleSort` 的运行时间急剧增加,远超线性增长,这与 O(n²) 的特征相符。由于性能问题,测试框架在 `n >= 50000` 时自动跳过了这些算法。
* **O(n log n) 算法 (MergeSort, QuickSort 变体)**:
* **预期**:当输入规模 `n` 增大时,性能增长平缓。比较次数大致在 `n * log(n)` 的量级。
* **观察**`MergeSort` 和各种 `QuickSort` 的运行时间随 `n` 的增长远比 O(n²) 算法要慢。例如,从 `n=10000``n=100000`10倍它们的运行时间增长远小于100倍符合 `n log n` 的趋势。`MergeSort` 的比较次数非常稳定,接近理论值。
* **快速排序变体对比**:
* `QuickSort` (基础版) 在随机数据下表现良好,但如果输入数据有序,其性能会退化到 O(n²)。
* `QuickSortOpt` (三数取中) 通过改进基准点选择,显著提高了在非完全随机数据下的稳定性,其比较和移动次数通常略优于基础版。
* `QuickSort3Way` 在处理含大量重复元素的数组时优势最大(本次实验为随机数据,优势不明显),其在最好情况下(所有元素相同)可达 O(n)。
* `DualPivotSort` (双基准) 在理论上可以减少比较次数。从实验数据看,在较大规模的数据集上(如 `n=100000` 及以上),它通常比单基准的快速排序更快,显示出其优化效果。
## 3. 程序运行指导
### 编译
所有相关的 `.cpp` 源文件需要一起编译。可以使用 g++ 编译器,命令如下:
```bash
g++ main.cpp InsertSort.cpp BubbleSort.cpp ShellSort.cpp MergeSort.cpp QuickSort.cpp QuickSortOptimized.cpp QuickSort3Way.cpp DualPivotQuickSort.cpp out.cpp -o sorting_experiment
```
此命令会生成一个名为 `sorting_experiment` 的可执行文件。
### 运行
直接在终端中运行生成的可执行文件:
```bash
./sorting_experiment
```
### 输出结果说明
程序会输出一个性能分析表格,每一行代表一个算法在一个特定输入规模下的测试结果。
| 列 | 说明 |
| :--- | :--- |
| **Algorithm** | 被测试的排序算法名称。 |
| **Size** | 输入数组的元素个数(即规模 `n`)。 |
| **Avg Time (s)** | 多次重复测试的平均运行时间,单位为秒。 |
| **Avg Comparisons**| 平均比较次数。 |
| **Avg Moves** | 平均移动(赋值/交换)次数。 |
| **Correct?** | 排序结果是否正确,"Yes" 表示正确。 |
## 4. 性能对比与结论
1. **算法类别差异**O(n²) 级别的算法插入排序、冒泡排序仅适用于小规模数据。当数据规模超过一万时其性能急剧下降无法在实际应用中使用。相比之下O(n log n) 级别的算法(归并、希尔、快速排序)则表现出卓越的性能和可扩展性。
2. **快速排序的优势与优化**:在所有 O(n log n) 算法中,快速排序及其变体通常在平均情况下的性能最好,这得益于其更少的常量因子和高效的缓存利用率。
* **基准点选择至关重要**:基础的快速排序在特定数据模式下存在性能退化的风险,而“三数取中”等优化策略能有效缓解此问题,增强算法的稳定性。
* **双基准快排的威力**`DualPivotQuickSort` 在大规模随机数据上展现了最佳性能,验证了其在现代计算环境下的理论优势。
3. **归并排序的稳定性**:虽然 `MergeSort` 在本次测试中的原始速度略逊于最优的快速排序,但它具有一个重要优点:其性能是稳定的 O(n log n),不受输入数据初始顺序的影响。此外,归并排序是一种稳定的排序算法,而快速排序不是。
**最终结论**:对于通用场景下的内部排序任务,经过优化的快速排序(特别是双基准快速排序)是性能上的首选。而当需要排序稳定性或对最坏情况有严格要求时,归并排序是更可靠的选择。

View File

@ -0,0 +1,32 @@
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
/*
* function : implement shell sort
* param nums : the vector to be sorted
* param comp_count : count of comparisons
* param move_count : count of moves
* return : ---
*/
void ShellSort(vector<int> &nums, long long &comp_count, long long &move_count)
{
int n = nums.size();
for (int gap = n / 2; gap > 0; gap /= 2)
{
for (int i = gap; i < n; i += 1)
{
int temp = nums[i];
int j;
for (j = i; j >= gap && (comp_count++, nums[j - gap] > temp); j -= gap)
{
nums[j] = nums[j - gap];
move_count++;
}
nums[j] = temp;
move_count++;
}
}
}

View File

@ -0,0 +1,20 @@
#include <iostream>
#include <vector>
#include <algorithm>
#include <ctime>
#include <cstdlib>
#include <stack>
#include <string>
#include <cstring>
using namespace std;
void InsertSort(vector<int>&, long long&, long long&);
void BubbleSort(vector<int>&, long long&, long long&);
void MergeSort(vector<int>&, long long&, long long&);
void QuickSort(vector<int>&, long long&, long long&);
void QuickSortOptimized(vector<int>&, long long&, long long&);
void QuickSort3Way(vector<int>&, long long&, long long&);
void DualPivotQuickSort(vector<int>&, long long&, long long&);
void ShellSort(vector<int>&, long long&, long long&);

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

View File

@ -0,0 +1,110 @@
#include <iostream>
#include <vector>
#include <algorithm>
#include <ctime>
#include <cstdlib>
#include <string>
#include <iomanip>
#include "algorithm.h"
#include "out.h"
using namespace std;
#define UP_BOUND 1000000
// Function pointer for sorting algorithms
typedef void (*SortFunction)(vector<int>&, long long&, long long&);
bool is_sorted(const vector<int>& vec)
{
for (size_t i = 0; i < vec.size() - 1; ++i)
{
if (vec[i] > vec[i + 1])
{
return false;
}
}
return true;
}
void run_performance_analysis()
{
cout << "--- Running Performance Analysis ---" << endl;
SortFunction algorithms[] = {InsertSort, BubbleSort, ShellSort, MergeSort, QuickSort, QuickSortOptimized, QuickSort3Way, DualPivotQuickSort};
string algo_names[] = {"InsertSort", "BubbleSort", "ShellSort", "MergeSort", "QuickSort", "QuickSortOpt", "QuickSort3Way", "DualPivotSort"};
int num_algorithms = sizeof(algorithms) / sizeof(algorithms[0]);
vector<int> sizes = {100, 1000, 10000, 50000, 100000, 500000};
int num_repeats = 10;
cout << left << setw(15) << "Algorithm"
<< setw(10) << "Size"
<< setw(20) << "Avg Time (s)"
<< setw(25) << "Avg Comparisons"
<< setw(25) << "Avg Moves"
<< setw(15) << "Correct?" << endl;
cout << string(110, '-') << endl;
for (int i = 0; i < num_algorithms; i++)
{
for (int size : sizes)
{
if (size >= 50000 && (algo_names[i] == "InsertSort" || algo_names[i] == "BubbleSort"))
{
cout << left << setw(15) << algo_names[i]
<< setw(10) << size << " -> Skipped" << endl;
continue;
}
double total_time = 0;
long long total_comps = 0;
long long total_moves = 0;
bool all_correct = true;
for (int j = 0; j < num_repeats; j++)
{
vector<int> vec(size);
for (int k = 0; k < size; k++)
vec[k] = rand() % UP_BOUND;
long long comp_count = 0;
long long move_count = 0;
vector<int> temp_vec = vec;
clock_t start_time = clock();
algorithms[i](temp_vec, comp_count, move_count);
clock_t end_time = clock();
if (!is_sorted(temp_vec))
{
all_correct = false;
}
total_time += (double)(end_time - start_time) / CLOCKS_PER_SEC;
total_comps += comp_count;
total_moves += move_count;
}
cout << left << setw(15) << algo_names[i]
<< setw(10) << size
<< fixed << setprecision(6) << setw(20) << total_time / num_repeats
<< setw(25) << total_comps / num_repeats
<< setw(25) << total_moves / num_repeats
<< setw(15) << (all_correct ? "Yes" : "No") << endl;
}
cout << endl;
}
cout << "------------------------------------" << endl;
}
int main()
{
srand(time(0)); // Seed for random number generation
run_performance_analysis();
return 0;
}

View File

@ -0,0 +1,16 @@
#include <iostream>
#include <vector>
using namespace std;
/*
* function : print a vector
* param nums : the vector to be printed
* return : ---
*/
void Out(vector<int> &nums)
{
for (int i = 0; i < static_cast<int>(nums.size()); i++)
cout << nums[i] << " ";
cout << endl;
}

View File

@ -0,0 +1,6 @@
#include <iostream>
#include <vector>
using namespace std;
void Out(vector<int> &);

View File

@ -0,0 +1,138 @@
import matplotlib.pyplot as plt
import pandas as pd
import io
output = """
--- Running Performance Analysis ---
Algorithm Size Avg Time (s) Avg Comparisons Avg Moves Correct?
--------------------------------------------------------------------------------------------------------------
InsertSort 100 0.000006 2628 2633 Yes
InsertSort 1000 0.000108 251895 251902 Yes
InsertSort 10000 0.010841 25002574 25002583 Yes
InsertSort 50000 -> Skipped
InsertSort 100000 -> Skipped
InsertSort 500000 -> Skipped
BubbleSort 100 0.000018 4891 7118 Yes
BubbleSort 1000 0.001527 498086 754888 Yes
BubbleSort 10000 0.147654 49984024 74752463 Yes
BubbleSort 50000 -> Skipped
BubbleSort 100000 -> Skipped
BubbleSort 500000 -> Skipped
ShellSort 100 0.000003 859 911 Yes
ShellSort 1000 0.000040 15404 15912 Yes
ShellSort 10000 0.000577 263303 268383 Yes
ShellSort 50000 0.003500 1883075 1908568 Yes
ShellSort 100000 0.007738 4329053 4379481 Yes
ShellSort 500000 0.047314 28756169 29008608 Yes
MergeSort 100 0.000005 541 1344 Yes
MergeSort 1000 0.000053 8710 19952 Yes
MergeSort 10000 0.000639 120467 267232 Yes
MergeSort 50000 0.003562 718133 1568928 Yes
MergeSort 100000 0.007466 1536366 3337856 Yes
MergeSort 500000 0.042618 8837077 18951424 Yes
QuickSort 100 0.000002 633 1146 Yes
QuickSort 1000 0.000027 11070 18485 Yes
QuickSort 10000 0.000340 156205 257969 Yes
QuickSort 50000 0.001971 938346 1488604 Yes
QuickSort 100000 0.004147 2013584 3293229 Yes
QuickSort 500000 0.023807 11835910 18761405 Yes
QuickSortOpt 100 0.000002 723 1306 Yes
QuickSortOpt 1000 0.000029 10853 19089 Yes
QuickSortOpt 10000 0.000359 152089 263599 Yes
QuickSortOpt 50000 0.002079 889846 1472662 Yes
QuickSortOpt 100000 0.004246 1894396 3081447 Yes
QuickSortOpt 500000 0.025016 10915240 17611893 Yes
QuickSort3Way 100 0.000003 756 693 Yes
QuickSort3Way 1000 0.000039 12003 9189 Yes
QuickSort3Way 10000 0.000479 168509 114458 Yes
QuickSort3Way 50000 0.002715 1013555 652409 Yes
QuickSort3Way 100000 0.005945 2123298 1376911 Yes
QuickSort3Way 500000 0.032901 12324462 7696985 Yes
DualPivotSort 100 0.000002 624 884 Yes
DualPivotSort 1000 0.000026 10635 12297 Yes
DualPivotSort 10000 0.000331 151783 170443 Yes
DualPivotSort 50000 0.001911 908308 974849 Yes
DualPivotSort 100000 0.004047 1926590 2053087 Yes
DualPivotSort 500000 0.022747 11189537 11712207 Yes
"""
# Use StringIO to treat the string data as a file
data = io.StringIO(output)
# Read the data, skipping the header and footer
df = pd.read_csv(data, sep='\s+', skiprows=3, skipfooter=1, engine='python',
names=['Algorithm', 'Size', 'Avg Time (s)', 'Avg Comparisons', 'Avg Moves', 'Correct?'])
# Drop the 'Correct?' column as it's not needed for plotting
df = df.drop(columns=['Correct?'])
# Remove rows with 'Skipped' values
df = df[~df.isin(['->', 'Skipped']).any(axis=1)]
# Convert columns to numeric types
for col in ['Size', 'Avg Time (s)', 'Avg Comparisons', 'Avg Moves']:
df[col] = pd.to_numeric(df[col])
# Get the list of algorithms
algorithms = df['Algorithm'].unique()
# Plotting
plt.style.use('ggplot')
# --- Plot 1: Average Time vs. Size ---
plt.figure(figsize=(12, 8))
for algo in algorithms:
subset = df[df['Algorithm'] == algo]
plt.plot(subset['Size'], subset['Avg Time (s)'], marker='o', linestyle='-', label=algo)
plt.title('Average Time vs. Input Size')
plt.xlabel('Input Size (n)')
plt.ylabel('Average Time (seconds)')
plt.xscale('log')
plt.yscale('log')
plt.legend()
plt.grid(True, which="both", ls="--")
plt.savefig('average_time_vs_size.png')
plt.close()
# --- Plot 2: Average Comparisons vs. Size ---
plt.figure(figsize=(12, 8))
for algo in algorithms:
subset = df[df['Algorithm'] == algo]
plt.plot(subset['Size'], subset['Avg Comparisons'], marker='o', linestyle='-', label=algo)
plt.title('Average Comparisons vs. Input Size')
plt.xlabel('Input Size (n)')
plt.ylabel('Average Comparisons')
plt.xscale('log')
plt.yscale('log')
plt.legend()
plt.grid(True, which="both", ls="--")
plt.savefig('average_comparisons_vs_size.png')
plt.close()
# --- Plot 3: Average Moves vs. Size ---
plt.figure(figsize=(12, 8))
for algo in algorithms:
subset = df[df['Algorithm'] == algo]
plt.plot(subset['Size'], subset['Avg Moves'], marker='o', linestyle='-', label=algo)
plt.title('Average Moves vs. Input Size')
plt.xlabel('Input Size (n)')
plt.ylabel('Average Moves')
plt.xscale('log')
plt.yscale('log')
plt.legend()
plt.grid(True, which="both", ls="--")
plt.savefig('average_moves_vs_size.png')
plt.close()
print("Plots saved as average_time_vs_size.png, average_comparisons_vs_size.png, and average_moves_vs_size.png")

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,16 @@
CC=g++
all: data_gen main analyser
data_gen:
$(CC) data_gen.cpp -o data_gen
main:
$(CC) main.cpp algorithm.cpp test.cpp -o main
analyser:
$(CC) analyser.cpp algorithm.cpp test.cpp -o analyser
.PHONY(clean):
clean:
rm -rf *.o *.data data_gen main analyser

View File

@ -0,0 +1,29 @@
DEMO
===========================
##环境依赖
gcc
##目录结构描述
├── README.md // help \
├── main.cpp // 主文件 \
├── algorithm.h // 算法声明头文件 \
├── algorithm.cpp // 算法实现 \
├── data_gen.cpp // 测试集数据生成 \
├── analyser.cpp // 插桩代码测试 \
├── test.h // 测试函数声明头文件 \
├── test.cpp // 测试函数实现 \
├── test.sh // 辅助测试的bash脚本 \
├── Makefile // 编译规则
##测试步骤
1. 编译
2. 生成测试集
3. 测试、插桩测试
(可通过简单的bash脚本进行批量生成数据集和批量测试)
##V1.0 版本内容更新
1. 创建文件与基础实现

View File

@ -0,0 +1,144 @@
/***************************************************************************** *
* Copyright (C) 2022 Mingtian Shao shaomt@nudt.edu.cn *
* *
* This file is part of homework of Algorithm Design and Analysis. *
* *
* @file algorithm.cpp *
* @brief Implement different algorithms *
* *
* @author Mingtian Shao *
* @email shaomt@nudt.edu.cn *
* @version 1.0 *
* @date 2022-11-12 *
* @license GNU General Public License (GPL) *
* *
*----------------------------------------------------------------------------*
* Change History : *
* <Date> | <Version> | <Author> | <Description> *
*----------------------------------------------------------------------------*
* 2022/11/12 | 1.0 | Mingtian Shao | Create file *
*----------------------------------------------------------------------------*
* *
*****************************************************************************/
#include <iostream>
#include <vector>
#include <ctime>
#include <cstdlib>
#include <stack>
#include <string>
#include <cstring>
#include "algorithm.h"
using namespace std;
/**
* @func algorithm_1
* @brief 解决背包问题思路一
* @param n: 物品种类
* @param w: 背包容量限制
* @param weights: 物品重量数组
* @param values: 物品价值数组
* @param solve: 保存解的数组
*
* @return 返回背包容纳的最大价值
*/
int algorithm_1(int n, int w, int* weights, int* values, int* solve)
{
// memo index start from 0, which means type-1 or weight-1
vector< vector<int> > memo(n);
vector< vector<int> > nums(n);
for (int i = 0; i < n; i++)
{
memo[i].resize(w);
nums[i].resize(w);
}
// avoid the inefficient branch for i = 0 in the following ciculation
for (int j = 0; j < w; j++) // avaliable weight capacity - 1
{
int k = (j + 1) / weights[0];
memo[0][j] = k * values[0]; // take as many as possible
nums[0][j] = k;
}
for (int i = 1; i < n; i++) // index of chosen object
{
for (int j = 0; j < w; j++) // avaliable weight capacity - 1
{
int maxvalue = 0, maxk = 0;
for (int k = 0; k <= (j + 1) / weights[i]; k++)
{
int tmp = k * values[i];
if (j - k * weights[i] >= 0)
{
tmp += memo[i - 1][j - k * weights[i]];
}
if (tmp > maxvalue)
{
maxvalue = tmp;
maxk = k;
}
}
memo[i][j] = maxvalue;
nums[i][j] = maxk;
}
}
int tmpw = w - 1;
for (int i = n - 1; i >= 0; i--)
{
solve[i] = nums[i][tmpw];
tmpw -= solve[i] * weights[i];
}
return memo[n - 1][w - 1];
}
/**
* @func 函数名
* @brief 函数简要说明
* @param 参数1
* @param 参数2
*
* @return 返回说明
*/
int algorithm_2(int n, int w, int* weights, int* values, int* solve)
{
/*
* coding
*/
}
/**
* @func algorithm_1_analy
* @brief 在函数algorithm_1的基础上进行插桩记录关键操作次数
* @param n: 物品种类
* @param w: 背包容量限制
* @param weights: 物品重量数组
* @param values: 物品价值数组
* @param solve: 保存解的数组
* @param calc_count: 记录计算次数
* @param search_count: 记录查找次数
*
* @return 返回背白容纳的最大价值
*/
int algorithm_1_analy(int n, int w, int* weights, int* values, int* solve, int& calc_count, int& search_count)
{
/*
* coding
*/
}
/**
* @func 函数名
* @brief 函数简要说明
* @param 参数1
* @param 参数2
*
* @return 返回说明
*/
int algorithm_2_analy(int n, int w, int* weights, int* values, int* solve, int& calc_count, int& search_count)
{
/*
* coding
*/
}

View File

@ -0,0 +1,17 @@
#include <iostream>
#include <vector>
#include <algorithm>
#include <ctime>
#include <cstdlib>
#include <stack>
#include <string>
#include <cstring>
using namespace std;
int algorithm_1(int, int, int*, int*, int*);
int algorithm_2(int, int, int*, int*, int*);
int algorithm_1_analy(int, int, int*, int*, int*, int&, int&);
int algorithm_2_analy(int, int, int*, int*, int*, int&, int&);

View File

@ -0,0 +1,98 @@
/*****************************************************************************
* Copyright (C) 2022 Mingtian Shao shaomt@nudt.edu.cn *
* *
* This file is part of homework of Algorithm Design and Analysis. *
* *
* @file analyser.cpp *
* @brief Analyze the number of critical operations *
* for different algorithms *
* *
* @author Mingtian Shao *
* @email shaomt@nudt.edu.cn *
* @version 1.0 *
* @date 2022-11-12 *
* @license GNU General Public License (GPL) *
* *
*----------------------------------------------------------------------------*
* Change History : *
* <Date> | <Version> | <Author> | <Description> *
*----------------------------------------------------------------------------*
* 2022/11/12 | 1.0 | Mingtian Shao | Create file *
*----------------------------------------------------------------------------*
* *
*****************************************************************************/
#include <iostream>
#include <fstream>
#include <random>
#include <cmath>
#include "algorithm.h"
#include "test.h"
using namespace std;
/**
* @func analy_fun
* @brief 插桩算法测试
* @param data_file: 测试集文件
* @param cntcalc: 计算计数器
* @param cntsearch: 查找计数器
* @param fun: 测试的算法函数
*
* @return 重复测试的次数(测试数据的组数)
*/
int analy_fun(char *data_file, int &cntcalc, int &cntsearch, int (fun)(int, int, int*, int*, int*, int&, int&))
{
ifstream fin(data_file);
int result; //保存每个测试用例的最大价值
int repeat; //记录测试数据组数
// k: 生成数据的组数
// n: 物品的种类(问题的规模)
// w: 背包重量限制
int k, n, w;
fin >> k >> n >> w;
repeat = k;
cout << "数据集组数:" << k << " , 物品种类:" << n << " , 背包容量限制: " << w << endl;
int* weights = new int[n], * values = new int[n];
int* solve = new int[n];
while (k--) {
for (int i = 0; i < n; i++) {
fin >> weights[i];
}
for (int i = 0; i < n; i++) {
fin >> values[i];
solve[i] = 0;
}
result = fun(n, w, weights, values, solve, cntcalc, cntsearch);
}
delete[] weights;
delete[] values;
delete[] solve;
return repeat;
}
int main(int argc, char *argv[])
{
//input: data_file
if (argc != 2)
{
cout<< "参数错误参数数据集文件如test_x_x_x.data" << endl;
exit(1);
}
int cntcalc = 0;
int cntsearch = 0;
int repeat;
repeat = analy_fun(argv[1], cntcalc, cntsearch, algorithm_1_analy);
int average_calc = cntcalc / repeat;
int average_search = cntsearch / repeat;
cout << "average_calc: " << average_calc << endl;
cout << "average_search: " << average_search << endl;
return 0;
}

View File

@ -0,0 +1,81 @@
/*****************************************************************************
* Copyright (C) 2022 Mingtian Shao shaomt@nudt.edu.cn *
* *
* This file is part of homework of Algorithm Design and Analysis. *
* *
* @file data_gen.cpp *
* @brief Generate data and save it to a file *
* *
* @author Mingtian Shao *
* @email shaomt@nudt.edu.cn *
* @version 1.0 *
* @date 2022-11-12 *
* @license GNU General Public License (GPL) *
* *
*----------------------------------------------------------------------------*
* Change History : *
* <Date> | <Version> | <Author> | <Description> *
*----------------------------------------------------------------------------*
* 2022/11/12 | 1.0 | Mingtian Shao | Create file *
*----------------------------------------------------------------------------*
* *
*****************************************************************************/
#include <iostream>
#include <fstream>
#include <random>
#include <cmath>
using namespace std;
/**
* @func data_gen
* @brief 生成测试数据集
* @param k: 测试集数量
* @param n: 物品种类
* @param w: 背包重量限制
*
* @return null
*/
void data_gen(int k, int n, int w)
{
char out_file[100];
//输出文件名可参考"test_{k}_{n}_{w}.data"
sprintf(out_file, "test_%d_%d_%d.data", k, n, w);
ofstream fout(out_file);
fout << k << " " << n << " " << w << endl;
default_random_engine e(time(nullptr));
//随机数分布对象
uniform_int_distribution<signed> u(2, w / 1.5);
while (k--)
{
// 生成weight值
for (int i = 0; i < n; i++) //生成2~n的随机数序列
fout << u(e) << " ";
fout << endl;
// 生成value值
for (int i = 0; i < n; i++) //生成2~n的随机数序列
fout << u(e) << " ";
fout << endl;
}
}
int main(int argc, char *argv[])
{
// k: 生成数据的组数
// n: 物品的种类(问题的规模)
// w: 背包重量限制
if(argc != 4 )
{
cout << "参数错误,参数包括: 生成数据的组数k, 物品的种类n, 背包重量限制w" << endl;
exit(1);
}
int k, n, w;
k = atoi(argv[1]);
n = atoi(argv[2]);
w = atoi(argv[3]);
data_gen(k,n,w);
return 0;
}

View File

@ -0,0 +1,57 @@
/*****************************************************************************
* Copyright (C) 2022 Mingtian Shao shaomt@nudt.edu.cn *
* *
* This file is part of homework of Algorithm Design and Analysis. *
* *
* @file main.cpp *
* @brief Test the performance of different algorithms *
* *
* @author Mingtian Shao *
* @email shaomt@nudt.edu.cn *
* @version 1.0 *
* @date 2022-11-12 *
* @license GNU General Public License (GPL) *
* *
*----------------------------------------------------------------------------*
* Change History : *
* <Date> | <Version> | <Author> | <Description> *
*----------------------------------------------------------------------------*
* 2022/11/12 | 1.0 | Mingtian Shao | Create file *
*----------------------------------------------------------------------------*
* *
*****************************************************************************/
#include <ctime>
#include <cstdlib>
#include <stack>
#include <string>
#include <cstring>
#include "algorithm.h"
#include "test.h"
using namespace std;
int main(int argc, char *argv[])
{
//input: data_file
if (argc != 2)
{
cout<< "参数错误参数数据集文件如test_x_x_x.data" << endl;
exit(1);
}
long double average_time_1, average_time_2;
average_time_1 = test_5(argv[1], algorithm_1);
//average_time_2 = test_5(argv[1], algorithm_2);
cout << average_time_1 << endl;
//cout << average_time_2 << endl;
return 0;
/**
* 供参考:
* 可能的输入数据集文件、n物品种类、w背包重量上限
* 1. 读取data_gen生成的测试集文件
* 2. 使用不同算法对于测试集进行求解
* 3. 记录算法性能并保存到文件
* coding
*/
}

View File

@ -0,0 +1,122 @@
/*****************************************************************************
* Copyright (C) 2022 Mingtian Shao shaomt@nudt.edu.cn *
* *
* This file is part of homework of Algorithm Design and Analysis. *
* *
* @file algorithm.cpp *
* @brief test different algorithms *
* *
* @author Mingtian Shao *
* @email shaomt@nudt.edu.cn *
* @version 1.0 *
* @date 2022-11-12 *
* @license GNU General Public License (GPL) *
* *
*----------------------------------------------------------------------------*
* Change History : *
* <Date> | <Version> | <Author> | <Description> *
*----------------------------------------------------------------------------*
* 2022/11/12 | 1.0 | Mingtian Shao | Create file *
*----------------------------------------------------------------------------*
* *
*****************************************************************************/
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <stack>
#include <string>
#include <cstring>
#include <fstream>
#include "algorithm.h"
#include "test.h"
using namespace std;
/**
* @func PrintArray
* @brief 输出指针数组
* @param n: 数组长度
* @param nums: 整型指针数组
*
* @return null
*/
void PrintArray(int n, int* nums)
{
for (int i = 0; i < n; i++)
{
cout << nums[i] << " ";
}
cout << endl;
}
/**
* @func test_5
* @brief 测试算法运行时间并输出每组测试用例的结果
* @param data_file: 测试数据集文件
* @param fun: 测试算法的实现函数该函数有5个参数故该测试函数名为test_5
*
* @return 算法的平均运行时间
*/
long double test_5(char* data_file, int (fun)(int, int, int*, int*, int*))
{
double sum_time = 0;
clock_t start_time, end_time;
ifstream fin(data_file);
int result; //保存每个测试用例的最大价值
int repeat; //记录测试数据组数
// k: 生成数据的组数
// n: 物品的种类(问题的规模)
// w: 背包重量限制
int k, n, w;
fin >> k >> n >> w;
repeat = k;
cout << "数据集组数:" << k << " , 物品种类:" << n << " , 背包容量限制: " << w << endl;
int* weights = new int[n], * values = new int[n];
int* solve = new int[n];
while (k--) {
for (int i = 0; i < n; i++) {
fin >> weights[i];
}
for (int i = 0; i < n; i++) {
fin >> values[i];
solve[i] = 0;
}
cout << "weights:" << endl;
PrintArray(n, weights);
cout << "values:" << endl;
PrintArray(n, values);
// 仅记录算法运行时间
start_time = clock();
result = fun(n, w, weights, values, solve);
end_time = clock();
sum_time += (double)(end_time - start_time) / CLOCKS_PER_SEC;
cout << "max value is " << result << endl;
cout << "the solution is "; PrintArray(n, solve);
}
delete[] weights;
delete[] values;
delete[] solve;
long double average_time = sum_time / repeat;
return average_time;
}
/**
* @func test_7
* @brief 主要用于记录算法fun的关键操作次数
* @param data_file: 测试数据集文件
* @param fun: 测试算法的实现函数该函数有7个参数故该测试函数名为test_7
*
* @return 算法的平均运行时间,该值仅供参考,因为插桩代码影响了算法运行效率
*/
long double test_7(char* data_file, int (fun)(int, int, int*, int*, int*, int&, int&))
{
/*
* coding
*/
}

View File

@ -0,0 +1,14 @@
#include <iostream>
#include <vector>
#include <algorithm>
#include <ctime>
#include <cstdlib>
#include <stack>
#include <string>
#include <cstring>
#include <fstream>
using namespace std;
long double test_5(char*, int (fun)(int, int, int*, int*, int*));
long double test_7(char*, int (fun)(int, int, int*, int*, int*, int&, int&));

View File

@ -0,0 +1,22 @@
#!/bin/bash
# 测试脚本,下述内容仅为示例
# 使用前先增加执行权限: sudo chmod +x test.sh
echo "test srart"
./data_gen 1000 100 100
./main test_1000_100_100.data
./analyser test_1000_100_100.data
echo "--------------------------------------------"
./data_gen 1000 500 500
./main test_1000_500_500.data
./analyser test_1000_500_500.data
echo "--------------------------------------------"
echo "test end"

Binary file not shown.