《数据结构与算法》课程设计:30-排序综合

《数据结构与算法》课程设计

30、排序综合

问题描述:
利用随机函数产生N个随机整数(20000以上),对这些数进行多种方法进行排序。
基本要求:
(1)至少采用三种方法实现上述问题求解(提示:可采用的方法有插入排序、希尔排序、起泡排序、快速排序、选择排序、堆排序、归并排序)。并把排序后的结果保存在不同的文件中;
(2)统计每一种排序方法的性能(以上机运行程序所花费的时间为准进行对比),找出其中两种较快的方法;
(3)如果采用4种或4种以上的方法者,可适当加分。

#include<iostream>
#include<vector>
#include<cstdlib>
#include<ctime>
#include<fstream>
#include<algorithm>

using namespace std;
struct sortTime {
    string name;        //排序方法名
    int time;           //排序消耗时间
};

bool cmpSotTime(sortTime o, sortTime t) {
    return o.time < t.time;
}

//直接插入排序
void InsertSort(vector<int> &vi, int length) {
    int i, j, tmp;
    for (i = 1; i < length; i++) {
        if (vi[i] < vi[i - 1]) {        //反序时
            tmp = vi[i];
            j = i - 1;
            do {        //找 vi[i] 的插入位置
                vi[j + 1] = vi[j];      //将数据大于 vi[i] 的记录后移
                j--;
            } while (j >= 0 && vi[j] > tmp);
            vi[j + 1] = tmp;        //在 j+1 处插入 R[i]
        }
    }
}

//折半插入排序
void BinInsertSort(vector<int> &vi, int length) {
    int i, j, low, high, mid, tmp;
    for (i = 1; i < length; i++) {
        if (vi[i] < vi[i - 1]) {        //反序时
            tmp = vi[i];        //将 vi[i] 保存到 tmp
            low = 0, high = i - 1;
            while (low <= high) {       //在 vi[low...high] 中查找插入的位置
                mid = (low + high) >> 1;        //取中间位置
                if (tmp < vi[mid]) {
                    high = mid - 1;     //插入点在左半区
                } else {
                    low = mid + 1;      //插入点在又半区
                }
            }       //找位置 high
            for (j = i - 1; j >= high + 1; j--) {       //集中进行元素后移
                vi[j + 1] = vi[j];
            }
            vi[high + 1] = tmp;     //插入 tmp
        }
    }
}

//希尔排序
void ShellSort(vector<int> &vi, int length) {
    int d = 1;
    while (d < length / 3) {      //设置增量
        d = 3 * d + 1;
    }
    while (d >= 1) {
        for (int i = d; i < length; i++) {      //对所有组采用直接插入排序
            for (int j = i; j >= d && vi[j] < vi[j - d]; j -= d) {      //对相隔 d 个位置一组采用直接插入排序
                swap(vi[j], vi[j - d]);
            }
        }
        d = d / 3;     //减小增量
    }
}

//冒泡排序
void BubbleSort(vector<int> &vi, int length) {
    int i, j;
    bool exchange;
    for (i = 0; i < length; i++) {
        exchange = false;       //一趟前 exchange 置为假
        for (j = length - 1; j > i; j--) {      //归位 vi[i],循环 length-i-1 次
            if (vi[j] < vi[j - 1]) {        //相邻两个元素反序时
                swap(vi[j], vi[j - 1]);     //将 vi[j] 和 vi[j-1] 两个元素交换
                exchange = true;        //一旦有交换,exchange 置为真
            }
        }
        if (!exchange) {        //本趟没有发生交换,中途结束算法
            return;
        }
    }
}

//快速排序
void QuickSort(vector<int> &vi, int l, int r) {
    if (l >= r) return;
    int tmp = vi[(l + r) >> 1], i = l - 1, j = r + 1;     //用区间中间元素作为基准
    while (i < j) {
        do i++; while (vi[i] < tmp);        //从左向右扫描,找一个大于 tmp 的 vi[i]
        do j--; while (vi[j] > tmp);        //从右向左扫描,找一个小于 tmp 的 vi[j]
        if (i < j) swap(vi[i], vi[j]);      //交换大于 tmp 的 vi[i] 和小于 tmp 的 vi[j]
    }
    QuickSort(vi, l, j);               //对左区间递归排序
    QuickSort(vi, j + 1, r);        //对右区间递归排序
}

