【一】排序算法

排序算法

选择排序

选择排序算法是一种简单的排序算法,其基本思想是每次找出数组中最小的元素,并将其放到数组的起始位置。在排序过程中,我们首先找出数组中最小的元素,然后将其与数组的第一个元素交换位置。接下来,在剩余的元素中再找出最小的元素,将其与数组的第二个元素交换位置。以此类推,直到整个数组都被排好序为止。

在下面的代码中,我们首先定义了选择排序算法函数 selection_sort(),它接受两个参数:要排序的数组 arr 和数组的大小 n。在函数中,我们通过两层循环来找出数组中最小的元素,并将其与数组的起始位置交换。最后,当所有元素都被排好序时,排序就完成了。

#include <stdio.h>

// 选择排序算法,对数组 arr 进行排序
void selection_sort(int arr[], int n) {
    int i, j, min_idx, temp;
    
    // 找出数组中最小元素,并将其放到数组的起始位置
    for (i = 0; i < n - 1; i++) {
        min_idx = i;
        for (j = i + 1; j < n; j++) {
            if (arr[j] < arr[min_idx]) {
                min_idx = j;
            }
        }
        temp = arr[i];
        arr[i] = arr[min_idx];
        arr[min_idx] = temp;
    }
}

int main() {
    int arr[] = {5, 2, 8, 3, 9, 4, 1, 7, 6};
    int n = sizeof(arr) / sizeof(arr[0]);
    selection_sort(arr, n);
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    return 0;
}

快速排序

快速排序算法其基本思想是通过不断地选取基准值并将数组中小于基准值的元素放到基准值的左边,大于基准值的元素放到基准值的右边,最终将数组分成左右两个子数组并递归地对它们进行排序。在排序过程中,我们通常将数组的第一个元素作为基准值,也可以随机选取基准值。

在下面的代码中,我们首先定义了快速排序算法函数 quick_sort(),它接受三个参数:要排序的数组 arr,以及数组的左右边界 left 和 right。在函数中,我们首先选取数组的第一个元素作为基准值,并将其放到正确的位置上。然后,我们将数组中小于基准值的元素放到基准值的左边,大于基准值的元素放到基准值的右边。最后,我们递归地对基准值左边和右边的子数组进行排序。

#include <stdio.h>

