排序算法时间性能的比较

【问题描述】 编写一个程序,采用不同的排序方法对数据集进行非递减有序排序,并对各种排序方法 的时间性能进行比较。

【实验目的】 掌握各种排序算法的原理、特点和时间性能。

【基本要求】 (1)输入待排序数据集中数据的个数 n (2)产生 n 个随机数 (3)分别用插入排序、选择排序、堆排序、快速排序、希尔排序、冒泡排序、归并排序算法 数据集进行排序,记录下每种排序方法实际消耗时间的毫秒数 

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

//插入排序
void insertion_sort(int arr[], int n) {
    for (int i = 1; i < n; i++) { //外层循环,从数组的第二个元素开始,因为第一个元素默认已经排序
        int key = arr[i];
        int j = i - 1;
        while (j >= 0 && arr[j] > key) {//内层循环的条件
            arr[j + 1] = arr[j];
            j--;//内层循环的结束条件,每次循环都会将j减1,直到找到key应该插入的位置
        }
        arr[j + 1] = key;
    }
}

//选择排序
void selection_sort(int arr[], int n) {
    for (int i = 0; i < n - 1; i++) {//外层循环,用于遍历整个数组
        int min_idx = i;//每次外层循环开始时,初始化一个变量 min_idx,用于记录当前未排序部分的最小值的索引
        for (int j = i + 1; j < n; j++) {
            if (arr[j] < arr[min_idx]) {
                min_idx = j;
            }
        }
        int temp = arr[min_idx];
        arr[min_idx] = arr[i];//将未排序部分的最小值移动到正确的位置。将当前位置 i 的元素赋值给最小值的位置 min_idx
        arr[i] = temp;
    }
}

// 堆化函数,将数组调整为最大堆
void heapify(int arr[], int n, int i) {
    int largest = i; // 初始化最大值为当前节点
    int left = 2 * i + 1; // 左子节点的索引
    int right = 2 * i + 2; // 右子节点的索引

    // 如果左子节点存在且大于当前最大值,更新最大值
    if (left < n && arr[left] > arr[largest]) {
        largest = left;
    }

    // 如果右子节点存在且大于当前最大值,更新最大值
    if (right < n && arr[right] > arr[largest]) {
        largest = right;
    }

    // 如果最大值不是当前节点,交换它们并递归地对交换后的节点进行堆化
    if (largest != i) {
        int swap = arr[i];
        arr[i] = arr[largest];
        arr[largest] = swap;
        heapify(arr, n, largest);
    }
}

// 堆排序
void heap_sort(int arr[], int n) {
    // 构建最大堆
    for (int i = n / 2 - 1; i >= 0; i--) {
        heapify(arr, n, i);
    }

    // 一个个从堆顶取出元素(最大值),放到数组末尾,并对剩余元素重新进行堆化
    for (int i = n - 1; i >= 0; i--) {
        int temp = arr[0]; // 取出堆顶元素
        arr[0] = arr[i]; // 将堆顶元素放到数组末尾
        arr[i] = temp; // 将原来的末尾元素放到堆顶位置
        heapify(arr, i, 0); // 对剩余元素重新进行堆化
    }
}

