目录
一、冒泡排序法
冒泡排序法的核心思想是比较相邻的元素,如果第一个比第二个大,就交换它们两个。对每一对相邻元素进行比较,将最大或最小的元素移动到数组末尾,直到没有任何一对数字需要比较。
#include <stdio.h>
void bubble_sort(int arr[], int len) {
int i, j, temp;
for (i = 0; i < len - 1; i++) {
for (j = 0; j < len - 1 - i; 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, 1};
int len = sizeof(arr) / sizeof(int);
int i;
printf("排序前数组元素为:");
for (i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
printf("\n");
bubble_sort(arr, len);
printf("排序后数组元素为:");
for (i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
使用了一个名为 bubble_sort
的函数,该函数接受一个整型数组 arr
和数组长度 len
作为参数,对数组进行冒泡排序并修改原数组。主函数中定义了一个整型数组 arr
,在使用 sizeof
获取数组长度后,调用 bubble_sort
函数对数组进行排序,最后输出排序结果。
二、选择排序法
选择排序法的核心思想是记录未排序数组的最小值或最大值,将其与无序部分的第一个元素交换位置,直到数组完全有序。其中,一次排序会确定当前无序区内的最小值或最大值,并将该值放置在正确的有序区位置上。
#include <stdio.h>
void selection_sort(int arr[], int len) {
int i, j, temp;
int min_index;
for (i = 0; i < len - 1; i++) {
min_index = i;
for (j = i + 1; j < len; j++) {
if (arr[min_index] > arr[j]) {
min_index = j;
}
}
if (min_index != i) {
temp = arr[i];
arr[i] = arr[min_index];
arr[min_index] = temp;
}
}
}
int main() {
int arr[] = {5, 2, 8, 3, 1};
int len = sizeof(arr) / sizeof(int);
int i;
printf("排序前数组元素为:");
for (i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
printf("\n");
selection_sort(arr, len);
printf("排序后数组元素为:");
for (i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
使用了一个名为 selection_sort
的函数,该函数接受一个整型数组 arr
和数组长度 len
作为参数,对数组进行选择排序并修改原数组。主函数中定义了一个整型数组 arr
,在使用 sizeof
获取数组长度后,调用 selection_sort
函数对数组进行排序,最后输出排序结果。
三、插入排序法
插入排序法的核心思想是将待排序的数组分成两部分:已排序部分和未排序部分。从未排序部分取出第一个元素,与已排序部分从后向前比较,找到其应该插入的位置并插入。重复这个过程,直到未排序部分没有元素。其中,每次排序会将新的元素插入到已排序部分合适的位置,使得已排序部分保持有序。
#include <stdio.h>
void insertion_sort(int arr[], int len) {
int i, j, temp;
for (i = 1; i < len; i++) {
temp = arr[i];
j = i - 1;
while (j >= 0 && arr[j] > temp) {
arr[j+1] = arr[j];
j--;
}
arr[j+1] = temp;
}
}
int main() {
int arr[] = {5, 2, 8, 3, 1};
int len = sizeof(arr) / sizeof(int);
int i;
printf("排序前数组元素为:");
for (i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
printf("\n");
insertion_sort(arr, len);
printf("排序后数组元素为:");
for (i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
使用了一个名为 insertion_sort
的函数,该函数接受一个整型数组 arr
和数组长度 len
作为参数,对数组进行插入排序并修改原数组。主函数中定义了一个整型数组 arr
,在使用 sizeof
获取数组长度后,调用 insertion_sort
函数对数组进行排序,最后输出排序结果。
四、希尔排序法
希尔排序法是插入排序法的改进版本,其核心思想是将数组分割为若干个子序列,分别进行插入排序。通过逐步减小子序列的长度,并不断对整个数组进行插入排序,使得整个数组变得有序。希尔排序法中的增量序列可以设定很多种,如 Shell 增量、Hibbard 增量、Knuth 增量等,通常采用 Shell 增量。
#include <stdio.h>
void shell_sort(int arr[], int len) {
int i, j, gap;
int temp;
for (gap = len / 2; gap > 0; gap /= 2) {
for (i = gap; i < len; 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, 1};
int len = sizeof(arr) / sizeof(int);
int i;
printf("排序前数组元素为:");
for (i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
printf("\n");
shell_sort(arr, len);
printf("排序后数组元素为:");
for (i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
使用了一个名为 shell_sort
的函数,该函数接受一个整型数组 arr
和数组长度 len
作为参数,对数组进行希尔排序并修改原数组。主函数中定义了一个整型数组 arr
,在使用 sizeof
获取数组长度后,调用 shell_sort
函数对数组进行排序,最后输出排序结果。
五、快速排序法
快速排序法是基于交换的排序算法,它采用了分治的思想。具体来说,每次选择一个基准值,将序列分为两个部分,左边部分都小于等于基准值,右边部分都大于等于基准值。然后递归地分别对左右两边部分进行排序,直到整个序列有序。通常采用双指针法,从左右两边同时向中间扫描找到需要交换的元素,然后进行交换。基准值的选取可以采用多种方式,如取第一个元素、取中间元素、取随机元素等,具体选取方式影响算法的效率。
#include <stdio.h>
void quick_sort(int arr[], int left, int right) {
if (left >= right) {
return;
}
int i = left, j = right;
int pivot = arr[left];
while (i < j) {
while (i < j && arr[j] >= pivot) {
j--;
}
arr[i] = arr[j];
while (i < j && arr[i] <= pivot) {
i++;
}
arr[j] = arr[i];
}
arr[i] = pivot;
quick_sort(arr, left, i-1);
quick_sort(arr, i+1, right);
}
int main() {
int arr[] = {5, 2, 8, 3, 1};
int len = sizeof(arr) / sizeof(int);
int i;
printf("排序前数组元素为:");
for (i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
printf("\n");
quick_sort(arr, 0, len-1);
printf("排序后数组元素为:");
for (i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
使用了一个名为 quick_sort
的函数,该函数接受一个整型数组 arr
、左边界 left
和右边界 right
作为参数,对数组进行快速排序并修改原数组。主函数中定义了一个整型数组 arr
,在使用 sizeof
获取数组长度后,调用 quick_sort
函数对数组进行排序,最后输出排序结果。
六、归并排序法
归并排序法是基于比较的稳定排序算法,采用了分治的思想。具体来说,将待排序序列逐层划分为若干个子序列,每个子序列都是有序的,然后将相邻两个子序列进行合并,直到整个序列有序。合并过程中需要用到一个额外的数组来存储归并后的结果,最后将排序好的结果赋值给原数组。原始序列被均分成两个长度相等的子序列,直到子序列长度为1,然后将相邻两个子序列进行合并。
#include <stdio.h>
#include <stdlib.h>
void merge(int arr[], int left, int mid, int right) {
int i = left, j = mid+1, k = 0;
int* temp = (int*) malloc(sizeof(int) * (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];
}
free(temp);
}
void merge_sort(int arr[], int left, int right) {
if (left >= right) {
return;
}
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 arr[] = {5, 2, 8, 3, 1};
int len = sizeof(arr) / sizeof(int);
int i;
printf("排序前数组元素为:");
for (i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
printf("\n");
merge_sort(arr, 0, len-1);
printf("排序后数组元素为:");
for (i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
该程序使用了一个名为 merge
的函数,该函数接受一个整型数组 arr
、左边界 left
、中间位置 mid
和右边界 right
作为参数,对数组的左半部分和右半部分进行归并排序并修改原数组。在归并排序过程中,需要用到一个额外的数组来存储排序过程中产生的临时结果。主函数中定义了一个整型数组 arr
,在使用 sizeof
获取数组长度后,调用 merge_sort
函数对数组进行排序,最后输出排序结果。
七、堆排序法
堆排序法是基于比较的不稳定排序算法,采用了大根堆(或小根堆)的数据结构来实现。首先将待排序序列建立成大根堆(或小根堆),然后将根节点与最后一个节点交换位置,这时候最后一个节点已经是有序的了,再对剩余部分的序列进行堆化,得到新的根节点,再将根节点与倒数第二个节点交换位置,以此类推,不断缩小排序范围,直到整个序列有序。堆排序需要额外的空间来存储堆结构,且常数因子较大。
#include <stdio.h>
void heapify(int arr[], int n, int i) {
int largest = i;
int l = 2*i+1, r = 2*i+2;
if (l < n && arr[l] > arr[largest]) {
largest = l;
}
if (r < n && arr[r] > arr[largest]) {
largest = r;
}
if (largest != i) {
int temp = arr[i];
arr[i] = arr[largest];
arr[largest] = temp;
heapify(arr, n, largest);
}
}
void heap_sort(int arr[], int n) {
int i;
for (i = n/2-1; i >= 0; i--) {
heapify(arr, n, i);
}
for (i = n-1; i >= 0; i--) {
int temp = arr[0];
arr[0] = arr[i];
arr[i] = temp;
heapify(arr, i, 0);
}
}
int main() {
int arr[] = {5, 2, 8, 3, 1};
int len = sizeof(arr) / sizeof(int);
int i;
printf("排序前数组元素为:");
for (i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
printf("\n");
heap_sort(arr, len);
printf("排序后数组元素为:");
for (i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
使用了一个名为 heapify
的函数和一个名为 heap_sort
的函数,分别对整型数组进行堆化和堆排序。在堆化过程中,需要通过递归地调用该函数来维护大根堆的性质;在堆排序过程中,需要先将整个数组堆化,然后逐步将最大值交换到数组末尾,并重新堆化剩余部分的数组。主函数中定义了一个整型数组 arr
,在使用 sizeof
获取数组长度后,调用 heap_sort
函数对数组进行排序,最后输出排序结果。
八、基数排序法
基数排序是一种非比较排序算法,采用了将数据按照位来比较的策略,由低位到高位依次对数据进行排序。它需要使用到计数排序或桶排序等线性时间复杂度的辅助排序算法,而且需要数据具有一定的范围限制和可比性。
#include <stdio.h>
#include <stdlib.h>
int get_digit(int num, int radix) {
int digit = 1;
while ((num /= radix) > 0) {
digit++;
}
return digit;
}
int get_num_at_digit(int num, int digit, int radix) {
int i;
for (i = 1; i < digit; i++) {
num /= radix;
}
return num % radix;
}
void radix_sort(int arr[], int n, int radix) {
int i, j, k, digit, max_digit = 0;
int* count = (int*) malloc(sizeof(int) * radix);
int* bucket = (int*) malloc(sizeof(int) * n);
for (i = 0; i < n; i++) {
digit = get_digit(arr[i], radix);
if (digit > max_digit) {
max_digit = digit;
}
}
for (k = 1; k <= max_digit; k++) {
for (i = 0; i < radix; i++) {
count[i] = 0;
}
for (i = 0; i < n; i++) {
digit = get_num_at_digit(arr[i], k, radix);
count[digit]++;
}
for (i = 1; i < radix; i++) {
count[i] += count[i-1];
}
for (i = n-1; i >= 0; i--) {
digit = get_num_at_digit(arr[i], k, radix);
bucket[--count[digit]] = arr[i];
}
for (i = 0; i < n; i++) {
arr[i] = bucket[i];
}
}
free(count);
free(bucket);
}
int main() {
int arr[] = {35, 28, 98, 45, 67, 23, 10};
int len = sizeof(arr) / sizeof(int);
int i;
printf("排序前数组元素为:");
for (i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
printf("\n");
radix_sort(arr, len, 10);
printf("排序后数组元素为:");
for (i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
该程序使用了一个名为 get_digit
的函数和一个名为 get_num_at_digit
的函数,分别用于获取一个整数的位数及某一位的数字;还使用了一个名为 radix_sort
的函数,基于计数排序的思想实现基数排序。在基数排序过程中,需要将待排序序列按照位数从低到高依次进行排序,每次排序需要使用计数排序对相应位上的数字进行排序。主函数中定义了一个整型数组 arr
,在使用 sizeof
获取数组长度后,调用 radix_sort
函数对数组进行排序,最后输出排序结果。
九、桶排序法
桶排序是一种常用的排序算法,它需要根据数据的特点构建若干个桶,将数据分配到相应的桶中并对每个桶中的数据进行排序,最后按照桶的顺序依次输出所有数据。桶排序具有线性时间复杂度,但需要额外的存储空间来存放桶。
#include <stdio.h>
#include <stdlib.h>
void bucket_sort(int arr[], int n, int bucketSize) {
int i, j, k;
int* bucket;
if (bucketSize <= 0) {
return;
}
int min_value = arr[0], max_value = arr[0];
for (i = 1; i < n; i++) {
if (arr[i] < min_value) {
min_value = arr[i];
} else if (arr[i] > max_value) {
max_value = arr[i];
}
}
int bucket_count = (max_value - min_value) / bucketSize + 1;
bucket = (int*) malloc(sizeof(int) * bucket_count);
for (i = 0; i < bucket_count; i++) {
bucket[i] = 0;
}
for (i = 0; i < n; i++) {
bucket[(arr[i] - min_value) / bucketSize]++;
}
for (i = 1; i < bucket_count; i++) {
bucket[i] += bucket[i-1];
}
int* results = (int*) malloc(sizeof(int) * n);
for (i = n-1; i >= 0; i--) {
j = (arr[i] - min_value) / bucketSize;
results[--bucket[j]] = arr[i];
}
for (i = 0; i < n; i++) {
arr[i] = results[i];
}
free(bucket);
free(results);
}
int main() {
int arr[] = {35, 28, 98, 45, 67, 23, 10};
int len = sizeof(arr) / sizeof(int);
int i;
printf("排序前数组元素为:");
for (i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
printf("\n");
bucket_sort(arr, len, 10);
printf("排序后数组元素为:");
for (i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
使用了一个名为 bucket_sort
的函数来实现桶排序。在桶排序过程中,需要将待排序序列分配到若干个桶中,然后对每个桶中的数据进行排序,最后按照桶的顺序依次输出所有数据。主函数中定义了一个整型数组 arr
,在使用 sizeof
获取数组长度后,调用 bucket_sort
函数对数组进行排序,最后输出排序结果。