C语言常用算法深度解析:从基础到高级的实战艺术

目录

一、C语言算法设计的核心哲学

[1.1 C语言算法的独特魅力](#1.1 C语言算法的独特魅力)

[1.2 算法复杂度分析的C语言视角](#1.2 算法复杂度分析的C语言视角)

二、基础算法实战

[2.1 查找算法:从线性到二分](#2.1 查找算法:从线性到二分)

[2.2 排序算法:手写经典实现](#2.2 排序算法:手写经典实现)

三、数值计算算法

[3.1 数学函数实现](#3.1 数学函数实现)

[3.2 随机数生成算法](#3.2 随机数生成算法)

四、字符串处理算法

[4.1 字符串匹配算法](#4.1 字符串匹配算法)

五、数据结构相关算法

[5.1 链表算法](#5.1 链表算法)

[5.2 树算法](#5.2 树算法)

六、动态规划算法

[6.1 经典DP问题](#6.1 经典DP问题)

[6.2 路径规划算法](#6.2 路径规划算法)


如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。

一、C语言算法设计的核心哲学

1.1 C语言算法的独特魅力

C语言算法的核心在于贴近硬件、控制精确、效率至上。与高级语言不同,C语言算法设计需要:

  • 手动内存管理:每个字节都要心中有数
  • 指针操作艺术:直接内存访问,威力与风险并存
  • 零开销抽象:不依赖运行时,性能可预测
  • 跨平台兼容:编写可移植的高效算法

1.2 算法复杂度分析的C语言视角

// 时间复杂度直观理解

O(1) → 直接数组访问 arr[i]

O(log n) → 二分查找

O(n) → 线性遍历链表

O(n log n)→ 快速排序

O(n²) → 冒泡排序

O(2ⁿ) → 汉诺塔递归

// 空间复杂度考量

// C语言需要显式管理栈和堆内存

void recursive_func(int n) {

int local_var; // 栈空间:O(1) per call

int* heap_mem = malloc(n * sizeof(int)); // 堆空间:O(n)

// 递归调用栈深度影响总空间复杂度

}

二、基础算法实战

2.1 查找算法:从线性到二分

// 1. 线性查找:通用但低效

int linear_search(int arr[], int n, int target) {

for (int i = 0; i < n; i++) {

if (arr[i] == target) {

return i; // 返回索引

}

}

return -1; // 未找到

}

// 2. 二分查找:有序数组的利器

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;

}

// 3. 插值查找:均匀分布数据的优化

int interpolation_search(int arr[], int n, int target) {

int low = 0, high = n - 1;

while (low <= high && target >= arr[low] && target <= arr[high]) {

if (low == high) {

return (arr[low] == target) ? low : -1;

}

// 关键:使用插值公式估算位置

int pos = low + ((double)(high - low) /

(arr[high] - arr[low])) * (target - arr[low]);

if (arr[pos] == target) {

return pos;

} else if (arr[pos] < target) {

low = pos + 1;

} else {

high = pos - 1;

}

}

return -1;

}

2.2 排序算法:手写经典实现

// 1. 冒泡排序:教学意义大于实用

void bubble_sort(int arr[], int n) {

for (int i = 0; i < n - 1; i++) {

int swapped = 0; // 优化:检查是否已排序

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 = 1;

}

}

if (!swapped) break; // 提前终止

}

}

// 2. 快速排序:分治思想的典范

void quick_sort(int arr[], int low, int high) {

if (low < high) {

// 分区操作

int pivot = partition(arr, low, high);

// 递归排序左右两部分

quick_sort(arr, low, pivot - 1);

quick_sort(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++;

// 交换arr[i]和arr[j]

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;

}

// 3. 归并排序:稳定排序的代表

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(int arr[], int left, int mid, int right) {

int n1 = mid - left + 1;

int n2 = right - mid;

// 创建临时数组

int* L = malloc(n1 * sizeof(int));

int* R = malloc(n2 * sizeof(int));

// 复制数据

for (int i = 0; i < n1; i++) L[i] = arr[left + i];

for (int j = 0; j < n2; j++) R[j] = arr[mid + 1 + j];

// 合并临时数组

int i = 0, j = 0, k = left;

while (i < n1 && j < n2) {

if (L[i] <= R[j]) {

arr[k] = L[i];

i++;

} else {

arr[k] = R[j];

j++;

}

k++;

}

// 复制剩余元素

while (i < n1) arr[k++] = L[i++];

while (j < n2) arr[k++] = R[j++];

free(L);

free(R);

}

三、数值计算算法

3.1 数学函数实现

// 1. 平方根算法:牛顿迭代法

double sqrt_newton(double x, double epsilon) {

if (x < 0) return -1.0; // 错误处理

double guess = x / 2.0;

double prev_guess;

do {

prev_guess = guess;

guess = (guess + x / guess) / 2.0;

} while (fabs(guess - prev_guess) > epsilon);

return guess;

}

// 2. 幂运算:快速幂算法

double power(double base, int exponent) {

if (exponent == 0) return 1.0;

if (exponent == 1) return base;

double result = 1.0;

double current = base;

int exp = abs(exponent);

while (exp > 0) {

if (exp & 1) { // 当前位为1

result *= current;

}

current *= current; // 平方

exp >>= 1; // 右移一位

}

return (exponent > 0) ? result : 1.0 / result;

}

// 3. 最大公约数:欧几里得算法

int gcd(int a, int b) {

while (b != 0) {

int temp = b;

b = a % b;

a = temp;

}

return a;

}

// 扩展欧几里得算法:求解ax + by = gcd(a,b)

struct ExtendedGCD {

int gcd;

int x;

int y;

};

struct ExtendedGCD extended_gcd(int a, int b) {

if (b == 0) {

return (struct ExtendedGCD){a, 1, 0};

}

struct ExtendedGCD result = extended_gcd(b, a % b);

return (struct ExtendedGCD){

result.gcd,

result.y,

result.x - (a / b) * result.y

};

}

3.2 随机数生成算法

// 线性同余生成器(LCG)

unsigned long lcg_seed = 1;

unsigned int lcg_rand() {

// 常用参数:a=1664525, c=1013904223, m=2^32

lcg_seed = (1664525UL * lcg_seed + 1013904223UL) & 0xFFFFFFFF;

return (unsigned int)(lcg_seed >> 16); // 返回高16位

}

// 梅森旋转算法(简化版)

#define MT_N 624

#define MT_M 397

static unsigned long mt[MT_N];

static int mt_index = MT_N + 1;

void mt_init(unsigned long seed) {

mt[0] = seed & 0xFFFFFFFFUL;

for (int i = 1; i < MT_N; i++) {

mt[i] = (1812433253UL * (mt[i-1] ^ (mt[i-1] >> 30)) + i) & 0xFFFFFFFFUL;

}

mt_index = MT_N;

}

unsigned long mt_rand() {

if (mt_index >= MT_N) {

// 生成新的一批随机数

static unsigned long mag01[2] = {0x0UL, 0x9908B0DFUL};

for (int i = 0; i < MT_N; i++) {

unsigned long y = (mt[i] & 0x80000000UL) | (mt[(i+1) % MT_N] & 0x7FFFFFFFUL);

mt[i] = mt[(i+MT_M) % MT_N] ^ (y >> 1) ^ mag01[y & 0x1UL];

}

mt_index = 0;

}

unsigned long y = mt[mt_index++];

// 温度变换

y ^= (y >> 11);

y ^= (y << 7) & 0x9D2C5680UL;

y ^= (y << 15) & 0xEFC60000UL;

y ^= (y >> 18);

return y;

}

四、字符串处理算法

4.1 字符串匹配算法

// 1. 朴素字符串匹配

int naive_search(const char* text, const char* pattern) {

int n = strlen(text);

int m = strlen(pattern);

for (int i = 0; i <= n - m; i++) {

int j;

for (j = 0; j < m; j++) {

if (text[i + j] != pattern[j]) {

break;

}

}

if (j == m) {

return i; // 找到匹配

}

}

return -1; // 未找到

}

// 2. KMP算法:高效字符串匹配

void compute_lps(const char* pattern, int m, int* lps) {

int len = 0; // 最长前缀后缀长度

lps[0] = 0;

int i = 1;

while (i < m) {

if (pattern[i] == pattern[len]) {

len++;

lps[i] = len;

i++;

} else {

if (len != 0) {

len = lps[len - 1];

} else {

lps[i] = 0;

i++;

}

}

}

}

int kmp_search(const char* text, const char* pattern) {

int n = strlen(text);

int m = strlen(pattern);

int* lps = malloc(m * sizeof(int));

compute_lps(pattern, m, lps);

int i = 0; // text的索引

int j = 0; // pattern的索引

while (i < n) {

if (pattern[j] == text[i]) {

i++;

j++;

}

if (j == m) {

free(lps);

return i - j; // 找到匹配

} else if (i < n && pattern[j] != text[i]) {

if (j != 0) {

j = lps[j - 1];

} else {

i++;

}

}

}

free(lps);

return -1; // 未找到

}

// 3. 字符串编辑距离(Levenshtein距离)

int edit_distance(const char* str1, const char* str2) {

int m = strlen(str1);

int n = strlen(str2);

// 创建DP表

int** dp = malloc((m + 1) * sizeof(int*));

for (int i = 0; i <= m; i++) {

dp[i] = malloc((n + 1) * sizeof(int));

}

// 初始化边界条件

for (int i = 0; i <= m; i++) dp[i][0] = i;

for (int j = 0; j <= n; j++) dp[0][j] = j;

// 填充DP表

for (int i = 1; i <= m; i++) {

for (int j = 1; j <= n; j++) {

if (str1[i-1] == str2[j-1]) {

dp[i][j] = dp[i-1][j-1]; // 字符相同

} else {

int insert = dp[i][j-1] + 1;

int delete = dp[i-1][j] + 1;

int replace = dp[i-1][j-1] + 1;

dp[i][j] = (insert < delete) ?

((insert < replace) ? insert : replace) :

((delete < replace) ? delete : replace);

}

}

}

int result = dp[m][n];

// 清理内存

for (int i = 0; i <= m; i++) free(dp[i]);

free(dp);

return result;

}

五、数据结构相关算法

5.1 链表算法

typedef struct Node {

int data;

struct Node* next;

} Node;

// 1. 链表反转(迭代法)

Node* reverse_list_iterative(Node* head) {

Node* prev = NULL;

Node* current = head;

Node* next = NULL;

while (current != NULL) {

next = current->next; // 保存下一个节点

current->next = prev; // 反转指针

prev = current; // 移动prev

current = next; // 移动current

}

return prev; // 新的头节点

}

// 2. 链表反转(递归法)

Node* reverse_list_recursive(Node* head) {

if (head == NULL || head->next == NULL) {

return head;

}

Node* new_head = reverse_list_recursive(head->next);

head->next->next = head;

head->next = NULL;

return new_head;

}

// 3. 检测链表环(Floyd判圈算法)

int has_cycle(Node* head) {

if (head == NULL || head->next == NULL) {

return 0;

}

Node* slow = head;

Node* fast = head;

while (fast != NULL && fast->next != NULL) {

slow = slow->next; // 每次走一步

fast = fast->next->next; // 每次走两步

if (slow == fast) {

return 1; // 有环

}

}

return 0; // 无环

}

// 4. 合并两个有序链表

Node* merge_sorted_lists(Node* l1, Node* l2) {

// 创建哑节点简化代码

Node dummy;

Node* tail = &dummy;

dummy.next = NULL;

while (l1 != NULL && l2 != NULL) {

if (l1->data <= l2->data) {

tail->next = l1;

l1 = l1->next;

} else {

tail->next = l2;

l2 = l2->next;

}

tail = tail->next;

}

// 连接剩余部分

tail->next = (l1 != NULL) ? l1 : l2;

return dummy.next;

}

5.2 树算法

typedef struct TreeNode {

int value;

struct TreeNode* left;

struct TreeNode* right;

} TreeNode;

// 1. 二叉树遍历(递归版)

void inorder_traversal(TreeNode* root) {

if (root == NULL) return;

inorder_traversal(root->left);

printf("%d ", root->value);

inorder_traversal(root->right);

}

void preorder_traversal(TreeNode* root) {

if (root == NULL) return;

printf("%d ", root->value);

preorder_traversal(root->left);

preorder_traversal(root->right);

}

void postorder_traversal(TreeNode* root) {

if (root == NULL) return;

postorder_traversal(root->left);

postorder_traversal(root->right);

printf("%d ", root->value);

}

// 2. 二叉树遍历(迭代版,使用栈)

void inorder_iterative(TreeNode* root) {

TreeNode* stack[100];

int top = -1;

TreeNode* current = root;

while (current != NULL || top != -1) {

// 遍历到最左节点

while (current != NULL) {

stack[++top] = current;

current = current->left;

}

// 弹出并访问

current = stack[top--];

printf("%d ", current->value);

// 转向右子树

current = current->right;

}

}

// 3. 二叉树高度计算

int tree_height(TreeNode* root) {

if (root == NULL) {

return 0;

}

int left_height = tree_height(root->left);

int right_height = tree_height(root->right);

return (left_height > right_height ? left_height : right_height) + 1;

}

// 4. 二叉树镜像(反转)

void mirror_tree(TreeNode* root) {

if (root == NULL) return;

// 交换左右子树

TreeNode* temp = root->left;

root->left = root->right;

root->right = temp;

// 递归处理子树

mirror_tree(root->left);

mirror_tree(root->right);

}

六、动态规划算法

6.1 经典DP问题

// 1. 斐波那契数列(带记忆化)

long long fibonacci(int n, long long* memo) {

if (n <= 1) return n;

if (memo[n] != -1) return memo[n];

memo[n] = fibonacci(n-1, memo) + fibonacci(n-2, memo);

return memo[n];

}

// 2. 0-1背包问题

int knapsack(int capacity, int weights[], int values[], int n) {

int** dp = malloc((n + 1) * sizeof(int*));

for (int i = 0; i <= n; i++) {

dp[i] = malloc((capacity + 1) * sizeof(int));

}

// 初始化

for (int i = 0; i <= n; i++) {

for (int w = 0; w <= capacity; w++) {

if (i == 0 || w == 0) {

dp[i][w] = 0;

} else if (weights[i-1] <= w) {

int include = values[i-1] + dp[i-1][w - weights[i-1]];

int exclude = dp[i-1][w];

dp[i][w] = (include > exclude) ? include : exclude;

} else {

dp[i][w] = dp[i-1][w];

}

}

}

int result = dp[n][capacity];

// 清理内存

for (int i = 0; i <= n; i++) free(dp[i]);

free(dp);

return result;

}

// 3. 最长公共子序列(LCS)

int lcs(const char* str1, const char* str2) {

int m = strlen(str1);

int n = strlen(str2);

int** dp = malloc((m + 1) * sizeof(int*));

for (int i = 0; i <= m; i++) {

dp[i] = malloc((n + 1) * sizeof(int));

}

for (int i = 0; i <= m; i++) {

for (int j = 0; j <= n; j++) {

if (i == 0 || j == 0) {

dp[i][j] = 0;

} else if (str1[i-1] == str2[j-1]) {

dp[i][j] = dp[i-1][j-1] + 1;

} else {

dp[i][j] = (dp[i-1][j] > dp[i][j-1]) ?

dp[i-1][j] : dp[i][j-1];

}

}

}

int result = dp[m][n];

// 清理内存

for (int i = 0; i <= m; i++) free(dp[i]);

free(dp);

return result;

}

6.2 路径规划算法

// Floyd-Warshall算法:所有顶点对的最短路径

#define INF 99999

#define V 4 // 顶点数

void floyd_warshall(int graph[V][V]) {

int dist[V][V];

// 初始化距离矩阵

for (int i = 0; i < V; i++) {

for (int j = 0; j < V; j++) {

dist[i][j] = graph[i][j];

}

}

// 动态规划核心

for (int k = 0; k < V; k++) {

for (int i = 0; i < V; i++) {

for (int j = 0; j < V; j++) {

if (dist[i][k] + dist[k][j] < dist[i][j]) {

dist[i][j] = dist[i][k] + dist[k][j];

}

}

}

}

// 打印结果

printf("最短距离矩阵:\n");

for (int i = 0; i < V; i++) {

for (int j = 0; j < V; j++) {

if (dist[i][j] == INF) {

printf("INF\t");

} else {

printf("%d\t", dist[i][j]);

}

}

printf("\n");

}

}

希望以上内容对你有帮助。

如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。

相关推荐
LYS_06182 小时前
RM专用赛事c型板IMU9轴解算(1)(对于IST8310和BMI088的直接使用)
c语言·开发语言
C++ 老炮儿的技术栈10 小时前
在C++ 程序中调用被 C编译器编译后的函数,为什么要加 extern “C”声明?
c语言·c++·windows·git·vscode·visual studio
CQ_YM13 小时前
ARM--SDK、led、beep与链接脚本
c语言·arm开发·嵌入式硬件·嵌入式
傻乐u兔15 小时前
C语音初阶————调试实用技巧2
c语言·开发语言
颜子鱼18 小时前
Linux驱动-INPUT子系统
linux·c语言·驱动开发
星迹7020 小时前
C语言相关的数电知识
c语言·开发语言
半条-咸鱼21 小时前
C语言基础语法+STM32实践学习笔记 | 指针/寄存器核心应用
c语言·stm32·学习·嵌入式
彭泽布衣21 小时前
gdb调试方法总结
linux·c语言·gdb·故障排查·段错误
lingran__21 小时前
C语言动态内存管理详解
c语言·开发语言