// 分区函数,用于将数组分为两部分,左边的元素都小于基准值,右边的元素都大于基准值
int partition(int arr[], int left, int right) {
    // 选择最右边的元素作为基准值
    int pivot = arr[right];
    // i 指向当前处理的元素的前一个位置
    int i = left - 1;
    // j 从左到右遍历数组
    for (int j = left; j <= right - 1; j++) {
        // 如果当前元素小于基准值,则将其与 i+1 位置的元素交换,并将 i 向后移动一位
        if (arr[j] < pivot) {
            i++;
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
    }
    // 将基准值放到正确的位置(即 i+1 的位置)
    int temp = arr[i + 1];
    arr[i + 1] = arr[right];
    arr[right] = temp;
    // 返回基准值的位置
    return i + 1;
}

// 快速排序函数,递归地将数组分为两部分并排序
void quick_sort(int arr[], int left, int right) {
    // 如果左边界小于右边界,说明还有元素需要排序
    if (left < right) {
        // 调用分区函数,获取基准值的位置
        int pivot = partition(arr, left, right);
        // 对基准值左边的部分进行排序
        quick_sort(arr, left, pivot - 1);
        // 对基准值右边的部分进行排序
        quick_sort(arr, pivot + 1, right);
    }
}

//希尔排序
void shell_sort(int arr[], int n) {
    for (int gap = n / 2; gap > 0; gap /= 2) {
        for (int i = gap; i < n; i++) {
            int temp = arr[i];
            int j;
            for (j = i; j >= gap && arr[j - gap] > temp; j -= gap) {
                arr[j] = arr[j - gap]; // 将当前元素与前面的元素进行比较和交换
            }
            arr[j] = temp; // 将当前元素插入到正确的位置
        }
    }
}

//冒泡排序
void bubble_sort(int arr[], int n) {
    // 外层循环控制排序趟数
    for (int i = 0; i < n - 1; i++) {
        // 内层循环控制每一趟排序多少次
        for (int j = 0; j < n - i - 1; j++) {
            // 如果当前元素大于下一个元素,则交换它们的位置
            if (arr[j] > arr[j + 1]) {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}

// 合并两个已排序的数组
void merge(int arr[], int left, int mid, int right) {
    int n1 = mid - left + 1; // 左半部分的长度
    int n2 = right - mid; // 右半部分的长度
    int L[n1], R[n2]; // 创建临时数组

    // 将左半部分的元素复制到临时数组L中
    for (int i = 0; i < n1; i++) {
        L[i] = arr[left + i];
    }

    // 将右半部分的元素复制到临时数组R中
    for (int j = 0; j < n2; j++) {
        R[j] = arr[mid + 1 + j];
    }

    int i = 0, j = 0, k = left; // 初始化三个指针

    // 比较临时数组L和R的元素,将较小的元素复制回原数组
    while (i < n1 && j < n2) {
        if (L[i] <= R[j]) {
            arr[k] = L[i];
            i++;
        } else {
            arr[k] = R[j];
            j++;
        }
        k++;
    }

    // 如果临时数组L还有剩余元素,将其复制回原数组
    while (i < n1) {
        arr[k] = L[i];
        i++;
        k++;
    }

    // 如果临时数组R还有剩余元素,将其复制回原数组
    while (j < n2) {
        arr[k] = R[j];
        j++;
        k++;
    }
}

// 归并排序
void merge_sort(int arr[], int left, int right) {
    // 如果数组长度大于1,那么对其进行排序
    if (left < right) {
        int mid = left + (right - left) / 2; // 计算中间位置
        merge_sort(arr, left, mid); // 对左半部分进行排序
        merge_sort(arr, mid + 1, right); // 对右半部分进行排序
        merge(arr, left, mid, right); // 将两部分合并
    }
}

int main() {
    int n;
    printf("请输入待排序数据集中数据的个数: \n");
    scanf("%d", &n);

    int *arr = (int *)malloc(n * sizeof(int));
    srand(time(NULL));
    for (int i = 0; i < n; i++) {
        arr[i] = rand() % n;//生成任意随机数
    }

    printf("原始数组: \n");
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
      int j=0;
    while(j<10){

    int choice;
    printf("请选择排序方式: \n");
    printf("1. 插入排序\n");
    printf("2. 选择排序\n");
    printf("3. 堆排序\n");
    printf("4. 快速排序\n");
    printf("5. 希尔排序\n");
    printf("6. 冒泡排序\n");
    printf("7. 归并排序\n");
    scanf("%d", &choice);

    clock_t start, end;
    double cpu_time_used;

    switch (choice) {
        case 1:
            start = clock();
            insertion_sort(arr, n);
            end = clock();
            
            break;
        case 2:
            start = clock();
            selection_sort(arr, n);
            end = clock();
            break;
        case 3:
            start = clock();
            heap_sort(arr, n);
            end = clock();
            break;
        case 4:
            start = clock();
            quick_sort(arr, 0, n - 1);
            end = clock();
            break;
        case 5:
            start = clock();
            shell_sort(arr, n);
            end = clock();
            break;
        case 6:
            start = clock();
            bubble_sort(arr, n);
            end = clock();
            break;
        case 7:
            start = clock();
            merge_sort(arr, 0, n - 1);
            end = clock();
            break;
        default:
            printf("无效的选择\n");
            return 1;
    }

    printf("排序后的数组: \n");
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
    cpu_time_used = cpu_time_used*1000;
    printf("排序方法实际消耗时间的毫秒数: %f ms\n", cpu_time_used );
    j++;
}

    free(arr);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值