first commit
This commit is contained in:
35
sort_closet/code-sorting/BubbleSort.cpp
Normal file
35
sort_closet/code-sorting/BubbleSort.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
67
sort_closet/code-sorting/DualPivotQuickSort.cpp
Normal file
67
sort_closet/code-sorting/DualPivotQuickSort.cpp
Normal 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);
|
||||
}
|
||||
33
sort_closet/code-sorting/InsertSort.cpp
Normal file
33
sort_closet/code-sorting/InsertSort.cpp
Normal 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++;
|
||||
}
|
||||
}
|
||||
36
sort_closet/code-sorting/Makefile
Normal file
36
sort_closet/code-sorting/Makefile
Normal 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
|
||||
86
sort_closet/code-sorting/MergeSort.cpp
Normal file
86
sort_closet/code-sorting/MergeSort.cpp
Normal 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);
|
||||
}
|
||||
48
sort_closet/code-sorting/QuickSort.cpp
Normal file
48
sort_closet/code-sorting/QuickSort.cpp
Normal 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);
|
||||
}
|
||||
70
sort_closet/code-sorting/QuickSort3Way.cpp
Normal file
70
sort_closet/code-sorting/QuickSort3Way.cpp
Normal 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);
|
||||
}
|
||||
81
sort_closet/code-sorting/QuickSortOptimized.cpp
Normal file
81
sort_closet/code-sorting/QuickSortOptimized.cpp
Normal 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);
|
||||
}
|
||||
82
sort_closet/code-sorting/README-zh.md
Normal file
82
sort_closet/code-sorting/README-zh.md
Normal 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" 代表正确无误。 |
|
||||
77
sort_closet/code-sorting/README.md
Normal file
77
sort_closet/code-sorting/README.md
Normal 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>
|
||||
98
sort_closet/code-sorting/REPORT.md
Normal file
98
sort_closet/code-sorting/REPORT.md
Normal 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),不受输入数据初始顺序的影响。此外,归并排序是一种稳定的排序算法,而快速排序不是。
|
||||
|
||||
**最终结论**:对于通用场景下的内部排序任务,经过优化的快速排序(特别是双基准快速排序)是性能上的首选。而当需要排序稳定性或对最坏情况有严格要求时,归并排序是更可靠的选择。
|
||||
32
sort_closet/code-sorting/ShellSort.cpp
Normal file
32
sort_closet/code-sorting/ShellSort.cpp
Normal 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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
20
sort_closet/code-sorting/algorithm.h
Normal file
20
sort_closet/code-sorting/algorithm.h
Normal 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&);
|
||||
|
||||
BIN
sort_closet/code-sorting/average_comparisons_vs_size.png
Normal file
BIN
sort_closet/code-sorting/average_comparisons_vs_size.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 154 KiB |
BIN
sort_closet/code-sorting/average_moves_vs_size.png
Normal file
BIN
sort_closet/code-sorting/average_moves_vs_size.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 152 KiB |
BIN
sort_closet/code-sorting/average_time_vs_size.png
Normal file
BIN
sort_closet/code-sorting/average_time_vs_size.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 147 KiB |
110
sort_closet/code-sorting/main.cpp
Normal file
110
sort_closet/code-sorting/main.cpp
Normal 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;
|
||||
}
|
||||
16
sort_closet/code-sorting/out.cpp
Normal file
16
sort_closet/code-sorting/out.cpp
Normal 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;
|
||||
}
|
||||
6
sort_closet/code-sorting/out.h
Normal file
6
sort_closet/code-sorting/out.h
Normal file
@ -0,0 +1,6 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
void Out(vector<int> &);
|
||||
138
sort_closet/code-sorting/plot_results.py
Normal file
138
sort_closet/code-sorting/plot_results.py
Normal 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")
|
||||
BIN
sort_closet/code-sorting/实验一-C.zip
Normal file
BIN
sort_closet/code-sorting/实验一-C.zip
Normal file
Binary file not shown.
BIN
sort_closet/code-sorting/实验一-c.docx
Normal file
BIN
sort_closet/code-sorting/实验一-c.docx
Normal file
Binary file not shown.
BIN
sort_closet/code_template-DP.tar
Normal file
BIN
sort_closet/code_template-DP.tar
Normal file
Binary file not shown.
16
sort_closet/code_template-DP/Makefile
Executable file
16
sort_closet/code_template-DP/Makefile
Executable 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
|
||||
29
sort_closet/code_template-DP/README.md
Executable file
29
sort_closet/code_template-DP/README.md
Executable 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. 创建文件与基础实现
|
||||
144
sort_closet/code_template-DP/algorithm.cpp
Executable file
144
sort_closet/code_template-DP/algorithm.cpp
Executable 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
|
||||
*/
|
||||
}
|
||||
17
sort_closet/code_template-DP/algorithm.h
Executable file
17
sort_closet/code_template-DP/algorithm.h
Executable 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&);
|
||||
|
||||
98
sort_closet/code_template-DP/analyser.cpp
Executable file
98
sort_closet/code_template-DP/analyser.cpp
Executable 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;
|
||||
}
|
||||
81
sort_closet/code_template-DP/data_gen.cpp
Executable file
81
sort_closet/code_template-DP/data_gen.cpp
Executable 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;
|
||||
}
|
||||
57
sort_closet/code_template-DP/main.cpp
Executable file
57
sort_closet/code_template-DP/main.cpp
Executable 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
|
||||
*/
|
||||
}
|
||||
122
sort_closet/code_template-DP/test.cpp
Executable file
122
sort_closet/code_template-DP/test.cpp
Executable 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
|
||||
*/
|
||||
}
|
||||
14
sort_closet/code_template-DP/test.h
Executable file
14
sort_closet/code_template-DP/test.h
Executable 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&));
|
||||
22
sort_closet/code_template-DP/test.sh
Executable file
22
sort_closet/code_template-DP/test.sh
Executable 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"
|
||||
|
||||
|
||||
|
||||
|
||||
BIN
sort_closet/code_template-sorting.zip
Normal file
BIN
sort_closet/code_template-sorting.zip
Normal file
Binary file not shown.
BIN
sort_closet/实验报告模板-提交时重命名为“实验x-编程语言”.docx
Normal file
BIN
sort_closet/实验报告模板-提交时重命名为“实验x-编程语言”.docx
Normal file
Binary file not shown.
Reference in New Issue
Block a user