C语言算法小工具:排序与查找算法实现

排序和查找是计算机科学中最基础也是最重要的算法。本文将详细介绍各种经典排序和查找算法的C语言实现,并提供实用的算法工具库。

1. 排序算法

1.1 简单排序算法

冒泡排序(Bubble Sort)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>
#include <string.h>

// 冒泡排序
void bubble_sort(int arr[], int n) {
for (int i = 0; i < n - 1; i++) {
bool swapped = false;
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;
swapped = true;
}
}
// 如果没有发生交换,说明数组已经有序
if (!swapped) break;
}
}

// 优化的冒泡排序(鸡尾酒排序)
void cocktail_sort(int arr[], int n) {
int left = 0, right = n - 1;

while (left < right) {
bool swapped = false;

// 从左到右冒泡
for (int i = left; i < right; i++) {
if (arr[i] > arr[i + 1]) {
int temp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = temp;
swapped = true;
}
}
right--;

if (!swapped) break;

// 从右到左冒泡
for (int i = right; i > left; i--) {
if (arr[i] < arr[i - 1]) {
int temp = arr[i];
arr[i] = arr[i - 1];
arr[i - 1] = temp;
swapped = true;
}
}
left++;

if (!swapped) break;
}
}

选择排序(Selection Sort)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// 选择排序
void selection_sort(int arr[], int n) {
for (int i = 0; i < n - 1; i++) {
int min_idx = i;

// 找到最小元素的索引
for (int j = i + 1; j < n; j++) {
if (arr[j] < arr[min_idx]) {
min_idx = j;
}
}

// 交换最小元素到当前位置
if (min_idx != i) {
int temp = arr[i];
arr[i] = arr[min_idx];
arr[min_idx] = temp;
}
}
}

// 双向选择排序
void double_selection_sort(int arr[], int n) {
int left = 0, right = n - 1;

while (left < right) {
int min_idx = left, max_idx = left;

// 同时找到最小和最大元素
for (int i = left; i <= right; i++) {
if (arr[i] < arr[min_idx]) {
min_idx = i;
}
if (arr[i] > arr[max_idx]) {
max_idx = i;
}
}

// 将最小元素放到左端
if (min_idx != left) {
int temp = arr[left];
arr[left] = arr[min_idx];
arr[min_idx] = temp;

// 如果最大元素在left位置,需要更新max_idx
if (max_idx == left) {
max_idx = min_idx;
}
}

// 将最大元素放到右端
if (max_idx != right) {
int temp = arr[right];
arr[right] = arr[max_idx];
arr[max_idx] = temp;
}

left++;
right--;
}
}

插入排序(Insertion Sort)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// 插入排序
void insertion_sort(int arr[], int n) {
for (int i = 1; i < n; i++) {
int key = arr[i];
int j = i - 1;

// 将大于key的元素向右移动
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j--;
}

arr[j + 1] = key;
}
}

// 二分插入排序
void binary_insertion_sort(int arr[], int n) {
for (int i = 1; i < n; i++) {
int key = arr[i];
int left = 0, right = i;

// 二分查找插入位置
while (left < right) {
int mid = left + (right - left) / 2;
if (arr[mid] > key) {
right = mid;
} else {
left = mid + 1;
}
}

// 移动元素
for (int j = i; j > left; j--) {
arr[j] = arr[j - 1];
}

arr[left] = key;
}
}

// 希尔排序(Shell Sort)
void shell_sort(int arr[], int n) {
// 使用Knuth序列:h = 3*h + 1
int h = 1;
while (h < n / 3) {
h = 3 * h + 1;
}

while (h >= 1) {
// 对每个子序列进行插入排序
for (int i = h; i < n; i++) {
int key = arr[i];
int j = i;

while (j >= h && arr[j - h] > key) {
arr[j] = arr[j - h];
j -= h;
}

arr[j] = key;
}

h /= 3;
}
}

1.2 高效排序算法