//选择排序
void SelectSort(vector<int> &vi, int length) {
    int i, j, k;
    for (i = 0; i < length - 1; i++) {      //做第 i 趟排序
        k = i;
        for (j = i + 1; j < length; j++) {      //在当前无序区 vi[i...length-1] 中选数据最小的 vi[k]
            if (vi[j] < vi[k]) {
                k = j;      //k 记下目前找到的最小数据所在的位置
            }
        }
        if (k != i) {       //vi[i] 和 vi[k] 两个元素交换
            swap(vi[i], vi[k]);
        }
    }
}

//构造大根堆
void sift(vector<int> &vi, int low, int high) {
    int i = low, j = 2 * i + 1;     //vi[j] 是 vi[i]的左孩子
    int tmp = vi[i];
    while (j <= high) {
        if (j + 1 <= high && vi[j] < vi[j + 1]) {        //若右孩子较大,把 j 指向右孩子
            j++;
        }
        if (vi[i] > vi[j]) {        //若根结点大于等于最大孩子关键字,筛选结束
            break;
        } else {                  //若根结点小于最大孩子的关键字
            swap(vi[i], vi[j]);      //将 vi[j] 调整到双亲结点的位置上
            i = j;                //修改 i 和 j 值,以便继续向下筛选
            j = i * 2 + 1;
        }
    }
    vi[i] = tmp;                //被筛选结点放入最终位置上
}

//堆排序
void HeapSort(vector<int> &vi, int length) {
    for (int i = (length >> 1) - 1; i >= 0; i--) {        //循环建立初始堆,调用 sift 算法 ⌊n/2⌋ 次
        sift(vi, i, length - 1);
    }
    for (int i = length - 1; i >= 0; i--) {             //进行 n-1 趟完成堆排序,每一趟堆中元素个数减 1
        swap(vi[0], vi[i]);              //将最后一个元素与根 vi[1] 交换
        sift(vi, 1, i - 1);       //对 vi[1...i-1] 进行筛选,得到 i1 个结点的堆
    }
}

//二路归并排序
const int N = 1000010;
int tmp[N];

void MergeSort(vector<int> &vi, int l, int r) {
    if (l >= r) return;
    int mid = l + r >> 1;       //取中间位置
    MergeSort(vi, l, mid), MergeSort(vi, mid + 1, r);       //递归分组
    int k = 0, i = l, j = mid + 1;
    while (i <= mid && j <= r) {
        if (vi[i] <= vi[j]) tmp[k++] = vi[i++];     //从小到大加进 tmp
        else tmp[k++] = vi[j++];
    }
    while (i <= mid) tmp[k++] = vi[i++];        //将剩余元素加进 tmp
    while (j <= r) tmp[k++] = vi[j++];          //将剩余元素加进 tmp
    for (i = l, j = 0; i <= r; i++, j++) vi[i] = tmp[j];
}