// 快速排序算法,对数组 arr 进行排序
void quick_sort(int arr[], int left, int right) {
    int pivot, i, j, temp;
    
    if (left < right) {
        // 以数组的第一个元素为基准值
        pivot = left;
        i = left;
        j = right;
        
        // 将数组中小于基准值的元素放到基准值的左边,大于基准值的元素放到基准值的右边
        while (i < j) {
            while (arr[i] <= arr[pivot] && i < right) {
                i++;
            }
            while (arr[j] > arr[pivot]) {
                j--;
            }
            if (i < j) {
                temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }
        
        // 将基准值放到正确的位置上
        temp = arr[pivot];
        arr[pivot] = arr[j];
        arr[j] = temp;
        
        // 递归地对基准值左边和右边的子数组进行排序
        quick_sort(arr, left, j - 1);
        quick_sort(arr, j + 1, right);
    }
}

int main() {
    int arr[] = {5, 2, 8, 3, 9, 4, 1, 7, 6};
    int n = sizeof(arr) / sizeof(arr[0]);
    quick_sort(arr, 0, n - 1);
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    return 0;
}

插入排序

插入排序算法是一种简单的排序算法,其基本思想是将数组中的元素一个个地插入到已经排好序的子数组中。在排序过程中,我们从第二个元素开始,将其插入到已经排好序的前面的子数组中,直到整个数组都被排好序为止。

在下面的代码中,我们首先定义了插入排序算法函数 insertion_sort(),它接受两个参数:要排序的数组 arr 和数组的大小 n。在函数中,我们从第二个元素开始遍历数组,将其插入到已经排好序的前面的子数组中。具体来说,我们将当前元素 key 与已经排好序的子数组中的元素依次比较,找到 key 应该插入的位置,并将后面的元素挪一位,最后将 key 插入到正确的位置上。

#include <stdio.h>

// 插入排序算法,对数组 arr 进行排序
void insertion_sort(int arr[], int n) {
    int i, j, key;
    
    // 从第二个元素开始插入排序
    for (i = 1; i < n; i++) {
        key = arr[i];
        j = i - 1;
        
        // 将 arr[j] 挪到正确的位置上
        while (j >= 0 && arr[j] > key) {
            arr[j + 1] = arr[j];
            j--;
        }
        arr[j + 1] = key;
    }
}

int main() {
    int arr[] = {5, 2, 8, 3, 9, 4, 1, 7, 6};
    int n = sizeof(arr) / sizeof(arr[0]);
    insertion_sort(arr, n);
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    return 0;
}

冒泡排序

冒泡排序算法是一种简单的排序算法,其基本思想是重复地交换相邻的元素,直到整个数组都被排好序为止。在排序过程中,每一轮比较都将当前未排序数组中的最大值沉到最后面。

在下面的代码中,我们首先定义了冒泡排序算法函数 bubble_sort(),它接受两个参数:要排序的数组 arr 和数组的大小 n。在函数中,我们通过两层循环来比较相邻的元素,并将它们交换位置,如果当前元素大于下一个元素,则交换它们的位置。在每一轮排序中,我们都将未排序数组中的最大值沉到最后面。

#include <stdio.h>

// 冒泡排序算法,对数组 arr 进行排序
void bubble_sort(int arr[], int n) {
    int i, j, temp;
    
    // 外层循环控制排序的轮数
    for (i = 0; i < n - 1; i++) {
        // 内层循环控制每一轮排序中的比较次数
        for (j = 0; j < n - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}

int main() {
    int arr[] = {5, 2, 8, 3, 9, 4, 1, 7, 6};
    int n = sizeof(arr) / sizeof(arr[0]);
    bubble_sort(arr, n);
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    return 0;
}

归并排序

归并排序算法,其基本思想是将数组分成两个子数组,分别对它们进行排序,然后将它们合并成一个有序数组。在排序过程中,我们采用分治的思想,将问题分解成更小的子问题,最终将所有子问题的解合并起来得到原问题的解。

在下面的代码中,我们首先定义了归并排序算法函数 merge_sort(),它接受三个参数:要排序的数组 arr,以及数组的左右边界 left 和 right。在函数中,我们首先将数组分成两个子数组,分别对它们进行归并排序。然后,我们将左右两个子数组合并成一个有序数组。具体来说,我们用两个指针 i 和 j 分别指向左右两个子数组的开头,比较它们的元素,并将较小的元素放入临时数组 temp 中。最后,将 temp 中的元素复制回原数组 arr 中。

#include <stdio.h>

// 归并排序算法,对数组 arr 进行排序
void merge_sort(int arr[], int left, int right) {
    if (left < right) {
        int mid = (left + right) / 2;
        
        // 分别对左右两个子数组进行归并排序
        merge_sort(arr, left, mid);
        merge_sort(arr, mid + 1, right);
        
        // 合并左右两个子数组
        int i = left;
        int j = mid + 1;
        int k = 0;
        int temp[right - left + 1];
        while (i <= mid && j <= right) {
            if (arr[i] < arr[j]) {
                temp[k++] = arr[i++];
            } else {
                temp[k++] = arr[j++];
            }
        }
        while (i <= mid) {
            temp[k++] = arr[i++];
        }
        while (j <= right) {
            temp[k++] = arr[j++];
        }
        for (i = left, k = 0; i <= right; i++, k++) {
            arr[i] = temp[k];
        }
    }
}

int main() {
    int arr[] = {5, 2, 8, 3, 9, 4, 1, 7, 6};
    int n = sizeof(arr) / sizeof(arr[0]);
    merge_sort(arr, 0, n - 1);
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    return 0;
}

希尔排序

希尔排序算法,一种改进的插入排序算法,其基本思想是将待排序的数组按照一定的间隔分成若干个子数组,对每个子数组进行插入排序,然后逐步缩小间隔,重复进行插入排序,直到间隔为 1,即最后一次排序为一次简单的插入排序为止。

在下面的代码中,我们首先定义了希尔排序算法函数 shell_sort(),它接受两个参数:要排序的数组 arr 和数组的大小 n。在函数中,我们采用希尔增量序列对数组进行分组,然后对每个子数组进行插入排序。具体来说,我们通过循环不断缩小增量 gap 的值,对每个子数组进行插入排序。在插入排序中,我们将当前元素 temp 与前面的元素依次比较,找到 temp 应该插入的位置,并将后面的元素挪一位,最后将 temp 插入到正确的位置上。

#include <stdio.h>

// 希尔排序算法,对数组 arr 进行排序
void shell_sort(int arr[], int n) {
    int i, j, gap, temp;
    
    // 希尔增量序列
    for (gap = n / 2; gap > 0; gap /= 2) {
        // 插入排序算法
        for (i = gap; i < n; i++) {
            temp = arr[i];
            for (j = i - gap; j >= 0 && arr[j] > temp; j -= gap) {
                arr[j + gap] = arr[j];
            }
            arr[j + gap] = temp;
        }
    }
}

int main() {
    int arr[] = {5, 2, 8, 3, 9, 4, 1, 7, 6};
    int n = sizeof(arr) / sizeof(arr[0]);
    shell_sort(arr, n);
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    return 0;
}

堆排序(不太重要

基本思想是将待排序的数组看成一颗完全二叉树,每个节点都比其子节点大(或小),将其转化为一个大根堆(或小根堆)。然后将堆顶元素与最后一个元素交换,然后重新调整剩下的元素,使它们重新构成一个大根堆(或小根堆)。不断重复这个过程,直到所有的元素都排好序为止。

在下面的代码中,我们首先定义了两个函数:adjust_heap() 和 heap_sort()。adjust_heap() 函数用于调整以 i 为根的子树为大根堆,它接受三个参数:要排序的数组 arr,以及当前子树的根节点 i 和数组的大小 n。在函数中,我们通过比较当前节点和左右子节点的大小关系,将当前节点与其子节点中较大的那个交换位置,并继续向下调整子树。

heap_sort() 函数是堆排序算法的主函数,它接受两个参数:要排序的数组 arr 和数组的大小 n。在函数中,我们首先建立初始大根堆,然后进行排序过程。具体来说,我们从最后一个元素开始,将其与堆顶元素交换位置,然后将堆顶元素向下调整,使其继续保持大根堆的性质。重复这个过程,直到所有的元素都排好序为止。

#include <stdio.h>

// 调整以 i 为根的子树为大根堆
void adjust_heap(int arr[], int i, int n) {
    int temp = arr[i];
    int j = 2 * i + 1;
    while (j < n) {
        if (j + 1 < n && arr[j] < arr[j + 1]) {
            j++;
        }
        if (arr[j] > temp) {
            arr[i] = arr[j];
            i = j;
            j = 2 * i + 1;
        } else {
            break;
        }
    }
    arr[i] = temp;
}

// 堆排序算法,对数组 arr 进行排序
void heap_sort(int arr[], int n) {
    int i, temp;
    
    // 建立初始大根堆
    for (i = n / 2 - 1; i >= 0; i--) {
        adjust_heap(arr, i, n);
    }
    
    // 排序过程
    for (i = n - 1; i >= 1; i--) {
        temp = arr[0];
        arr[0] = arr[i];
        arr[i] = temp;
        adjust_heap(arr, 0, i);
    }
}

int main() {
    int arr[] = {5, 2, 8, 3, 9, 4, 1, 7, 6};
    int n = sizeof(arr) / sizeof(arr[0]);
    heap_sort(arr, n);
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值