快速排序(Quick Sort)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// 分区函数
int partition(int arr[], int low, int high) {
int pivot = arr[high]; // 选择最后一个元素作为基准
int i = low - 1;

for (int j = low; j < high; j++) {
if (arr[j] <= pivot) {
i++;
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}

int temp = arr[i + 1];
arr[i + 1] = arr[high];
arr[high] = temp;

return i + 1;
}

// 快速排序
void quick_sort(int arr[], int low, int high) {
if (low < high) {
int pi = partition(arr, low, high);

quick_sort(arr, low, pi - 1);
quick_sort(arr, pi + 1, high);
}
}

// 三路快排(处理重复元素)
void three_way_quick_sort(int arr[], int low, int high) {
if (low >= high) return;

int lt = low, gt = high;
int pivot = arr[low];
int i = low + 1;

while (i <= gt) {
if (arr[i] < pivot) {
int temp = arr[lt];
arr[lt] = arr[i];
arr[i] = temp;
lt++;
i++;
} else if (arr[i] > pivot) {
int temp = arr[i];
arr[i] = arr[gt];
arr[gt] = temp;
gt--;
} else {
i++;
}
}

three_way_quick_sort(arr, low, lt - 1);
three_way_quick_sort(arr, gt + 1, high);
}

// 随机化快排
void randomized_quick_sort(int arr[], int low, int high) {
if (low < high) {
// 随机选择基准
int random_idx = low + rand() % (high - low + 1);
int temp = arr[random_idx];
arr[random_idx] = arr[high];
arr[high] = temp;

int pi = partition(arr, low, high);
randomized_quick_sort(arr, low, pi - 1);
randomized_quick_sort(arr, pi + 1, high);
}
}

归并排序(Merge Sort)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
// 合并函数
void merge(int arr[], int left, int mid, int right) {
int n1 = mid - left + 1;
int n2 = right - mid;

// 创建临时数组
int *left_arr = (int*)malloc(n1 * sizeof(int));
int *right_arr = (int*)malloc(n2 * sizeof(int));

// 复制数据到临时数组
for (int i = 0; i < n1; i++) {
left_arr[i] = arr[left + i];
}
for (int j = 0; j < n2; j++) {
right_arr[j] = arr[mid + 1 + j];
}

// 合并临时数组
int i = 0, j = 0, k = left;

while (i < n1 && j < n2) {
if (left_arr[i] <= right_arr[j]) {
arr[k] = left_arr[i];
i++;
} else {
arr[k] = right_arr[j];
j++;
}
k++;
}

// 复制剩余元素
while (i < n1) {
arr[k] = left_arr[i];
i++;
k++;
}

while (j < n2) {
arr[k] = right_arr[j];
j++;
k++;
}

free(left_arr);
free(right_arr);
}

// 归并排序
void merge_sort(int arr[], int left, int right) {
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);
}
}

// 自底向上的归并排序(迭代版本)
void merge_sort_iterative(int arr[], int n) {
int *temp = (int*)malloc(n * sizeof(int));

for (int size = 1; size < n; size *= 2) {
for (int left = 0; left < n - size; left += 2 * size) {
int mid = left + size - 1;
int right = (left + 2 * size - 1 < n - 1) ? left + 2 * size - 1 : n - 1;

// 合并 arr[left...mid] 和 arr[mid+1...right]
int i = left, j = mid + 1, k = left;

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 (int i = left; i <= right; i++) {
arr[i] = temp[i];
}
}
}

free(temp);
}

堆排序(Heap Sort)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// 堆化函数
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 temp = arr[i];
arr[i] = arr[largest];
arr[largest] = temp;

// 递归堆化受影响的子树
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);
}
}

1.3 特殊排序算法

