19 经典算法实现

在前一篇中,我们讨论了树与图的基本概念和操作,包括二叉树的遍历和图的搜索算法。这一篇将深入探讨一些经典算法,并通过C语言实现它们。这些算法在算法竞赛、面试以及实际开发中扮演着重要角色。

1. 排序算法

排序是数据结构与算法中非常基础且重要的一部分。这里我们介绍几种经典的排序算法,包括快速排序、归并排序和冒泡排序。

1.1 冒泡排序

冒泡排序是一种简单的排序算法,通过重复遍历要排序的列表,比较每对相邻元素并交换它们的位置,如果它们的顺序错误。

1
2
3
4
5
6
7
8
9
10
11
12
void bubbleSort(int arr[], int n) {
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
// 交换
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}

1.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
void quickSort(int arr[], int low, int high) {
if (low < high) {
int pivot = partition(arr, low, high);
quickSort(arr, low, pivot - 1);
quickSort(arr, pivot + 1, high);
}
}

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;
}

1.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
void mergeSort(int arr[], int left, int right) {
if (left < right) {
int mid = left + (right - left) / 2;
mergeSort(arr, left, mid);
mergeSort(arr, mid + 1, right);
merge(arr, left, mid, right);
}
}

void merge(int arr[], int left, int mid, int right) {
int i = left, j = mid + 1, 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];
}
}

2. 查找算法

查找算法用于在数据结构中查找某个元素,这里介绍线性查找和二分查找。

2.1 线性查找

线性查找是最简单的查找方法,通过逐个检查每一个元素来寻找目标值。如果找到,则返回该元素的索引,否则返回-1。

1
2
3
4
5
6
7
8
int linearSearch(int arr[], int n, int target) {
for (int i = 0; i < n; i++) {
if (arr[i] == target) {
return i; // 找到目标
}
}
return -1; // 未找到
}

2.2 二分查找

二分查找是一种高效的查找算法,前提是数组必须是已排序的。它通过不断地将查找范围减半来查找目标值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int binarySearch(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; // 找到目标
}
if (arr[mid] < target) {
left = mid + 1; // 在右半边
} else {
right = mid - 1; // 在左半边
}
}
return -1; // 未找到
}

3. 动态规划

动态规划是一种将复杂问题分解成更简单子问题的方法,它通常用于寻找最优解。这里以“斐波那契数列”为例。

3.1 斐波那契数列

斐波那契数列的定义为:

$$
F(n) = F(n-1) + F(n-2), \quad F(0) = 0, \quad F(1) = 1
$$

使用动态规划来解决斐波那契数列。

1
2
3
4
5
6
7
8
9
10
11
12
int fib(int n) {
if (n <= 1) return n;

int dp[n + 1];
dp[0] = 0;
dp[1] = 1;

for (int i = 2; i <= n; i++) {
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[n];
}

4. 示例与总结

通过对这些经典算法的理解和实现,我们不仅掌握了常用的算法思想,还能够在实际应用中灵活运用。下面是一个简单的示例,演示如何使用上述的排序和查找算法。

#include <stdio.h>

int main() {
    int arr[] = {64, 34, 25, 12, 22, 11, 90};
    int n = sizeof(arr)/sizeof(arr[0]);

    // 排序数组
    bubbleSort(arr, n);
作者

IT教程网(郭震)

发布于

2024-08-10

更新于

2024-08-10

许可协议

分享转发

交流

更多教程加公众号

更多教程加公众号

加入星球获取PDF

加入星球获取PDF

打卡评论