后续可能会更新作业的ppt以及其他要求,可直接拿去交作业
代码展示
#include <algorithm>
#include <iostream>
#include <random>
#include <vector>
using namespace std;
// 关键字参加的交换次数
long long comparison_times = 0;
// 关键字参加的移动次数
long long move_times = 0;
// 随机数生成器,生成int范围内的整数
std::random_device seed;
std::default_random_engine engine{ seed() };
std::uniform_int_distribution<int> dis(INT_MIN, INT_MAX);
// 排序算法 - 冒泡排序,
// 通过相邻元素的比较和交换,在每一轮使一个元素移动到正确的位置。
// 时间复杂度O(n^2)
// 总体来说,选择排序每次交换都是使得最小值移至最前,效率略高一点。冒泡排序每次比较都可能发生交换,效率略低。
void bubbling_sort(vector<int>& arr) {
for (int i = 0; i < arr.size(); ++i) {
for (int j = 1; j < arr.size() - i; ++j) {
++comparison_times;
if (arr[j] < arr[j - 1]) {
swap(arr[j], arr[j - 1]);
move_times += 3;
}
}
}
}
// 排序算法 - 简单选择排序
// 每一轮从未排序的元素中选出最小的元素,使其移动到已排序的序列的末尾。
// 时间复杂度O(n^2)
void simple_selection_sort(vector<int>& arr) {
for (int i = 0; i < arr.size(); ++i) {
int min_index = i;
for (int j = i; j < arr.size(); ++j) {
++comparison_times;
if (arr[min_index] > arr[j]) {
min_index = j;
}
}
swap(arr[min_index], arr[i]);
move_times += 3;
}
}
// 排序算法 - 快速排序算法
void quick_sort(vector<int>& arr, int left, int right) {
// 递归终止条件:区间只有0或1个元素,已然有序,无需继续划分
if (right - left < 1) {
return;
}
// 随机选取一个数作为基准数Pivot
int index = left + rand() % (right - left + 1);
int pivot = arr[index];
// 初始化左右指针lt和gt,cnt用于遍历,lt表示小于pivot的最后一个元素,gt表示大于pivot的第一个元素
int lt = left;
int gt = right;
int cnt = left;
// 遍历数组,进行三向切分
while (cnt <= gt) {
// 当前元素小于pivot,则交换至左指针lt处,lt和cnt同时右移
++comparison_times;
if (arr[cnt] < pivot) {
swap(arr[cnt++], arr[lt++]);
move_times += 3;
}
// 当前元素大于pivot,则交换至右指针gt处,gt左移
else if (arr[cnt] > pivot) {
swap(arr[gt--], arr[cnt]);
move_times += 3;
}
// 等于pivot,直接跳过
else {
++cnt;
}
}
// 递归调用,继续对左右两部分进行快速排序
quick_sort(arr, left, lt - 1);
quick_sort(arr, gt + 1, right);
}
// 排序算法 - 简单插入排序
void simple_insertion_sort(vector<int>& arr) {
for (int i = 1; i < arr.size(); ++i) {
for (int j = i - 1; j >= 0; --j) {
++comparison_times;
if (arr[j + 1] < arr[j]) {
move_times += 3;
swap(arr[j + 1], arr[j]);
}
else {
break;
}
}
}
}
// 排序算法 - 希尔排序
// 是插入排序的一种优化版本。它通过间隔为h的增量来比较并交换相隔h个元素,采用递减的h值,最终当h=1时,变成普通的插入排序。
// 时间复杂度O(nlogn)
void shell_sort(vector<int>& arr) {
int h = 1;
while (h < arr.size() / 3) {
h = 3 * h + 1; // 确定初始步长h
}
while (h >= 1) {
for (int i = h; i < arr.size(); i++) {
int j = i;
int temp = arr[i];
while (j >= h && arr[j - h] > temp && ++comparison_times) {
++move_times;
arr[j] = arr[j - h];
j -= h;
}
++move_times;
arr[j] = temp;
}
h /= 3; // 步长缩小
}
}
// 排序算法 - 堆排序,利用堆结构(可看成完全二叉树)的特点实现排序。
// 时间复杂度O(nlogn)
void heapify(vector<int>& arr, int n, int i) {
int largest = i; // 目前最大值的索引
int l = 2 * i + 1; // 左子节点索引
int r = 2 * i + 2; // 右子节点索引
comparison_times += 2;
if (l < n && arr[l] > arr[largest]) largest = l;
if (r < n && arr[r] > arr[largest]) largest = r;
if (largest != i) {
swap(arr[i], arr[largest]);
move_times += 3;
heapify(arr, n, largest);
}
}
void heap_sort(vector<int>& arr) {
// 建立最大堆,将数组转换成最大堆
for (int i = arr.size() / 2 - 1; i >= 0; i--) heapify(arr, arr.size(), i);
// 交换根节点和最后一个节点,调整最大堆,重复此操作
for (int i = arr.size() - 1; i >= 0; i--) {
move_times += 3;
swap(arr[0], arr[i]);
heapify(arr, i, 0);
}
}
//重置数组
void restore_status(vector<int>& tmp, vector<int>& arr,
long long& comparison_times, long long& move_times) {
tmp = arr;
comparison_times = 0;
move_times = 0;
return;
}
//打印数组
void print_statistical_results(const long long& comparison_times,
const long long& move_times) {
cout << comparison_times << ' ' << move_times << '\n';
}
int main() {
// ios::sync_with_stdio(false);
int step = 10;
for (int i = 0; i < 5; ++i, step *= 5) {
vector<int> arr, tmp;
for (int j = 0; j < step; ++j) {
arr.push_back(dis(engine));
}
// 冒泡排序
restore_status(tmp, arr, comparison_times, move_times);
bubbling_sort(tmp);
cout << "当有"<<step<<"个元素参加冒泡排序的关键字参加的交换次数和比较次数分别为:";
print_statistical_results(comparison_times, move_times);
// 简单选择排序
restore_status(tmp, arr, comparison_times, move_times);
simple_selection_sort(tmp);
cout << "当有" << step
<< "个元素参加简单选择排序的关键字参加的交换次数和比较次数分别为:";
print_statistical_results(comparison_times, move_times);
// 快速排序
restore_status(tmp, arr, comparison_times, move_times);
quick_sort(tmp, 0, tmp.size() - 1);
cout << "当有" << step
<< "个元素参加快速排序的关键字参加的交换次数和比较次数分别为:";
print_statistical_results(comparison_times, move_times);
// 简单插入排序
restore_status(tmp, arr, comparison_times, move_times);
simple_insertion_sort(tmp);
cout << "当有" << step
<< "个元素参加简单插入排序的关键字参加的交换次数和比较次数分别为:";
print_statistical_results(comparison_times, move_times);
// 希尔排序
restore_status(tmp, arr, comparison_times, move_times);
shell_sort(tmp);
cout << "当有" << step
<< "个元素参加希尔排序的关键字参加的交换次数和比较次数分别为:";
print_statistical_results(comparison_times, move_times);
// 堆排序
restore_status(tmp, arr, comparison_times, move_times);
heap_sort(tmp);
cout << "当有" << step
<< "个元素参加堆排序的关键字参加的交换次数和比较次数分别为:";
print_statistical_results(comparison_times, move_times);
cout << endl;
}
cout << "end";
return 0;
}