计数排序(Counting Sort)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 计数排序(适用于范围较小的整数)
void counting_sort(int arr[], int n, int max_val) {
int *count = (int*)calloc(max_val + 1, sizeof(int));
int *output = (int*)malloc(n * sizeof(int));

// 统计每个元素的出现次数
for (int i = 0; i < n; i++) {
count[arr[i]]++;
}

// 计算累积计数
for (int i = 1; i <= max_val; i++) {
count[i] += count[i - 1];
}

// 构建输出数组
for (int i = n - 1; i >= 0; i--) {
output[count[arr[i]] - 1] = arr[i];
count[arr[i]]--;
}

// 复制回原数组
for (int i = 0; i < n; i++) {
arr[i] = output[i];
}

free(count);
free(output);
}

基数排序(Radix Sort)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// 获取数字的最大位数
int get_max_digits(int arr[], int n) {
int max_val = arr[0];
for (int i = 1; i < n; i++) {
if (arr[i] > max_val) {
max_val = arr[i];
}
}

int digits = 0;
while (max_val > 0) {
digits++;
max_val /= 10;
}

return digits;
}

// 按指定位进行计数排序
void counting_sort_by_digit(int arr[], int n, int exp) {
int output[n];
int count[10] = {0};

// 统计每个数字的出现次数
for (int i = 0; i < n; i++) {
count[(arr[i] / exp) % 10]++;
}

// 计算累积计数
for (int i = 1; i < 10; i++) {
count[i] += count[i - 1];
}

// 构建输出数组
for (int i = n - 1; i >= 0; i--) {
output[count[(arr[i] / exp) % 10] - 1] = arr[i];
count[(arr[i] / exp) % 10]--;
}

// 复制回原数组
for (int i = 0; i < n; i++) {
arr[i] = output[i];
}
}

// 基数排序
void radix_sort(int arr[], int n) {
int max_digits = get_max_digits(arr, n);

for (int exp = 1; max_digits > 0; exp *= 10, max_digits--) {
counting_sort_by_digit(arr, n, exp);
}
}

桶排序(Bucket Sort)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <math.h>

// 桶排序(适用于均匀分布的浮点数)
void bucket_sort(float arr[], int n) {
// 创建桶
int bucket_count = n;
float **buckets = (float**)malloc(bucket_count * sizeof(float*));
int *bucket_sizes = (int*)calloc(bucket_count, sizeof(int));

for (int i = 0; i < bucket_count; i++) {
buckets[i] = (float*)malloc(n * sizeof(float));
}

// 将元素分配到桶中
for (int i = 0; i < n; i++) {
int bucket_idx = (int)(bucket_count * arr[i]);
if (bucket_idx >= bucket_count) bucket_idx = bucket_count - 1;

buckets[bucket_idx][bucket_sizes[bucket_idx]++] = arr[i];
}

// 对每个桶进行排序(这里使用插入排序)
for (int i = 0; i < bucket_count; i++) {
if (bucket_sizes[i] > 0) {
// 简单的插入排序
for (int j = 1; j < bucket_sizes[i]; j++) {
float key = buckets[i][j];
int k = j - 1;

while (k >= 0 && buckets[i][k] > key) {
buckets[i][k + 1] = buckets[i][k];
k--;
}

buckets[i][k + 1] = key;
}
}
}

// 合并桶中的元素
int index = 0;
for (int i = 0; i < bucket_count; i++) {
for (int j = 0; j < bucket_sizes[i]; j++) {
arr[index++] = buckets[i][j];
}
free(buckets[i]);
}

free(buckets);
free(bucket_sizes);
}

2. 查找算法

2.1 线性查找

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 线性查找
int linear_search(int arr[], int n, int target) {
for (int i = 0; i < n; i++) {
if (arr[i] == target) {
return i;
}
}
return -1; // 未找到
}

// 哨兵线性查找
int sentinel_linear_search(int arr[], int n, int target) {
int last = arr[n - 1];
arr[n - 1] = target;

int i = 0;
while (arr[i] != target) {
i++;
}

arr[n - 1] = last;

if (i < n - 1 || arr[n - 1] == target) {
return i;
}

return -1;
}