int main() {
    srand((unsigned) time(NULL));
    int length;
    cout << "请输入随机数的个数:";
    cin >> length;
    vector<int> insertArray, binInsertArray, shellArray, bubbleArray, quickArray, selectArray, heapArray, mergeArray;

    cout << "开始生成随机数...\n";
    for (int i = 0, t; i < length; i++) {
        t = rand();
        insertArray.push_back(t);
        binInsertArray.push_back(t);
        shellArray.push_back(t);
        bubbleArray.push_back(t);
        quickArray.push_back(t);
        selectArray.push_back(t);
        heapArray.push_back(t);
        mergeArray.push_back(t);
    }

    cout << "随机数生成完毕!\n开始进行排序...\n";
    clock_t start;      //定时器
    sortTime st[8];
    start = clock();
    InsertSort(insertArray, insertArray.size());
    st[0].name = "直接插入排序", st[0].time = clock() - start;
    start = clock();
    BinInsertSort(binInsertArray, binInsertArray.size());
    st[1].name = "折半插入排序", st[1].time = clock() - start;
    start = clock();
    ShellSort(shellArray, shellArray.size());
    st[2].name = "希尔排序", st[2].time = clock() - start;
    start = clock();
    BubbleSort(bubbleArray, bubbleArray.size());
    st[3].name = "冒泡排序", st[3].time = clock() - start;
    start = clock();
    QuickSort(quickArray, 0, quickArray.size() - 1);
    st[4].name = "快速排序", st[4].time = clock() - start;
    start = clock();
    SelectSort(selectArray, selectArray.size());
    st[5].name = "选择排序", st[5].time = clock() - start;
    start = clock();
    HeapSort(heapArray, heapArray.size());
    st[6].name = "堆排序", st[6].time = clock() - start;
    start = clock();
    MergeSort(mergeArray, 0, mergeArray.size() - 1);
    st[7].name = "二路归并排序", st[7].time = clock() - start;

    cout << "排序完毕!开始将数据写入文件...\n";
    //开流
    ofstream insertSortOutStream("../CurriculumDesign/data/InsertSort.txt", ios::out);
    ofstream binInsertSortOutStream("../CurriculumDesign/data/BinInsertSort.txt", ios::out);
    ofstream shellSortOutStream("../CurriculumDesign/data/ShellSort.txt", ios::out);
    ofstream bubbleSortOutStream("../CurriculumDesign/data/BubbleSort.txt", ios::out);
    ofstream quickSortOutStream("../CurriculumDesign/data/QuickSort.txt", ios::out);
    ofstream selectSortOutStream("../CurriculumDesign/data/SelectSort.txt", ios::out);
    ofstream heapSortOutStream("../CurriculumDesign/data/HeapSort.txt", ios::out);
    ofstream mergeSortOutStream("../CurriculumDesign/data/MergeSort.txt", ios::out);
    //写数据
    insertSortOutStream << "直接插入排序:\n" << "时间消耗:" << st[0].time << "ms\n";
    binInsertSortOutStream << "折半插入排序:\n" << "时间消耗:" << st[1].time << "ms\n";
    shellSortOutStream << "希尔排序:\n" << "时间消耗:" << st[2].time << "ms\n";
    bubbleSortOutStream << "冒泡排序:\n" << "时间消耗:" << st[3].time << "ms\n";
    quickSortOutStream << "快速排序:\n" << "时间消耗:" << st[4].time << "ms\n";
    selectSortOutStream << "选择排序:\n" << "时间消耗:" << st[5].time << "ms\n";
    heapSortOutStream << "堆排序:\n" << "时间消耗:" << st[6].time << "ms\n";
    mergeSortOutStream << "二路归并排序:\n" << "时间消耗:" << st[7].time << "ms\n";
    for (int i = 0; i < length; i++) {
        insertSortOutStream << insertArray[i] << '\n';
        binInsertSortOutStream << binInsertArray[i] << '\n';
        shellSortOutStream << binInsertArray[i] << '\n';
        bubbleSortOutStream << binInsertArray[i] << '\n';
        quickSortOutStream << binInsertArray[i] << '\n';
        selectSortOutStream << binInsertArray[i] << '\n';
        heapSortOutStream << binInsertArray[i] << '\n';
        mergeSortOutStream << binInsertArray[i] << '\n';
    }
    cout << "数据写入文件完毕!\n";
    //关流
    insertSortOutStream.close();
    binInsertSortOutStream.close();
    shellSortOutStream.close();
    bubbleSortOutStream.close();
    quickSortOutStream.close();
    selectSortOutStream.close();
    heapSortOutStream.close();
    mergeSortOutStream.close();
    sort(st, st + 8, cmpSotTime);
    cout << "第一快的排序方法:" << st[0].name << "时间消耗:" << st[0].time << "ms\n";
    cout << "第二快的排序方法:" << st[1].name << "时间消耗:" << st[1].time << "ms\n";
    return 0;
}
  • 8
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值