六大排序算法比较(程序设计作业)

后续可能会更新作业的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;
}

  • 10
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值