2.2 二分查找

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// 标准二分查找
int binary_search(int arr[], int n, int target) {
int left = 0, right = n - 1;

while (left <= right) {
int mid = left + (right - left) / 2;

if (arr[mid] == target) {
return mid;
} else if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}

return -1;
}

// 递归二分查找
int binary_search_recursive(int arr[], int left, int right, int target) {
if (left <= right) {
int mid = left + (right - left) / 2;

if (arr[mid] == target) {
return mid;
} else if (arr[mid] < target) {
return binary_search_recursive(arr, mid + 1, right, target);
} else {
return binary_search_recursive(arr, left, mid - 1, target);
}
}

return -1;
}

// 查找第一个出现的位置
int binary_search_first(int arr[], int n, int target) {
int left = 0, right = n - 1;
int result = -1;

while (left <= right) {
int mid = left + (right - left) / 2;

if (arr[mid] == target) {
result = mid;
right = mid - 1; // 继续在左半部分查找
} else if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}

return result;
}

// 查找最后一个出现的位置
int binary_search_last(int arr[], int n, int target) {
int left = 0, right = n - 1;
int result = -1;

while (left <= right) {
int mid = left + (right - left) / 2;

if (arr[mid] == target) {
result = mid;
left = mid + 1; // 继续在右半部分查找
} else if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}

return result;
}

// 查找插入位置
int binary_search_insert_position(int arr[], int n, int target) {
int left = 0, right = n - 1;

while (left <= right) {
int mid = left + (right - left) / 2;

if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}

return left;
}

2.3 插值查找

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 插值查找(适用于均匀分布的有序数组)
int interpolation_search(int arr[], int n, int target) {
int left = 0, right = n - 1;

while (left <= right && target >= arr[left] && target <= arr[right]) {
if (left == right) {
return (arr[left] == target) ? left : -1;
}

// 计算插值位置
int pos = left + ((double)(target - arr[left]) / (arr[right] - arr[left])) * (right - left);

if (arr[pos] == target) {
return pos;
} else if (arr[pos] < target) {
left = pos + 1;
} else {
right = pos - 1;
}
}

return -1;
}

2.4 指数查找

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 指数查找
int exponential_search(int arr[], int n, int target) {
if (arr[0] == target) {
return 0;
}

// 找到范围
int bound = 1;
while (bound < n && arr[bound] <= target) {
bound *= 2;
}

// 在找到的范围内进行二分查找
int left = bound / 2;
int right = (bound < n) ? bound : n - 1;

return binary_search_recursive(arr, left, right, target);
}

2.5 跳跃查找

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <math.h>

// 跳跃查找
int jump_search(int arr[], int n, int target) {
int step = sqrt(n);
int prev = 0;

// 找到目标可能存在的块
while (arr[(step < n ? step : n) - 1] < target) {
prev = step;
step += sqrt(n);
if (prev >= n) {
return -1;
}
}

// 在块内进行线性查找
while (arr[prev] < target) {
prev++;
if (prev == (step < n ? step : n)) {
return -1;
}
}

if (arr[prev] == target) {
return prev;
}

return -1;
}

3. 算法工具库

3.1 通用排序接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// 排序算法枚举
typedef enum {
SORT_BUBBLE,
SORT_SELECTION,
SORT_INSERTION,
SORT_SHELL,
SORT_QUICK,
SORT_MERGE,
SORT_HEAP,
SORT_COUNTING,
SORT_RADIX
} SortAlgorithm;

// 比较函数类型
typedef int (*compare_func_t)(const void *a, const void *b);

// 通用排序函数
void sort_array(void *arr, size_t n, size_t element_size,
SortAlgorithm algorithm, compare_func_t compare) {
switch (algorithm) {
case SORT_QUICK:
qsort(arr, n, element_size, compare);
break;
case SORT_MERGE:
// 调用归并排序实现
break;
// 其他算法...
default:
fprintf(stderr, "不支持的排序算法\n");
}
}

// 整数比较函数
int int_compare(const void *a, const void *b) {
int ia = *(const int*)a;
int ib = *(const int*)b;
return (ia > ib) - (ia < ib);
}

// 字符串比较函数
int string_compare(const void *a, const void *b) {
return strcmp(*(const char**)a, *(const char**)b);
}

3.2 性能测试工具

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <time.h>
#include <sys/time.h>

// 高精度计时器
double get_time() {
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec + tv.tv_usec / 1000000.0;
}

// 排序算法性能测试
void benchmark_sort_algorithm(void (*sort_func)(int[], int),
const char *algorithm_name,
int arr[], int n) {
int *test_arr = (int*)malloc(n * sizeof(int));
memcpy(test_arr, arr, n * sizeof(int));

double start_time = get_time();
sort_func(test_arr, n);
double end_time = get_time();

printf("%s: %.6f 秒\n", algorithm_name, end_time - start_time);

// 验证排序结果
bool is_sorted = true;
for (int i = 1; i < n; i++) {
if (test_arr[i] < test_arr[i - 1]) {
is_sorted = false;
break;
}
}

printf("排序结果: %s\n", is_sorted ? "正确" : "错误");
free(test_arr);
}

// 综合性能测试
void run_sort_benchmarks(int n) {
printf("=== 排序算法性能测试 (数组大小: %d) ===\n", n);

// 生成测试数据
int *original_arr = (int*)malloc(n * sizeof(int));
srand(time(NULL));

for (int i = 0; i < n; i++) {
original_arr[i] = rand() % 10000;
}

// 测试各种排序算法
benchmark_sort_algorithm(bubble_sort, "冒泡排序", original_arr, n);
benchmark_sort_algorithm(selection_sort, "选择排序", original_arr, n);
benchmark_sort_algorithm(insertion_sort, "插入排序", original_arr, n);
benchmark_sort_algorithm(shell_sort, "希尔排序", original_arr, n);

// 对于快排和归并排序,需要包装函数
void quick_sort_wrapper(int arr[], int n) {
quick_sort(arr, 0, n - 1);
}

void merge_sort_wrapper(int arr[], int n) {
merge_sort(arr, 0, n - 1);
}

benchmark_sort_algorithm(quick_sort_wrapper, "快速排序", original_arr, n);
benchmark_sort_algorithm(merge_sort_wrapper, "归并排序", original_arr, n);
benchmark_sort_algorithm(heap_sort, "堆排序", original_arr, n);

free(original_arr);
}

3.3 数组工具函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
// 数组工具函数
void print_array(int arr[], int n, const char *title) {
printf("%s: ", title);
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}

// 检查数组是否已排序
bool is_sorted(int arr[], int n) {
for (int i = 1; i < n; i++) {
if (arr[i] < arr[i - 1]) {
return false;
}
}
return true;
}

// 生成随机数组
void generate_random_array(int arr[], int n, int min_val, int max_val) {
for (int i = 0; i < n; i++) {
arr[i] = min_val + rand() % (max_val - min_val + 1);
}
}

// 生成已排序数组
void generate_sorted_array(int arr[], int n) {
for (int i = 0; i < n; i++) {
arr[i] = i;
}
}

// 生成逆序数组
void generate_reverse_sorted_array(int arr[], int n) {
for (int i = 0; i < n; i++) {
arr[i] = n - 1 - i;
}
}

// 数组复制
void copy_array(int dest[], const int src[], int n) {
for (int i = 0; i < n; i++) {
dest[i] = src[i];
}
}

// 数组反转
void reverse_array(int arr[], int n) {
for (int i = 0; i < n / 2; i++) {
int temp = arr[i];
arr[i] = arr[n - 1 - i];
arr[n - 1 - i] = temp;
}
}

// 数组洗牌(Fisher-Yates算法)
void shuffle_array(int arr[], int n) {
for (int i = n - 1; i > 0; i--) {
int j = rand() % (i + 1);
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}

4. 实际应用示例

4.1 多关键字排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 学生结构体
typedef struct {
char name[50];
int age;
float score;
} Student;

// 按分数降序,年龄升序排序
int student_compare(const void *a, const void *b) {
const Student *sa = (const Student*)a;
const Student *sb = (const Student*)b;

// 首先按分数降序
if (sa->score != sb->score) {
return (sa->score < sb->score) - (sa->score > sb->score);
}

// 分数相同时按年龄升序
return (sa->age > sb->age) - (sa->age < sb->age);
}

void sort_students(Student students[], int n) {
qsort(students, n, sizeof(Student), student_compare);
}

4.2 外部排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// 简单的外部排序实现(适用于大文件)
void external_sort(const char *input_file, const char *output_file,
int memory_limit) {
FILE *input = fopen(input_file, "r");
if (!input) {
perror("无法打开输入文件");
return;
}

int chunk_size = memory_limit / sizeof(int);
int *buffer = (int*)malloc(chunk_size * sizeof(int));
int chunk_count = 0;

// 第一阶段:分块排序
while (1) {
int count = 0;

// 读取一块数据
while (count < chunk_size && fscanf(input, "%d", &buffer[count]) == 1) {
count++;
}

if (count == 0) break;

// 排序当前块
qsort(buffer, count, sizeof(int), int_compare);

// 写入临时文件
char temp_filename[100];
sprintf(temp_filename, "temp_%d.dat", chunk_count);

FILE *temp_file = fopen(temp_filename, "w");
for (int i = 0; i < count; i++) {
fprintf(temp_file, "%d\n", buffer[i]);
}
fclose(temp_file);

chunk_count++;
}

fclose(input);
free(buffer);

// 第二阶段:多路归并
// 这里简化实现,实际应用中需要使用优先队列
// ...
}

5. 算法选择指南

5.1 排序算法选择

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 智能排序算法选择
void smart_sort(int arr[], int n) {
if (n <= 1) return;

if (n <= 10) {
// 小数组使用插入排序
insertion_sort(arr, n);
} else if (n <= 1000) {
// 中等数组使用快速排序
quick_sort(arr, 0, n - 1);
} else {
// 大数组使用归并排序(稳定)
merge_sort(arr, 0, n - 1);
}
}

// 根据数据特征选择算法
void adaptive_sort(int arr[], int n) {
// 检查数组是否已经基本有序
int inversions = 0;
for (int i = 1; i < n && inversions < n / 4; i++) {
if (arr[i] < arr[i - 1]) {
inversions++;
}
}

if (inversions < n / 10) {
// 基本有序,使用插入排序
insertion_sort(arr, n);
} else {
// 无序程度较高,使用快速排序
quick_sort(arr, 0, n - 1);
}
}

5.2 查找算法选择

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 智能查找
int smart_search(int arr[], int n, int target, bool is_sorted) {
if (n <= 0) return -1;

if (!is_sorted) {
return linear_search(arr, n, target);
}

if (n <= 100) {
// 小数组直接线性查找
return linear_search(arr, n, target);
} else {
// 大数组使用二分查找
return binary_search(arr, n, target);
}
}

总结

本文详细介绍了各种经典的排序和查找算法的C语言实现,包括:

排序算法:

  • 简单排序:冒泡、选择、插入、希尔排序
  • 高效排序:快速、归并、堆排序
  • 特殊排序:计数、基数、桶排序

查找算法:

  • 线性查找及其优化
  • 二分查找及其变种
  • 插值、指数、跳跃查找

关键要点:

  1. 算法选择 - 根据数据规模和特征选择合适的算法
  2. 性能优化 - 理解算法的时间和空间复杂度
  3. 实际应用 - 结合具体场景进行算法优化
  4. 代码质量 - 注重错误处理和内存管理

掌握这些基础算法的实现原理和优化技巧,是成为优秀程序员的重要基础。

版权所有,如有侵权请联系我