当前位置: 首页 > news >正文

C语言学习知识点总结(适合新手/考试复习)

C语言学习知识点总结(适合新手/考试复习)

🎯 写在前面:这份学习笔记是我在学习C语言过程中的心得体会。作为一名曾经的编程小白,我深知学习编程的不易。因此,我尽量用通俗易懂的语言,结合实际例子,帮助大家更好地理解C语言。

C语言知识点总结

  • C语言学习知识点总结(适合新手/考试复习)
    • 第一部分:C语言基础
      • 1. 初识C语言
        • 1.1 第一个C程序
        • 1.2 基本数据类型
        • 1.3 格式化输入输出
      • 2. 运算符与表达式
        • 2.1 基本运算符
        • 2.2 关系运算符和逻辑运算符
        • 2.3 赋值运算符和条件运算符
      • 3. 程序流程控制
        • 3.1 条件语句
        • 3.2 循环语句
      • 4. 数组
        • 4.1 一维数组基础
        • 4.2 二维数组
        • 4.3 数组的高级应用
      • 5. 函数
        • 5.1 函数基础
        • 5.2 函数高级特性
        • 5.3 函数优化技术
      • 6. 指针
        • 6.1 指针基础
        • 6.2 指针的高级应用
        • 6.3 指针的安全性和优化
      • 7. 结构体和共用体
        • 7.1 结构体基础
        • 7.2 结构体的高级特性
        • 7.3 共用体和枚举
      • 8. 文件操作
        • 8.1 文件的基本操作
        • 8.2 文本文件操作
        • 8.3 二进制文件操作
        • 8.4 高级文件操作
    • 第二部分:进阶知识点
      • 1. 预处理指令
        • 1.1 预处理器基础
        • 1.2 高级预处理技术
        • 1.3 预处理器最佳实践
      • 2. 动态内存分配
        • 2.1 内存分配基础
        • 2.2 高级内存管理
        • 2.3 内存管理最佳实践
      • 3. 位运算
        • 3.1 基本位运算
        • 3.2 位运算技巧
        • 3.3 位运算高级应用
      • 4. 排序算法
        • 4.1 基本排序算法
        • 4.2 高级排序算法
        • 4.3 排序算法的比较和应用
      • 5. 查找算法
        • 5.1 静态查找
        • 5.2 动态查找
        • 5.3 哈希查找
      • 6. 字符串算法
        • 6.1 字符串反转
        • 6.2 KMP字符串匹配
      • 7. 数学算法
        • 7.1 最大公约数(GCD)
        • 7.2 素数筛选(埃氏筛)
      • 8. 图算法
        • 8.1 深度优先搜索(DFS)
        • 8.2 广度优先搜索(BFS)
      • 9. 动态规划
        • 9.1 斐波那契数列
        • 9.2 背包问题

第一部分:C语言基础

在开始学习C语言之前,我们先要理解:为什么要学习C语言?C语言是一门"古老"但强大的编程语言,它是很多其他编程语言的基础,学好C语言就像打好地基一样重要。它的特点是:

  • 语言简洁,执行效率高
  • 贴近硬件,可以直接操作内存
  • 应用广泛,从操作系统到单片机都有它的身影

1. 初识C语言

让我们从最基础的开始,就像学习任何一门新语言一样,先从"你好,世界"开始。

1.1 第一个C程序

下面这个程序可能看起来很简单,但它包含了C语言最基本的要素:

#include <stdio.h>

int main() {
    printf("Hello, World!\n");
    return 0;
}

让我们一行一行地解释这个程序:

  1. #include <stdio.h>:这是一个预处理指令,告诉编译器我们需要使用输入输出函数。就像要用微信,首先得安装它一样。
  2. int main():这是程序的入口,所有C程序都从这里开始执行。就像一本书必须有目录一样。
  3. printf():这是一个输出函数,用来在屏幕上显示文字。
  4. return 0:告诉系统程序正常结束了。

🌟 初学者常见问题:

  • 忘记写分号(;)
  • main函数名写错(比如写成Main)
  • 忘记引入stdio.h就使用printf
  • 字符串忘记加双引号
1.2 基本数据类型

在C语言中,数据类型就像是不同的容器,用来存放不同类型的数据。就像我们生活中用不同的容器来存放不同的东西:水要用水杯,饭要用饭盒。

#include <stdio.h>

int main() {
    // 整型:用来存储整数
    int a = 10;          // 最常用的整数类型,比如年龄
    short b = 20;        // 短整数,节省内存空间
    long c = 30L;        // 长整数,可以存储更大的数
    
    // 浮点型:用来存储小数
    float d = 3.14f;     // 单精度浮点数,比如身高
    double e = 3.14159;  // 双精度浮点数,比如圆周率
    
    // 字符型:用来存储单个字符
    char f = 'A';        // 字符,比如等级(A、B、C)
    
    // 输出各种类型的值
    printf("整数:%d\n", a);
    printf("浮点数:%f\n", d);
    printf("字符:%c\n", f);
    
    return 0;
}

🎯 数据类型的选择建议:

  1. 存储普通整数,用int就够了
  2. 需要小数点,用floatdouble
  3. 存储单个字符,用char
  4. 需要很大的数,才考虑用long

💡 生活中的例子:

  • 年龄:用int(不会有小数的年龄)
  • 体重:用float(需要小数点)
  • 成绩等级:用char(A、B、C、D)
  • 银行存款:用double(需要精确到分)
1.3 格式化输入输出

在C语言中,格式化输入输出就像是我们日常生活中的对话。printf是"说话",scanf是"听别人说"。让我们来看看如何让程序和用户进行友好的对话:

#include <stdio.h>

int main() {
    // 格式化输出
    int num = 123;
    float pi = 3.14159;
    char str[] = "Hello";
    
    printf("整数格式:\n");
    printf("默认右对齐:%8d\n", num);    // "     123"
    printf("左对齐:%-8d\n", num);       // "123     "
    printf("零填充:%08d\n", num);       // "00000123"
    
    printf("\n浮点数格式:\n");
    printf("默认小数点后6位:%f\n", pi);     // "3.141590"
    printf("指定精度:%.2f\n", pi);          // "3.14"
    printf("科学计数法:%e\n", pi);          // "3.141590e+00"
    
    printf("\n字符串格式:\n");
    printf("默认:%s\n", str);           // "Hello"
    printf("限制宽度:%8s\n", str);      // "   Hello"
    printf("限制长度:%.3s\n", str);     // "Hel"
}

🎨 格式控制符的妙用:

  1. 整数格式化

    • %d:最基本的整数显示,就像写数字一样
    • %8d:预留8个空格,就像在表格中对齐数字
    • %08d:用0填充空位,就像银行账号的显示方式
  2. 小数格式化

    • %f:显示小数,默认保留6位小数
    • %.2f:保留2位小数,适合显示价格
    • %e:科学计数法,适合表示很大或很小的数
  3. 字符串格式化

    • %s:显示字符串,就像写一段文字
    • %8s:控制显示宽度,适合制作表格
    • %.3s:限制显示长度,类似微博字数限制

💡 实际应用场景:

  • 显示商品价格:%.2f
  • 对齐账单数据:%8d
  • 显示百分比:%.1f%%
  • 格式化日期时间:%02d:%02d:%02d

🚫 常见错误提醒:

  1. 格式符和实际类型不匹配:

    int num = 10;
    printf("%f", num);    // 错误!整数用%d
    
  2. 忘记取地址符&:

    int age;
    scanf("%d", age);     // 错误!应该是&age
    

小技巧:

  1. 制作表格时,可以这样对齐:

    printf("姓名    年龄    成绩\n");
    printf("%-8s%4d%8.1f\n", "张三", 18, 92.5);
    printf("%-8s%4d%8.1f\n", "李四", 19, 88.0);
    
  2. 读取带空格的字符串:

    char name[50];
    printf("请输入姓名:");
    gets(name);    // 可以读取带空格的字符串
    

2. 运算符与表达式

在C语言中,运算符就像是数学中的运算符号,但功能更加强大。让我们通过生活中的例子来理解它们。

2.1 基本运算符

就像我们在小学学习的加减乘除一样,C语言中的基本运算符也很容易理解:

#include <stdio.h>

int main() {
    int a = 10, b = 3;
    
    // 算术运算符
    printf("基本运算:\n");
    printf("%d + %d = %d\n", a, b, a + b);    // 就像买东西算总价
    printf("%d - %d = %d\n", a, b, a - b);    // 就像找零钱
    printf("%d × %d = %d\n", a, b, a * b);    // 就像买3件10元的商品
    printf("%d ÷ %d = %d\n", a, b, a / b);    // 整数除法,结果取整
    printf("%d 除以 %d 的余数是:%d\n", a, b, a % b);  // 就像分苹果剩下的
    
    // 自增自减(就像计数器)
    int count = 5;
    printf("\n计数器示例:\n");
    printf("当前人数:%d\n", count);
    printf("一个人进来:%d\n", ++count);    // 先加1再使用
    printf("一个人出去:%d\n", --count);    // 先减1再使用
    
    return 0;
}

💡 生活中的例子:

  1. 加法(+):购物时计算总价
  2. 减法(-):找零钱、计算年龄差
  3. 乘法(*):计算商品总价(单价×数量)
  4. 除法(/):平均分配(10个苹果分给3个人)
  5. 取余(%):判断奇偶、计算剩余部分

⚠️ 需要注意的点:

  1. 整数除法会直接舍弃小数部分
  2. 除数不能为0
  3. 取余运算只能用于整数
2.2 关系运算符和逻辑运算符

这些运算符就像是我们生活中的判断,帮助我们做出决策:

#include <stdio.h>

int main() {
    int age = 18;
    int score = 85;
    
    // 关系运算符(就像比较大小)
    printf("年龄判断:\n");
    printf("是否成年:%d\n", age >= 18);    // 1表示是,0表示否
    printf("是否到退休年龄:%d\n", age >= 60);
    
    // 逻辑运算符(就像组合条件)
    printf("\n考试成绩评估:\n");
    // 同时满足多个条件(&&)
    printf("是否及格且表现优秀:%d\n", score >= 60 && score < 90);
    // 满足任意一个条件(||)
    printf("是否需要补考或者重修:%d\n", score < 60 || score > 100);
    
    return 0;
}

🌟 实际应用场景:

  1. 关系运算符

    • 判断年龄是否达到标准
    • 比较成绩高低
    • 检查库存是否充足
  2. 逻辑运算符

    • 判断是否满足多个条件(&&)
    • 判断是否满足任意条件(||)
    • 判断条件是否不成立(!)
2.3 赋值运算符和条件运算符

这些是C语言中的"效率工具",可以让我们的代码更简洁:

#include <stdio.h>

int main() {
    // 赋值运算符(简化写法)
    int money = 100;
    printf("初始金额:%d\n", money);
    
    money += 50;    // 等同于 money = money + 50
    printf("存入50元后:%d\n", money);
    
    money -= 30;    // 等同于 money = money - 30
    printf("取出30元后:%d\n", money);
    
    // 条件运算符(三目运算符)- 简化if-else
    int score = 75;
    printf("\n成绩评估:%s\n", 
           score >= 60 ? "及格" : "不及格");
    
    // 实际应用组合
    int age = 20;
    int ticket = 100;
    int final_price = ticket * (age < 12 ? 0.5 : 1.0);
    printf("票价:%d元\n", final_price);
    
    return 0;
}

使用技巧:

  1. 复合赋值运算符

    • +=:累加(比如积分增加)
    • -=:递减(比如库存减少)
    • *=:倍数增长(比如利息计算)
  2. 条件运算符

    • 适合简单的条件选择
    • 可以用在表达式中
    • 代码更简单

3. 程序流程控制

让我们把程序流程控制想象成生活中的决策和重复动作。每个人每天都在不知不觉中做出很多决定,执行很多重复的动作,这些就是程序中的流程控制。

3.1 条件语句

条件语句就像我们每天都要面对的选择,比如:

  • 如果下雨了,就带伞
  • 如果饿了,就吃饭
  • 如果累了,就休息
#include <stdio.h>

int main() {
    // if-else语句示例:模拟考试成绩评级系统
    int score = 85;
    
    printf("=== 成绩评估系统 ===\n");
    if (score >= 90) {
        printf("🌟 优秀!继续保持!\n");
    } else if (score >= 80) {
        printf("👍 良好!还可以更好!\n");
    } else if (score >= 60) {
        printf("😊 及格!需要继续努力!\n");
    } else {
        printf("💪 加油!不要灰心!\n");
    }
    
    // switch语句示例:模拟简单点餐系统
    int choice = 1;
    printf("\n=== 快餐点餐系统 ===\n");
    switch (choice) {
        case 1:
            printf("🍔 您选择了汉堡套餐\n");
            break;
        case 2:
            printf("🍗 您选择了炸鸡套餐\n");
            break;
        case 3:
            printf("🍝 您选择了意面套餐\n");
            break;
        default:
            printf("❓ 对不起,没有这个选项\n");
    }
    
    return 0;
}

💡 实际应用场景:

  1. if-else适用场景

    • 根据年龄判断票价优惠
    • 根据消费金额计算折扣
    • 根据天气选择出行方式
  2. switch适用场景

    • 菜单选择系统
    • 简单的状态机
    • 等级评定系统

⚠️ 易错点提醒:

  1. if-else中的常见错误:

    • 忘记写大括号{}
    • 判断条件写成=(赋值)而不是==(比较)
    • 条件的范围重叠或遗漏
  2. switch中的常见错误:

    • 忘记写break导致执行多个case
    • case中的值必须是常量
    • default位置可以放在任意位置(但建议放在最后)
3.2 循环语句

循环就像我们生活中的:

  • 每天刷牙
  • 每周健身
  • 每月查看账单
#include <stdio.h>

int main() {
    // for循环示例:模拟健身计划
    printf("=== 健身计划追踪 ===\n");
    for (int day = 1; day <= 7; day++) {
        printf("第%d天:完成%d个俯卧撑 💪\n", 
               day, day * 5);  // 每天增加5个
    }
    
    // while循环示例:模拟存钱计划
    printf("\n=== 存钱计划追踪 ===\n");
    int savings = 0;
    int week = 1;
    while (savings < 1000) {
        savings += 200;  // 每周存200
        printf("第%d周:已存%d元 💰\n", 
               week++, savings);
    }
    
    // do-while循环示例:模拟游戏菜单
    int choice;
    do {
        printf("\n=== 游戏菜单 ===\n");
        printf("1. 开始游戏 🎮\n");
        printf("2. 设置 ⚙️\n");
        printf("3. 退出 🚪\n");
        printf("请选择(1-3):");
        scanf("%d", &choice);
    } while (choice < 1 || choice > 3);
    
    return 0;
}

🎯 实践建议:

  1. 选择合适的循环:

    • for:知道确切循环次数
    • while:不确定循环次数,但知道结束条件
    • do-while:至少需要执行一次的情况
  2. 循环优化技巧:

    • 使用break提前结束循环
    • 使用continue跳过当前循环
    • 避免死循环(一定要有正确的终止条件)

4. 数组

4.1 一维数组基础
#include <stdio.h>

int main() {
    // 数组的多种定义和初始化方式
    int arr1[5] = {1, 2, 3, 4, 5};     // 完整初始化
    int arr2[5] = {1, 2};              // 部分初始化,其余为0
    int arr3[] = {1, 2, 3};            // 自动确定大小
    int arr4[5] = {0};                 // 全部初始化为0
    
    // 数组基本操作
    printf("=== 数组基本操作 ===\n");
    // 1. 访问元素
    printf("第一个元素:%d\n", arr1[0]);
    printf("最后一个元素:%d\n", arr1[4]);
    
    // 2. 修改元素
    arr1[0] = 10;
    
    // 3. 计算数组大小
    int size = sizeof(arr1) / sizeof(arr1[0]);
    printf("数组大小:%d\n", size);
    
    // 4. 数组遍历的多种方式
    // 4.1 下标遍历
    for (int i = 0; i < size; i++) {
        printf("%d ", arr1[i]);
    }
    printf("\n");
    
    // 4.2 指针遍历
    int *p = arr1;
    for (int i = 0; i < size; i++) {
        printf("%d ", *(p + i));
    }
    printf("\n");
    
    return 0;
}

⚠️ 关键技术点:

  1. 数组定义规则

    • 数组大小必须是常量表达式
    • 数组名代表数组首地址
    • 下标从0开始
  2. 内存特性

    • 连续内存空间
    • 固定大小,不可变
    • 随机访问,O(1)时间复杂度
  3. 数组越界问题

    • 访问越界可能导致程序崩溃
    • 编译器可能不会检查越界
    • 需要手动确保下标合法
4.2 二维数组
#include <stdio.h>

int main() {
    // 1. 二维数组的多种定义方式
    int arr1[3][4] = {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}
    };
    
    int arr2[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12}; // 按行展开初始化
    
    // 2. 二维数组的访问
    printf("=== 二维数组访问 ===\n");
    // 2.1 使用行列下标
    printf("arr1[1][2] = %d\n", arr1[1][2]);
    
    // 2.2 使用指针
    printf("*(*arr1 + 1) = %d\n", *(*arr1 + 1));
    
    // 3. 二维数组的遍历
    int rows = sizeof(arr1) / sizeof(arr1[0]);
    int cols = sizeof(arr1[0]) / sizeof(arr1[0][0]);
    
    // 3.1 按行优先遍历
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            printf("%3d ", arr1[i][j]);
        }
        printf("\n");
    }
    
    // 3.2 按列优先遍历
    for (int j = 0; j < cols; j++) {
        for (int i = 0; i < rows; i++) {
            printf("%3d ", arr1[i][j]);
        }
        printf("\n");
    }
    
    return 0;
}

🔍 二维数组核心要点:

  1. 内存布局

    • 行优先存储
    • 连续内存空间
    • 可以通过一维数组方式访问
  2. 地址计算

    • 元素地址 = 基地址 + (i * 列数 + j) * sizeof(元素类型)
    • arr[i][j] 等价于 ((arr + i) + j)
  3. 参数传递

    • 作为函数参数时必须指定列数
    • 可以省略行数,但不能省略列数
4.3 数组的高级应用
#include <stdio.h>

// 1. 数组作为函数参数
void printArray(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

// 2. 返回数组的函数(通过指针)
int* findElement(int arr[], int size, int target) {
    for (int i = 0; i < size; i++) {
        if (arr[i] == target) {
            return &arr[i];
        }
    }
    return NULL;
}

// 3. 二维数组作为函数参数
void process2DArray(int arr[][4], int rows) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < 4; j++) {
            arr[i][j] *= 2;
        }
    }
}

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    int size = sizeof(arr) / sizeof(arr[0]);
    
    // 数组作为参数传递
    printf("原始数组:");
    printArray(arr, size);
    
    // 查找元素
    int target = 3;
    int *found = findElement(arr, size, target);
    if (found != NULL) {
        printf("找到元素 %d 在位置:%ld\n", target, found - arr);
    }
    
    // 二维数组操作
    int matrix[3][4] = {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}
    };
    
    process2DArray(matrix, 3);
    
    return 0;
}

📝 高级特性总结:

  1. 数组与指针

    • 数组名可以作为指针使用
    • 数组作为参数会退化为指针
    • 指针算术运算与数组索引等价
  2. 内存管理

    • 栈上分配的数组大小固定
    • 需要可变大小时使用动态内存分配
    • 注意避免内存泄漏
  3. 性能优化

    • 合理利用CPU缓存
    • 避免频繁的数组拷贝
    • 使用合适的遍历方式

5. 函数

5.1 函数基础
#include <stdio.h>

// 1. 函数声明
int add(int a, int b);
void swap(int *x, int *y);
int getMax(int arr[], int size);

// 2. 函数定义
int add(int a, int b) {
    return a + b;
}

void swap(int *x, int *y) {
    int temp = *x;
    *x = *y;
    *y = temp;
}

int getMax(int arr[], int size) {
    int max = arr[0];
    for(int i = 1; i < size; i++) {
        if(arr[i] > max) max = arr[i];
    }
    return max;
}

int main() {
    // 3. 函数调用示例
    printf("=== 函数调用演示 ===\n");
    
    // 3.1 基本函数调用
    int sum = add(5, 3);
    printf("add(5, 3) = %d\n", sum);
    
    // 3.2 传递指针参数
    int x = 10, y = 20;
    printf("交换前: x = %d, y = %d\n", x, y);
    swap(&x, &y);
    printf("交换后: x = %d, y = %d\n", x, y);
    
    // 3.3 传递数组参数
    int arr[] = {64, 34, 25, 12, 22, 11, 90};
    int size = sizeof(arr) / sizeof(arr[0]);
    printf("数组最大值: %d\n", getMax(arr, size));
    
    return 0;
}

📝 函数基础要点:

  1. 函数声明

    • 函数原型声明
    • 参数列表
    • 返回值类型
  2. 参数传递

    • 值传递:参数为基本数据类型
    • 指针传递:需要修改原值
    • 数组传递:退化为指针
  3. 返回值

    • void:无返回值
    • 基本数据类型
    • 指针类型
5.2 函数高级特性
#include <stdio.h>

// 1. 内联函数
inline int square(int x) {
    return x * x;
}

// 2. 函数指针
int operate(int x, int y, int (*operation)(int, int)) {
    return operation(x, y);
}

int multiply(int x, int y) { return x * y; }
int divide(int x, int y) { return x / y; }

// 3. 可变参数函数
#include <stdarg.h>

int sum(int count, ...) {
    va_list args;
    va_start(args, count);
    
    int total = 0;
    for(int i = 0; i < count; i++) {
        total += va_arg(args, int);
    }
    
    va_end(args);
    return total;
}

// 4. 递归函数
unsigned long long factorial(int n) {
    if(n <= 1) return 1;
    return n * factorial(n - 1);
}

int main() {
    printf("=== 函数高级特性演示 ===\n");
    
    // 1. 内联函数调用
    printf("square(5) = %d\n", square(5));
    
    // 2. 函数指针使用
    int (*operation)(int, int);
    operation = multiply;
    printf("multiply(6, 3) = %d\n", operation(6, 3));
    
    operation = divide;
    printf("divide(6, 3) = %d\n", operation(6, 3));
    
    // 3. 可变参数函数调用
    printf("sum(4, 1,2,3,4) = %d\n", sum(4, 1,2,3,4));
    
    // 4. 递归函数调用
    printf("factorial(5) = %llu\n", factorial(5));
    
    return 0;
}

🔍 高级特性要点:

  1. 内联函数

    • 减少函数调用开销
    • 编译器优化
    • 适用于简短、频繁调用的函数
  2. 函数指针

    • 指向函数的指针
    • 回调函数实现
    • 函数表实现
  3. 可变参数

    • va_list 类型
    • va_start/va_arg/va_end 宏
    • 参数个数的传递
  4. 递归函数

    • 基本情况处理
    • 递归调用
    • 栈空间使用
5.3 函数优化技术
#include <stdio.h>

// 1. 参数优化
void processArray(const int *arr, int size) {  // 使用const防止修改
    // 只读操作
}

// 2. 返回值优化
typedef struct {
    int x;
    int y;
} Point;

Point* createPoint(int x, int y) {  // 返回堆内存中的对象
    Point* p = (Point*)malloc(sizeof(Point));
    if(p != NULL) {
        p->x = x;
        p->y = y;
    }
    return p;
}

// 3. 尾递归优化
int factorial_tail(int n, int acc) {
    if(n <= 1) return acc;
    return factorial_tail(n - 1, n * acc);
}

int main() {
    // 函数优化示例
    int arr[] = {1, 2, 3, 4, 5};
    processArray(arr, 5);
    
    Point* p = createPoint(10, 20);
    if(p != NULL) {
        printf("Point: (%d, %d)\n", p->x, p->y);
        free(p);
    }
    
    printf("Factorial(5) = %d\n", factorial_tail(5, 1));
    
    return 0;
}

优化技术要点:

  1. 参数传递优化

    • 使用const修饰只读参数
    • 大对象使用指针传递
    • 小对象使用值传递
  2. 返回值优化

    • 返回指针而非大对象
    • 使用输出参数
    • 考虑内存管理
  3. 递归优化

    • 尾递归转换
    • 递归深度控制
    • 内存使用优化

6. 指针

6.1 指针基础
#include <stdio.h>

int main() {
    // 1. 指针的声明和初始化
    int num = 42;
    int *ptr = &num;         // 基本指针
    const int *ptr1 = &num;  // 指向常量的指针
    int * const ptr2 = &num; // 常量指针
    
    // 2. 指针的基本操作
    printf("=== 指针基本操作 ===\n");
    printf("变量值: %d\n", num);
    printf("变量地址: %p\n", (void*)&num);
    printf("指针存储的地址: %p\n", (void*)ptr);
    printf("指针指向的值: %d\n", *ptr);
    
    // 3. 指针的算术运算
    int array[5] = {1, 2, 3, 4, 5};
    int *p = array;
    
    printf("\n=== 指针算术运算 ===\n");
    printf("初始值: %d\n", *p);
    p++;                    // 指针递增
    printf("递增后: %d\n", *p);
    printf("偏移访问: %d\n", *(p + 2));
    
    return 0;
}

📝 指针基础要点:

  1. 指针类型

    • 基本指针:可读写指向的值
    • 指向常量的指针:不能通过指针修改值
    • 常量指针:指针本身不能修改
    • void指针:通用指针类型
  2. 内存操作

    • &:取地址运算符
    • *:解引用运算符
    • 指针大小:取决于系统架构
  3. 指针运算

    • 加减运算:按照指针类型的大小进行
    • 比较运算:比较地址大小
    • NULL指针:表示不指向任何地址
6.2 指针的高级应用
#include <stdio.h>
#include <stdlib.h>

// 1. 函数指针
typedef int (*Operation)(int, int);
int add(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }

// 2. 回调函数
void processArray(int *arr, int size, int (*process)(int)) {
    for(int i = 0; i < size; i++) {
        arr[i] = process(arr[i]);
    }
}

int square(int x) { return x * x; }
int double_value(int x) { return x * 2; }

// 3. 多级指针应用
void allocateMatrix(int ***matrix, int rows, int cols) {
    *matrix = (int**)malloc(rows * sizeof(int*));
    for(int i = 0; i < rows; i++) {
        (*matrix)[i] = (int*)malloc(cols * sizeof(int));
    }
}

int main() {
    // 1. 函数指针使用
    Operation ops[] = {add, subtract};
    printf("10 + 5 = %d\n", ops[0](10, 5));
    printf("10 - 5 = %d\n", ops[1](10, 5));
    
    // 2. 回调函数示例
    int arr[] = {1, 2, 3, 4, 5};
    printf("\n原始数组: ");
    for(int i = 0; i < 5; i++) printf("%d ", arr[i]);
    
    processArray(arr, 5, square);
    printf("\n平方后: ");
    for(int i = 0; i < 5; i++) printf("%d ", arr[i]);
    
    // 3. 多级指针示例
    int **matrix;
    allocateMatrix(&matrix, 3, 4);
    
    // 使用矩阵
    for(int i = 0; i < 3; i++) {
        for(int j = 0; j < 4; j++) {
            matrix[i][j] = i * 4 + j;
            printf("%2d ", matrix[i][j]);
        }
        printf("\n");
    }
    
    // 释放内存
    for(int i = 0; i < 3; i++) {
        free(matrix[i]);
    }
    free(matrix);
    
    return 0;
}

🔍 高级应用要点:

  1. 函数指针

    • 存储函数地址
    • 实现回调机制
    • 函数表实现
  2. 多级指针

    • 动态分配多维数组
    • 指针的间接引用
    • 参数传递优化
  3. 内存管理

    • 动态内存分配
    • 内存泄漏预防
    • 指针安全性
6.3 指针的安全性和优化
#include <stdio.h>
#include <stdlib.h>

// 1. 安全的内存分配
void* safeAlloc(size_t size) {
    void* ptr = malloc(size);
    if(ptr == NULL) {
        fprintf(stderr, "内存分配失败\n");
        exit(1);
    }
    return ptr;
}

// 2. 智能指针模拟
typedef struct {
    int* ptr;
    size_t* ref_count;
} SmartPtr;

SmartPtr createSmartPtr(int value) {
    SmartPtr sp;
    sp.ptr = (int*)safeAlloc(sizeof(int));
    sp.ref_count = (size_t*)safeAlloc(sizeof(size_t));
    *sp.ptr = value;
    *sp.ref_count = 1;
    return sp;
}

void addRef(SmartPtr* sp) {
    (*sp->ref_count)++;
}

void release(SmartPtr* sp) {
    (*sp->ref_count)--;
    if(*sp->ref_count == 0) {
        free(sp->ptr);
        free(sp->ref_count);
        sp->ptr = NULL;
        sp->ref_count = NULL;
    }
}

int main() {
    // 1. 安全的指针使用
    int* ptr = (int*)safeAlloc(sizeof(int));
    *ptr = 42;
    printf("安全分配的值: %d\n", *ptr);
    free(ptr);
    ptr = NULL;  // 避免悬挂指针
    
    // 2. 智能指针示例
    SmartPtr sp1 = createSmartPtr(100);
    printf("智能指针值: %d\n", *sp1.ptr);
    printf("引用计数: %zu\n", *sp1.ref_count);
    
    // 复制智能指针
    SmartPtr sp2 = sp1;
    addRef(&sp2);
    printf("复制后引用计数: %zu\n", *sp1.ref_count);
    
    // 释放智能指针
    release(&sp1);
    release(&sp2);
    
    return 0;
}

安全性和优化要点:

  1. 内存安全

    • 空指针检查
    • 边界检查
    • 类型安全
  2. 资源管理

    • RAII原则
    • 引用计数
    • 自动内存管理
  3. 性能优化

    • 指针对齐
    • 缓存友好访问
    • 避免指针追踪

7. 结构体和共用体

7.1 结构体基础
#include <stdio.h>
#include <string.h>

// 1. 结构体定义
struct Point {
    int x;
    int y;
};

// 2. 结构体对齐和压缩
#pragma pack(1)  // 设置1字节对齐
struct CompactData {
    char a;      // 1字节
    int b;       // 4字节
    short c;     // 2字节
};
#pragma pack()   // 恢复默认对齐

// 3. 结构体嵌套
struct Rectangle {
    struct Point topLeft;
    struct Point bottomRight;
    char *label;
};

int main() {
    // 1. 结构体初始化
    struct Point p1 = {10, 20};                    // 常规初始化
    struct Point p2 = {.y = 30, .x = 40};         // 指定成员初始化
    
    // 2. 内存对齐演示
    printf("=== 内存对齐 ===\n");
    printf("Point大小: %zu字节\n", sizeof(struct Point));
    printf("CompactData大小: %zu字节\n", sizeof(struct CompactData));
    
    // 3. 结构体操作
    struct Rectangle rect;
    rect.topLeft = p1;
    rect.bottomRight = p2;
    rect.label = "Rectangle1";
    
    printf("\n=== 结构体访问 ===\n");
    printf("矩形: (%d,%d) to (%d,%d)\n", 
           rect.topLeft.x, rect.topLeft.y,
           rect.bottomRight.x, rect.bottomRight.y);
    
    return 0;
}

📝 结构体基础要点:

  1. 内存布局

    • 成员按声明顺序存储
    • 考虑内存对齐
    • 可能存在填充字节
  2. 对齐规则

    • 默认对齐:按系统字长
    • 自定义对齐:使用pragma pack
    • 对齐优化:成员排序
  3. 初始化方式

    • 顺序初始化
    • 指定成员初始化
    • 动态分配初始化
7.2 结构体的高级特性
#include <stdio.h>
#include <stdlib.h>

// 1. 结构体封装
typedef struct {
    char *data;
    size_t length;
    size_t capacity;
} String;

// 构造函数
String* String_create(const char* str) {
    String* s = (String*)malloc(sizeof(String));
    if (s != NULL) {
        s->capacity = strlen(str) + 1;
        s->data = (char*)malloc(s->capacity);
        if (s->data != NULL) {
            strcpy(s->data, str);
            s->length = strlen(str);
        } else {
            free(s);
            return NULL;
        }
    }
    return s;
}

// 析构函数
void String_destroy(String* s) {
    if (s != NULL) {
        free(s->data);
        free(s);
    }
}

// 2. 柔性数组
typedef struct {
    int length;
    int data[];  // 柔性数组成员
} Array;

Array* Array_create(int length) {
    Array* arr = (Array*)malloc(sizeof(Array) + length * sizeof(int));
    if (arr != NULL) {
        arr->length = length;
    }
    return arr;
}

// 3. 位域结构
struct Flags {
    unsigned int read: 1;     // 1位
    unsigned int write: 1;    // 1位
    unsigned int exec: 1;     // 1位
    unsigned int reserved: 5; // 5位
};

int main() {
    // 1. 封装示例
    String* str = String_create("Hello");
    if (str != NULL) {
        printf("字符串: %s, 长度: %zu\n", str->data, str->length);
        String_destroy(str);
    }
    
    // 2. 柔性数组示例
    Array* arr = Array_create(5);
    if (arr != NULL) {
        for (int i = 0; i < arr->length; i++) {
            arr->data[i] = i * i;
            printf("%d ", arr->data[i]);
        }
        printf("\n");
        free(arr);
    }
    
    // 3. 位域示例
    struct Flags flags = {1, 1, 0, 0};  // 读写权限
    printf("Flags大小: %zu字节\n", sizeof(struct Flags));
    printf("权限: r%c w%c x%c\n",
           flags.read ? 'w' : '-',
           flags.write ? 'w' : '-',
           flags.exec ? 'x' : '-');
    
    return 0;
}

🔍 高级特性要点:

  1. 封装技术

    • 构造和析构函数
    • 资源管理
    • 接口设计
  2. 柔性数组

    • 必须是最后一个成员
    • 不占用结构体大小
    • 动态内存分配
  3. 位域使用

    • 节省内存空间
    • 位级操作
    • 标志位管理
7.3 共用体和枚举
#include <stdio.h>

// 1. 共用体定义
union Data {
    int i;          // 4字节
    float f;        // 4字节
    char str[8];    // 8字节
};

// 2. 枚举定义
enum DayOfWeek {
    SUNDAY = 0,
    MONDAY,
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY
};

// 3. 类型标记联合
typedef enum {
    TYPE_INT,
    TYPE_FLOAT,
    TYPE_STRING
} ValueType;

typedef struct {
    ValueType type;
    union {
        int i;
        float f;
        char *s;
    } value;
} TypedValue;

// 值打印函数
void printValue(TypedValue *v) {
    switch (v->type) {
        case TYPE_INT:
            printf("整数: %d\n", v->value.i);
            break;
        case TYPE_FLOAT:
            printf("浮点数: %f\n", v->value.f);
            break;
        case TYPE_STRING:
            printf("字符串: %s\n", v->value.s);
            break;
    }
}

int main() {
    // 1. 共用体示例
    union Data data;
    printf("Data大小: %zu字节\n", sizeof(union Data));
    
    data.i = 42;
    printf("整数: %d\n", data.i);
    data.f = 3.14f;
    printf("浮点数: %f\n", data.f);
    strcpy(data.str, "Hello");
    printf("字符串: %s\n", data.str);
    
    // 2. 枚举示例
    enum DayOfWeek today = WEDNESDAY;
    printf("今天是周%d\n", today + 1);
    
    // 3. 类型标记联合示例
    TypedValue val1 = {TYPE_INT, {.i = 42}};
    TypedValue val2 = {TYPE_FLOAT, {.f = 3.14f}};
    TypedValue val3 = {TYPE_STRING, {.s = "Hello"}};
    
    printValue(&val1);
    printValue(&val2);
    printValue(&val3);
    
    return 0;
}

共用体和枚举要点:

  1. 共用体特性

    • 成员共享内存
    • 大小为最大成员
    • 内存覆盖规则
  2. 枚举特性

    • 常量定义
    • 自动递增
    • 类型安全
  3. 应用场景

    • 数据类型转换
    • 内存节省
    • 状态管理

8. 文件操作

8.1 文件的基本操作
#include <stdio.h>
#include <errno.h>
#include <string.h>

int main() {
    // 1. 文件打开模式
    FILE *fp;
    const char *modes[] = {"r", "w", "a", "r+", "w+", "a+"};
    
    // 2. 错误处理示例
    if ((fp = fopen("test.txt", "r")) == NULL) {
        fprintf(stderr, "错误码: %d\n", errno);
        fprintf(stderr, "错误信息: %s\n", strerror(errno));
        return 1;
    }
    
    // 3. 文件指针操作
    fseek(fp, 0, SEEK_SET);    // 移到文件开头
    fseek(fp, 0, SEEK_END);    // 移到文件末尾
    long size = ftell(fp);     // 获取文件大小
    rewind(fp);                // 回到文件开头
    
    // 4. 文件关闭
    fclose(fp);
    
    return 0;
}
8.2 文本文件操作
#include <stdio.h>

int main() {
    FILE *fp;
    char buffer[1024];
    
    // 1. 写入文本文件
    fp = fopen("text.txt", "w");
    if (fp != NULL) {
        // 单字符写入
        fputc('H', fp);
        
        // 字符串写入
        fputs("ello, World!\n", fp);
        
        // 格式化写入
        fprintf(fp, "Count: %d\n", 42);
        
        fclose(fp);
    }
    
    // 2. 读取文本文件
    fp = fopen("text.txt", "r");
    if (fp != NULL) {
        // 单字符读取
        int ch = fgetc(fp);
        
        // 行读取
        if (fgets(buffer, sizeof(buffer), fp) != NULL) {
            printf("读取的行: %s", buffer);
        }
        
        // 格式化读取
        int count;
        if (fscanf(fp, "Count: %d", &count) == 1) {
            printf("读取的数字: %d\n", count);
        }
        
        fclose(fp);
    }
    
    return 0;
}
8.3 二进制文件操作
#include <stdio.h>
#include <stdlib.h>

// 定义数据结构
typedef struct {
    int id;
    char name[50];
    double score;
} Student;

int main() {
    FILE *fp;
    Student students[3] = {
        {1, "张三", 85.5},
        {2, "李四", 92.0},
        {3, "王五", 78.5}
    };
    
    // 1. 写入二进制文件
    fp = fopen("students.dat", "wb");
    if (fp != NULL) {
        // 整块写入
        fwrite(students, sizeof(Student), 3, fp);
        
        // 单个写入
        Student newStudent = {4, "赵六", 88.5};
        fwrite(&newStudent, sizeof(Student), 1, fp);
        
        fclose(fp);
    }
    
    // 2. 读取二进制文件
    fp = fopen("students.dat", "rb");
    if (fp != NULL) {
        Student readStudent;
        
        // 随机访问
        fseek(fp, sizeof(Student) * 2, SEEK_SET);  // 定位到第三个记录
        fread(&readStudent, sizeof(Student), 1, fp);
        printf("ID: %d, 姓名: %s, 分数: %.1f\n",
               readStudent.id, readStudent.name, readStudent.score);
        
        fclose(fp);
    }
    
    return 0;
}
8.4 高级文件操作
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 1. 文件缓冲区管理
void bufferDemo() {
    FILE *fp = fopen("test.txt", "w");
    if (fp != NULL) {
        // 设置缓冲区
        char buffer[1024];
        setvbuf(fp, buffer, _IOFBF, sizeof(buffer));
        
        // 写入数据
        fprintf(fp, "测试数据\n");
        
        // 强制刷新缓冲区
        fflush(fp);
        
        fclose(fp);
    }
}

// 2. 临时文件操作
void tempFileDemo() {
    FILE *temp = tmpfile();
    if (temp != NULL) {
        fprintf(temp, "临时数据\n");
        rewind(temp);
        
        char buffer[100];
        if (fgets(buffer, sizeof(buffer), temp) != NULL) {
            printf("临时文件内容: %s", buffer);
        }
        
        fclose(temp);  // 关闭时自动删除
    }
}

// 3. 文件锁定示例
void fileLockDemo() {
    FILE *fp = fopen("shared.txt", "r+");
    if (fp != NULL) {
        #ifdef _WIN32
        _flock(fileno(fp), _LK_NBLCK);  // Windows
        #else
        flock(fileno(fp), LOCK_EX);      // UNIX
        #endif
        
        // 对文件进行操作
        fprintf(fp, "加锁写入\n");
        
        #ifdef _WIN32
        _funlock(fileno(fp));
        #else
        flock(fileno(fp), LOCK_UN);
        #endif
        
        fclose(fp);
    }
}

int main() {
    bufferDemo();
    tempFileDemo();
    fileLockDemo();
    return 0;
}

【核心要点】

  1. 文件操作基础

    • 文件打开模式的选择
    • 错误处理机制
    • 文件指针操作
    • 资源管理
  2. 文本文件操作

    • 字符级操作
    • 行级操作
    • 格式化IO
    • 缓冲区管理
  3. 二进制文件操作

    • 结构体的读写
    • 随机访问
    • 数据对齐
    • 字节序考虑
  4. 高级特性

    • 缓冲区管理
    • 临时文件
    • 文件锁定
    • 异常处理

⚠️ 注意事项

  1. 始终检查文件操作的返回值
  2. 正确关闭文件以释放资源
  3. 考虑文件访问权限
  4. 处理平台差异性
  5. 注意数据的字节对齐

第二部分:进阶知识点

1. 预处理指令

1.1 预处理器基础
#include <stdio.h>

// 1. 宏定义
#define PI 3.14159
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define SQUARE(x) ((x) * (x))

// 2. 条件编译
#define DEBUG 1

#if DEBUG
    #define LOG(msg) printf("[DEBUG] %s\n", msg)
#else
    #define LOG(msg)  // 空定义
#endif

// 3. 预定义宏
void printInfo() {
    printf("文件:%s\n", __FILE__);
    printf("行号:%d\n", __LINE__);
    printf("编译时间:%s %s\n", __DATE__, __TIME__);
    printf("ANSI C:%d\n", __STDC__);
}

int main() {
    // 宏的使用
    printf("PI = %.5f\n", PI);
    printf("最大值:%d\n", MAX(10, 20));
    printf("平方值:%d\n", SQUARE(5));
    
    // 条件编译的使用
    LOG("测试消息");
    
    // 预定义宏的使用
    printInfo();
    
    return 0;
}
1.2 高级预处理技术
#include <stdio.h>

// 1. 字符串化运算符 #
#define PRINT_VAR(var) printf(#var " = %d\n", var)

// 2. 标记连接运算符 ##
#define CONCAT(x, y) x##y

// 3. 可变参数宏
#define DEBUG_LOG(format, ...) \
    printf("[DEBUG] " format "\n", ##__VA_ARGS__)

// 4. 条件编译的高级用法
#ifdef _WIN32
    #define OS "Windows"
#elif defined(__linux__)
    #define OS "Linux"
#elif defined(__APPLE__)
    #define OS "macOS"
#else
    #define OS "Unknown"
#endif

// 5. 防止头文件重复包含
#ifndef MY_HEADER_H
#define MY_HEADER_H

typedef struct {
    int x;
    int y;
} Point;

#endif

int main() {
    // 字符串化示例
    int count = 42;
    PRINT_VAR(count);  // 输出:count = 42
    
    // 标记连接示例
    int value12 = 100;
    printf("%d\n", CONCAT(value, 12));  // 访问value12
    
    // 可变参数宏示例
    DEBUG_LOG("测试 %s", "消息");
    DEBUG_LOG("简单消息");
    
    // 条件编译结果
    printf("当前操作系统:%s\n", OS);
    
    return 0;
}
1.3 预处理器最佳实践
// 1. 头文件保护
#ifndef MATH_UTILS_H
#define MATH_UTILS_H

// 2. 版本控制
#define MATH_UTILS_VERSION 100  // 1.0.0

// 3. 功能开关
#define ENABLE_ADVANCED_MATH 1

// 4. 条件检查
#if defined(_MSC_VER) && _MSC_VER < 1400
    #error "需要 Visual C++ 2005 或更高版本"
#endif

// 5. 平台特定代码
#ifdef _WIN32
    #define PATH_SEPARATOR '\\'
#else
    #define PATH_SEPARATOR '/'
#endif

// 6. 安全的宏定义
#define SAFE_DELETE(p) do { if(p) { delete (p); (p) = NULL; } } while(0)
#define SAFE_ARRAY_DELETE(p) do { if(p) { delete[] (p); (p) = NULL; } } while(0)

// 7. 条件编译的嵌套
#if defined(DEBUG)
    #if defined(_WIN32)
        #define DEBUG_BREAK() __debugbreak()
    #else
        #define DEBUG_BREAK() __builtin_trap()
    #endif
#else
    #define DEBUG_BREAK()
#endif

#endif // MATH_UTILS_H

【核心要点】

  1. 预处理器基础

    • 宏定义与函数的区别
    • 条件编译的使用场景
    • 预定义宏的应用
  2. 高级预处理技术

    • 字符串化运算符(#)
    • 标记连接运算符(##)
    • 可变参数宏
    • 条件编译的高级应用
  3. 最佳实践

    • 头文件保护机制
    • 版本控制和功能开关
    • 平台特定代码处理
    • 安全的宏定义方式

⚠️ 注意事项

  1. 宏定义中的括号使用
  2. 避免宏的副作用
  3. 合理使用条件编译
  4. 注意宏的命名规范
  5. 预处理器的执行顺序

🔍 常见应用场景

  1. 调试信息控制
  2. 平台特定代码
  3. 版本兼容性处理
  4. 代码优化开关
  5. 资源管理宏

2. 动态内存分配

2.1 内存分配基础
#include <stdio.h>
#include <stdlib.h>

int main() {
    // 1. 基本内存分配
    int *p1 = (int*)malloc(sizeof(int));          // 分配单个整数
    int *p2 = (int*)calloc(1, sizeof(int));      // 分配并初始化为0
    int *p3 = (int*)realloc(NULL, sizeof(int));  // 类似malloc
    
    // 2. 数组内存分配
    int *arr = (int*)malloc(5 * sizeof(int));
    if (arr != NULL) {
        for (int i = 0; i < 5; i++) {
            arr[i] = i + 1;
        }
    }
    
    // 3. 内存释放
    free(p1);
    free(p2);
    free(p3);
    free(arr);
    
    // 4. 避免内存泄漏
    p1 = p2 = p3 = arr = NULL;
    
    return 0;
}
2.2 高级内存管理
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 1. 安全的内存分配函数
void* safeMalloc(size_t size) {
    void* ptr = malloc(size);
    if (ptr == NULL) {
        fprintf(stderr, "内存分配失败\n");
        exit(EXIT_FAILURE);
    }
    return ptr;
}

// 2. 二维数组动态分配
int** create2DArray(int rows, int cols) {
    int** array = (int**)safeMalloc(rows * sizeof(int*));
    for (int i = 0; i < rows; i++) {
        array[i] = (int*)safeMalloc(cols * sizeof(int));
    }
    return array;
}

// 3. 二维数组释放
void free2DArray(int** array, int rows) {
    if (array) {
        for (int i = 0; i < rows; i++) {
            free(array[i]);
        }
        free(array);
    }
}

// 4. 内存池实现
typedef struct MemoryPool {
    void* memory;
    size_t size;
    size_t used;
} MemoryPool;

MemoryPool* createMemoryPool(size_t size) {
    MemoryPool* pool = (MemoryPool*)safeMalloc(sizeof(MemoryPool));
    pool->memory = safeMalloc(size);
    pool->size = size;
    pool->used = 0;
    return pool;
}

void* poolAlloc(MemoryPool* pool, size_t size) {
    if (pool->used + size > pool->size) {
        return NULL;  // 内存池已满
    }
    void* ptr = (char*)pool->memory + pool->used;
    pool->used += size;
    return ptr;
}

void destroyMemoryPool(MemoryPool* pool) {
    if (pool) {
        free(pool->memory);
        free(pool);
    }
}

int main() {
    // 1. 二维数组示例
    int rows = 3, cols = 4;
    int** matrix = create2DArray(rows, cols);
    
    // 初始化矩阵
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            matrix[i][j] = i * cols + j;
            printf("%2d ", matrix[i][j]);
        }
        printf("\n");
    }
    
    // 2. 内存池示例
    MemoryPool* pool = createMemoryPool(1024);  // 1KB内存池
    
    // 从内存池分配内存
    int* numbers = (int*)poolAlloc(pool, 5 * sizeof(int));
    char* text = (char*)poolAlloc(pool, 20);
    
    if (numbers && text) {
        // 使用分配的内存
        for (int i = 0; i < 5; i++) {
            numbers[i] = i;
        }
        strcpy(text, "Hello, Memory Pool!");
        printf("Text: %s\n", text);
    }
    
    // 清理资源
    free2DArray(matrix, rows);
    destroyMemoryPool(pool);
    
    return 0;
}
2.3 内存管理最佳实践
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 1. 内存跟踪结构
typedef struct {
    void* ptr;
    size_t size;
    const char* file;
    int line;
} MemoryBlock;

#define MAX_BLOCKS 1000
MemoryBlock g_blocks[MAX_BLOCKS];
int g_blockCount = 0;

// 2. 内存分配跟踪
#define TRACK_MALLOC(size) trackMalloc(size, __FILE__, __LINE__)
void* trackMalloc(size_t size, const char* file, int line) {
    void* ptr = malloc(size);
    if (ptr && g_blockCount < MAX_BLOCKS) {
        g_blocks[g_blockCount].ptr = ptr;
        g_blocks[g_blockCount].size = size;
        g_blocks[g_blockCount].file = file;
        g_blocks[g_blockCount].line = line;
        g_blockCount++;
    }
    return ptr;
}

// 3. 内存释放跟踪
void trackFree(void* ptr) {
    for (int i = 0; i < g_blockCount; i++) {
        if (g_blocks[i].ptr == ptr) {
            memmove(&g_blocks[i], &g_blocks[i + 1], 
                    (g_blockCount - i - 1) * sizeof(MemoryBlock));
            g_blockCount--;
            break;
        }
    }
    free(ptr);
}

// 4. 内存泄漏检测
void checkMemoryLeaks() {
    if (g_blockCount > 0) {
        printf("检测到内存泄漏!\n");
        for (int i = 0; i < g_blockCount; i++) {
            printf("泄漏: %zu bytes at %p (%s:%d)\n",
                   g_blocks[i].size,
                   g_blocks[i].ptr,
                   g_blocks[i].file,
                   g_blocks[i].line);
        }
    } else {
        printf("未检测到内存泄漏\n");
    }
}

// 5. 对齐内存分配
void* alignedMalloc(size_t size, size_t alignment) {
    void* ptr = NULL;
#ifdef _WIN32
    ptr = _aligned_malloc(size, alignment);
#else
    if (posix_memalign(&ptr, alignment, size) != 0) {
        ptr = NULL;
    }
#endif
    return ptr;
}

void alignedFree(void* ptr) {
#ifdef _WIN32
    _aligned_free(ptr);
#else
    free(ptr);
#endif
}

int main() {
    // 内存跟踪示例
    int* numbers = (int*)TRACK_MALLOC(5 * sizeof(int));
    char* text = (char*)TRACK_MALLOC(20);
    
    // 使用内存
    if (numbers && text) {
        for (int i = 0; i < 5; i++) {
            numbers[i] = i;
        }
        strcpy(text, "Hello");
    }
    
    // 释放部分内存
    trackFree(numbers);
    
    // 检查内存泄漏
    checkMemoryLeaks();  // 应该显示text未释放
    
    // 对齐内存分配示例
    float* aligned_data = (float*)alignedMalloc(256, 16);
    if (aligned_data) {
        // 使用对齐的内存
        alignedFree(aligned_data);
    }
    
    // 清理剩余资源
    trackFree(text);
    checkMemoryLeaks();  // 应该显示无泄漏
    
    return 0;
}

【核心要点】

  1. 内存分配基础

    • malloc/calloc/realloc的使用
    • 内存释放和空指针处理
    • 内存分配失败处理
    • 避免内存泄漏
  2. 高级内存管理

    • 安全的内存分配封装
    • 多维数组的动态分配
    • 内存池实现
    • 资源管理策略
  3. 最佳实践

    • 内存跟踪和调试
    • 内存泄漏检测
    • 内存对齐处理
    • 平台兼容性考虑

⚠️ 注意事项

  1. 检查内存分配返回值
  2. 避免内存泄漏和重复释放
  3. 注意内存对齐要求
  4. 考虑内存分配效率
  5. 处理内存碎片问题

🔍 应用场景

  1. 动态数组实现
  2. 图像处理缓冲区
  3. 数据库缓存管理
  4. 游戏资源管理
  5. 大数据处理

3. 位运算

3.1 基本位运算
#include <stdio.h>

int main() {
    // 1. 基本位运算操作
    unsigned int a = 60;    // 二进制:00111100
    unsigned int b = 13;    // 二进制:00001101
    
    printf("=== 基本位运算 ===\n");
    printf("a = %u (%08X)\n", a, a);
    printf("b = %u (%08X)\n", b, b);
    printf("按位与 (AND): %u (%08X)\n", a & b, a & b);
    printf("按位或 (OR): %u (%08X)\n", a | b, a | b);
    printf("按位异或 (XOR): %u (%08X)\n", a ^ b, a ^ b);
    printf("按位取反 (NOT): %u (%08X)\n", ~a, ~a);
    
    // 2. 移位运算
    printf("\n=== 移位运算 ===\n");
    printf("左移2位 (a << 2): %u (%08X)\n", a << 2, a << 2);
    printf("右移2位 (a >> 2): %u (%08X)\n", a >> 2, a >> 2);
    
    // 3. 带符号数右移
    int negative = -60;    // 负数的右移
    printf("\n=== 带符号右移 ===\n");
    printf("负数右移1位: %d (%08X)\n", negative >> 1, negative >> 1);
    
    return 0;
}
3.2 位运算技巧
#include <stdio.h>

// 1. 判断奇偶性
#define IS_EVEN(n) (((n) & 1) == 0)

// 2. 交换两数
void swapBits(int *a, int *b) {
    if (a != b) {  // 检查是否为同一地址
        *a ^= *b;
        *b ^= *a;
        *a ^= *b;
    }
}

// 3. 计算二进制中1的个数
int countSetBits(unsigned int n) {
    int count = 0;
    while (n) {
        count += n & 1;
        n >>= 1;
    }
    return count;
}

// 4. 快速计算2的幂
#define IS_POWER_OF_TWO(n) (((n) & ((n) - 1)) == 0)

// 5. 获取最低位的1
#define LOWEST_SET_BIT(n) ((n) & -(n))

int main() {
    // 1. 奇偶性判断
    int num = 7;
    printf("数字 %d 是%s数\n", num, IS_EVEN(num) ? "偶" : "奇");
    
    // 2. 位交换示例
    int x = 5, y = 10;
    printf("交换前: x = %d, y = %d\n", x, y);
    swapBits(&x, &y);
    printf("交换后: x = %d, y = %d\n", x, y);
    
    // 3. 计算置位数
    unsigned int n = 0xFF;  // 二进制:11111111
    printf("数字 %u 中1的个数: %d\n", n, countSetBits(n));
    
    // 4. 2的幂检查
    int powerOfTwo = 16;
    printf("%d %s 2的幂\n", powerOfTwo, 
           IS_POWER_OF_TWO(powerOfTwo) ? "是" : "不是");
    
    // 5. 最低位1
    int number = 12;  // 二进制:1100
    printf("%d 的最低位1值为: %d\n", number, LOWEST_SET_BIT(number));
    
    return 0;
}
3.3 位运算高级应用
#include <stdio.h>

// 1. 位域结构
typedef struct {
    unsigned int ready: 1;      // 1位,状态标志
    unsigned int busy: 1;       // 1位,忙标志
    unsigned int error: 2;      // 2位,错误代码
    unsigned int command: 4;    // 4位,命令
    unsigned int reserved: 24;  // 24位,保留
} StatusRegister;

// 2. 位掩码操作
#define SET_BIT(x, pos)    ((x) |= (1U << (pos)))
#define CLEAR_BIT(x, pos)  ((x) &= ~(1U << (pos)))
#define TOGGLE_BIT(x, pos) ((x) ^= (1U << (pos)))
#define GET_BIT(x, pos)    (((x) >> (pos)) & 1U)

// 3. 循环移位
unsigned int rotateLeft(unsigned int value, int shift) {
    if ((shift &= sizeof(value) * 8 - 1) == 0)
        return value;
    return (value << shift) | (value >> (sizeof(value) * 8 - shift));
}

unsigned int rotateRight(unsigned int value, int shift) {
    if ((shift &= sizeof(value) * 8 - 1) == 0)
        return value;
    return (value >> shift) | (value << (sizeof(value) * 8 - shift));
}

// 4. 位图实现
#define BITMAP_SIZE 128
typedef struct {
    unsigned int bits[BITMAP_SIZE / 32];
} Bitmap;

void setBit(Bitmap* bitmap, int pos) {
    bitmap->bits[pos / 32] |= (1U << (pos % 32));
}

void clearBit(Bitmap* bitmap, int pos) {
    bitmap->bits[pos / 32] &= ~(1U << (pos % 32));
}

int testBit(Bitmap* bitmap, int pos) {
    return (bitmap->bits[pos / 32] >> (pos % 32)) & 1U;
}

int main() {
    // 1. 位域示例
    StatusRegister status = {0};
    status.ready = 1;
    status.command = 5;
    printf("状态寄存器: ready=%d, command=%d\n", 
           status.ready, status.command);
    
    // 2. 位掩码操作示例
    unsigned int flags = 0;
    SET_BIT(flags, 3);    // 设置第3位
    TOGGLE_BIT(flags, 5); // 切换第5位
    printf("标志位: %08X\n", flags);
    printf("第3位: %d\n", GET_BIT(flags, 3));
    
    // 3. 循环移位示例
    unsigned int value = 0x12345678;
    printf("原值: %08X\n", value);
    printf("左移4位: %08X\n", rotateLeft(value, 4));
    printf("右移4位: %08X\n", rotateRight(value, 4));
    
    // 4. 位图示例
    Bitmap bitmap = {0};
    setBit(&bitmap, 100);  // 设置第100位
    setBit(&bitmap, 101);  // 设置第101位
    printf("第100位: %d\n", testBit(&bitmap, 100));
    printf("第99位: %d\n", testBit(&bitmap, 99));
    
    return 0;
}

【核心要点】

  1. 基本位运算

    • 按位与、或、异或、取反
    • 左移和右移操作
    • 带符号数和无符号数的区别
    • 位运算优先级
  2. 位运算技巧

    • 奇偶性判断
    • 无临时变量交换
    • 计算置位数
    • 2的幂检查
    • 最低位1提取
  3. 高级应用

    • 位域结构定义
    • 位掩码操作
    • 循环移位实现
    • 位图数据结构

⚠️ 注意事项

  1. 位运算的优先级
  2. 带符号数右移的符号扩展
  3. 位域的对齐和移植性
  4. 位运算的性能考虑
  5. 代码可读性平衡

🔍 应用场景

  1. 状态标志管理
  2. 权限控制
  3. 硬件寄存器操作
  4. 数据压缩
  5. 加密算法

4. 排序算法

4.1 基本排序算法
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 1. 冒泡排序 - 时间复杂度O(n²)
void bubbleSort(int arr[], int n) {
    int i, j;
    int flag;  // 优化标志
    for (i = 0; i < n - 1; i++) {
        flag = 0;
        for (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;
                flag = 1;
            }
        }
        if (!flag) break;  // 如果一轮未发生交换,说明已经有序
    }
}

// 2. 选择排序 - 时间复杂度O(n²)
void selectionSort(int arr[], int n) {
    int i, j, min_idx;
    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;
        }
        if (min_idx != i) {
            int temp = arr[i];
            arr[i] = arr[min_idx];
            arr[min_idx] = temp;
        }
    }
}

// 3. 插入排序 - 时间复杂度O(n²)
void insertionSort(int arr[], int n) {
    int i, key, j;
    for (i = 1; i < n; i++) {
        key = arr[i];
        j = i - 1;
        while (j >= 0 && arr[j] > key) {
            arr[j + 1] = arr[j];
            j--;
        }
        arr[j + 1] = key;
    }
}

// 4. 希尔排序 - 时间复杂度O(n^1.3)
void shellSort(int arr[], int n) {
    for (int gap = n/2; gap > 0; gap /= 2) {
        for (int i = gap; i < n; i++) {
            int temp = arr[i];
            int j;
            for (j = i; j >= gap && arr[j - gap] > temp; j -= gap)
                arr[j] = arr[j - gap];
            arr[j] = temp;
        }
    }
}
4.2 高级排序算法
// 1. 快速排序 - 时间复杂度O(nlogn)
void quickSort(int arr[], int low, int high) {
    if (low < high) {
        // 三数取中法选择基准
        int mid = low + (high - low) / 2;
        if (arr[low] > arr[high])
            swap(&arr[low], &arr[high]);
        if (arr[mid] > arr[high])
            swap(&arr[mid], &arr[high]);
        if (arr[low] > arr[mid])
            swap(&arr[low], &arr[mid]);
            
        int pivot = arr[mid];
        int i = low - 1;
        int j = high + 1;
        
        while (1) {
            do {
                i++;
            } while (arr[i] < pivot);
            
            do {
                j--;
            } while (arr[j] > pivot);
            
            if (i >= j)
                break;
                
            swap(&arr[i], &arr[j]);
        }
        
        quickSort(arr, low, j);
        quickSort(arr, j + 1, high);
    }
}

// 2. 归并排序 - 时间复杂度O(nlogn)
void merge(int arr[], int left, int mid, int right) {
    int i, j, k;
    int n1 = mid - left + 1;
    int n2 = right - mid;
    
    int *L = (int*)malloc(n1 * sizeof(int));
    int *R = (int*)malloc(n2 * sizeof(int));
    
    for (i = 0; i < n1; i++)
        L[i] = arr[left + i];
    for (j = 0; j < n2; j++)
        R[j] = arr[mid + 1 + j];
        
    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];
        i++;
        k++;
    }
    
    while (j < n2) {
        arr[k] = R[j];
        j++;
        k++;
    }
    
    free(L);
    free(R);
}

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

// 3. 堆排序 - 时间复杂度O(nlogn)
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) {
        swap(&arr[i], &arr[largest]);
        heapify(arr, n, largest);
    }
}

void heapSort(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--) {
        swap(&arr[0], &arr[i]);
        heapify(arr, i, 0);
    }
}
4.3 排序算法的比较和应用
// 1. 排序算法性能测试
void testSortingAlgorithm(void (*sortFunc)(int[], int), const char* name, int arr[], int n) {
    int *testArr = (int*)malloc(n * sizeof(int));
    memcpy(testArr, arr, n * sizeof(int));
    
    clock_t start = clock();
    sortFunc(testArr, n);
    clock_t end = clock();
    
    double time_spent = (double)(end - start) / CLOCKS_PER_SEC;
    printf("%s 用时: %f秒\n", name, time_spent);
    
    // 验证排序结果
    int isSorted = 1;
    for (int i = 1; i < n; i++) {
        if (testArr[i] < testArr[i-1]) {
            isSorted = 0;
            break;
        }
    }
    printf("排序%s\n", isSorted ? "正确" : "错误");
    
    free(testArr);
}

// 2. 排序算法选择指南
/*
选择排序算法的考虑因素:
1. 数据规模
   - 小规模数据(n < 50):插入排序
   - 中等规模(50 <= n < 10000):快速排序
   - 大规模数据(n >= 10000):归并排序或堆排序

2. 稳定性要求
   - 需要稳定排序:归并排序、插入排序、冒泡排序
   - 不需要稳定性:快速排序、堆排序、希尔排序

3. 空间复杂度要求
   - O(1)空间:堆排序、快速排序(平均)
   - O(n)空间:归并排序

4. 数据特征
   - 接近有序:插入排序
   - 完全随机:快速排序
   - 大量重复元素:三路快排
*/

// 3. 实际应用示例
void sortExample() {
    // 生成测试数据
    int n = 10000;
    int *arr = (int*)malloc(n * sizeof(int));
    for (int i = 0; i < n; i++)
        arr[i] = rand() % 10000;
        
    // 测试各种排序算法
    printf("=== 排序算法性能比较 ===\n");
    testSortingAlgorithm(bubbleSort, "冒泡排序", arr, n);
    testSortingAlgorithm(insertionSort, "插入排序", arr, n);
    testSortingAlgorithm(quickSort, "快速排序", arr, n);
    testSortingAlgorithm(mergeSort, "归并排序", arr, n);
    testSortingAlgorithm(heapSort, "堆排序", arr, n);
    
    free(arr);
}

【核心要点】

  1. 基本排序算法

    • 冒泡排序:相邻元素比较交换
    • 选择排序:每次选择最小元素
    • 插入排序:构建有序序列
    • 希尔排序:改进的插入排序
  2. 高级排序算法

    • 快速排序:分治法,基准选择关键
    • 归并排序:分治法,稳定排序
    • 堆排序:利用堆数据结构
  3. 算法选择

    • 考虑数据规模
    • 考虑稳定性要求
    • 考虑空间复杂度
    • 考虑数据特征

⚠️ 注意事项

  1. 基准元素的选择对快排性能影响大
  2. 递归深度可能导致栈溢出
  3. 原地排序vs额外空间
  4. 稳定性的保证
  5. 特殊输入的处理

5. 查找算法

5.1 静态查找
#include <stdio.h>

// 1. 顺序查找
int sequentialSearch(int arr[], int n, int target) {
    for (int i = 0; i < n; i++) {
        if (arr[i] == target)
            return i;
    }
    return -1;
}

// 2. 二分查找(迭代版本)
int binarySearch(int arr[], int n, int target) {
    int left = 0;
    int 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. 二分查找(递归版本)
int binarySearchRecursive(int arr[], int left, int right, int target) {
    if (right >= left) {
        int mid = left + (right - left) / 2;
        
        if (arr[mid] == target)
            return mid;
            
        if (arr[mid] > target)
            return binarySearchRecursive(arr, left, mid - 1, target);
            
        return binarySearchRecursive(arr, mid + 1, right, target);
    }
    return -1;
}

// 4. 插值查找
int interpolationSearch(int arr[], int n, int target) {
    int left = 0;
    int right = n - 1;
    
    while (left <= right && target >= arr[left] && target <= arr[right]) {
        if (left == right) {
            if (arr[left] == target) return left;
            return -1;
        }
        
        // 使用插值公式计算探测点
        int pos = left + (((double)(right - left) * (target - arr[left])) / 
                         (arr[right] - arr[left]));
        
        if (arr[pos] == target)
            return pos;
            
        if (arr[pos] < target)
            left = pos + 1;
        else
            right = pos - 1;
    }
    return -1;
}
5.2 动态查找
// 1. 二叉搜索树节点定义
typedef struct TreeNode {
    int key;
    struct TreeNode *left;
    struct TreeNode *right;
} TreeNode;

// 创建新节点
TreeNode* createNode(int key) {
    TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode));
    node->key = key;
    node->left = node->right = NULL;
    return node;
}

// 插入节点
TreeNode* insert(TreeNode* root, int key) {
    if (root == NULL)
        return createNode(key);
        
    if (key < root->key)
        root->left = insert(root->left, key);
    else if (key > root->key)
        root->right = insert(root->right, key);
        
    return root;
}

// 查找节点
TreeNode* search(TreeNode* root, int key) {
    if (root == NULL || root->key == key)
        return root;
        
    if (key < root->key)
        return search(root->left, key);
        
    return search(root->right, key);
}

// 2. 平衡二叉树(AVL树)节点
typedef struct AVLNode {
    int key;
    struct AVLNode *left;
    struct AVLNode *right;
    int height;
} AVLNode;

// 获取节点高度
int height(AVLNode *N) {
    if (N == NULL)
        return 0;
    return N->height;
}

// 获取平衡因子
int getBalance(AVLNode *N) {
    if (N == NULL)
        return 0;
    return height(N->left) - height(N->right);
}

// AVL树的插入和查找操作(略)
5.3 哈希查找
#define TABLE_SIZE 10

// 1. 链地址法
typedef struct HashNode {
    int key;
    int value;
    struct HashNode* next;
} HashNode;

typedef struct {
    HashNode* table[TABLE_SIZE];
} HashMap;

// 初始化哈希表
void initHashMap(HashMap* map) {
    for (int i = 0; i < TABLE_SIZE; i++)
        map->table[i] = NULL;
}

// 哈希函数
int hash(int key) {
    return key % TABLE_SIZE;
}

// 插入键值对
void insert(HashMap* map, int key, int value) {
    int index = hash(key);
    
    HashNode* newNode = (HashNode*)malloc(sizeof(HashNode));
    newNode->key = key;
    newNode->value = value;
    newNode->next = map->table[index];
    map->table[index] = newNode;
}

// 查找值
HashNode* search(HashMap* map, int key) {
    int index = hash(key);
    HashNode* current = map->table[index];
    
    while (current != NULL) {
        if (current->key == key)
            return current;
        current = current->next;
    }
    return NULL;
}

// 2. 开放地址法
typedef struct {
    int key;
    int value;
    int isOccupied;
} HashEntry;

typedef struct {
    HashEntry* table;
    int size;
} HashTable;

// 初始化开放地址哈希表
HashTable* createHashTable(int size) {
    HashTable* ht = (HashTable*)malloc(sizeof(HashTable));
    ht->table = (HashEntry*)calloc(size, sizeof(HashEntry));
    ht->size = size;
    return ht;
}

// 线性探测
int linearProbe(HashTable* ht, int key) {
    int index = hash(key);
    int i = 0;
    
    while (ht->table[(index + i) % ht->size].isOccupied && 
           ht->table[(index + i) % ht->size].key != key) {
        i++;
        if (i == ht->size) return -1;  // 表满
    }
    return (index + i) % ht->size;
}

【核心要点】

  1. 静态查找

    • 顺序查找:O(n),适用于小规模无序数据
    • 二分查找:O(logn),要求有序数据
    • 插值查找:O(loglogn),适用于均匀分布数据
  2. 动态查找

    • 二叉搜索树:平均O(logn),最差O(n)
    • AVL树:严格O(logn),自平衡
    • 红黑树:O(logn),实际应用广泛
  3. 哈希查找

    • 链地址法:处理冲突,适用于动态数据
    • 开放地址法:节省空间,适用于静态数据
    • 时间复杂度:平均O(1)

⚠️ 注意事项

  1. 选择合适的查找算法要考虑:

    • 数据规模
    • 数据是否有序
    • 数据分布特征
    • 空间限制
    • 查找频率
  2. 实现细节:

    • 边界条件处理
    • 溢出处理
    • 错误处理
    • 资源管理

🔍 应用场景

  1. 静态查找:

    • 有序数组查找
    • 数据库索引
    • 文件检索
  2. 动态查找:

    • 符号表实现
    • 路由表查找
    • 文件系统
  3. 哈希查找:

    • 缓存系统
    • 数据库索引
    • 字符串匹配

6. 字符串算法

6.1 字符串反转
void reverseString(char* str) {
    int length = strlen(str);
    for (int i = 0; i < length/2; i++) {
        char temp = str[i];
        str[i] = str[length-1-i];
        str[length-1-i] = temp;
    }
}
6.2 KMP字符串匹配
void computeLPSArray(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 KMPSearch(char* text, char* pattern) {
    int M = strlen(pattern);
    int N = strlen(text);
    
    int lps[M];
    computeLPSArray(pattern, M, lps);
    
    int i = 0;
    int j = 0;
    while (i < N) {
        if (pattern[j] == text[i]) {
            j++;
            i++;
        }
        if (j == M) {
            return i-j;  // 找到匹配
        } else if (i < N && pattern[j] != text[i]) {
            if (j != 0)
                j = lps[j-1];
            else
                i++;
        }
    }
    return -1;  // 未找到匹配
}

7. 数学算法

7.1 最大公约数(GCD)
int gcd(int a, int b) {
    if (b == 0)
        return a;
    return gcd(b, a % b);
}

// 扩展欧几里得算法
void extendedGCD(int a, int b, int *x, int *y) {
    if (b == 0) {
        *x = 1;
        *y = 0;
        return;
    }
    
    int x1, y1;
    extendedGCD(b, a % b, &x1, &y1);
    
    *x = y1;
    *y = x1 - (a/b) * y1;
}
7.2 素数筛选(埃氏筛)
void sieveOfEratosthenes(int n) {
    int prime[n+1];
    memset(prime, 1, sizeof(prime));
    
    for (int p = 2; p * p <= n; p++) {
        if (prime[p]) {
            // 将p的倍数标记为非素数
            for (int i = p * p; i <= n; i += p)
                prime[i] = 0;
        }
    }
    
    // 打印素数
    for (int p = 2; p <= n; p++)
        if (prime[p])
            printf("%d ", p);
}

8. 图算法

8.1 深度优先搜索(DFS)
#define MAX_VERTICES 100

void DFS(int graph[MAX_VERTICES][MAX_VERTICES], int vertex, int visited[], int V) {
    printf("%d ", vertex);
    visited[vertex] = 1;
    
    for (int i = 0; i < V; i++) {
        if (graph[vertex][i] && !visited[i]) {
            DFS(graph, i, visited, V);
        }
    }
}
8.2 广度优先搜索(BFS)
void BFS(int graph[MAX_VERTICES][MAX_VERTICES], int start, int V) {
    int visited[MAX_VERTICES] = {0};
    int queue[MAX_VERTICES];
    int front = 0, rear = 0;
    
    visited[start] = 1;
    queue[rear++] = start;
    
    while (front < rear) {
        int vertex = queue[front++];
        printf("%d ", vertex);
        
        for (int i = 0; i < V; i++) {
            if (graph[vertex][i] && !visited[i]) {
                visited[i] = 1;
                queue[rear++] = i;
            }
        }
    }
}

9. 动态规划

9.1 斐波那契数列
int fibonacci(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];
}
9.2 背包问题
int knapsack(int W, int wt[], int val[], int n) {
    int dp[n+1][W+1];
    
    for (int i = 0; i <= n; i++) {
        for (int w = 0; w <= W; w++) {
            if (i == 0 || w == 0)
                dp[i][w] = 0;
            else if (wt[i-1] <= w)
                dp[i][w] = max(val[i-1] + dp[i-1][w-wt[i-1]], 
                              dp[i-1][w]);
            else
                dp[i][w] = dp[i-1][w];
        }
    }
    return dp[n][W];
}

以上就是全部的内容。如果各位大佬有疑问,欢迎在评论区留言,你的点赞收藏是我创作的动力!

相关文章:

  • 项目--高并发CPP内存池,低配版本
  • 【人工智能】Deepseek 与 Kimi 联袂:重塑 PPT 创作,开启智能演示新纪元
  • springBoot集成声明式和编程式事务的方式
  • Python基于Django的图书馆管理系统【附源码、文档说明】
  • RangeError: Invalid array length
  • linux0.11内核源码修仙传第五章——内存初始化(主存与缓存)
  • 高颜值多端适用软件:兼具屏保功能,PC 端登录可用
  • 数据结构(队列)
  • DeepSeek-R1本地化部署(Mac)
  • 【原创】springboot+vue实验室预约管理系统设计与实现
  • 增删改查 数据下载 一键编辑 删除
  • SpringSecurity认证授权完整流程
  • 城市霓虹灯夜景拍照后期Lr调色教程,手机滤镜PS+Lightroom预设下载!
  • instr,locate是否使用索引实验
  • DeepSeek【部署 03】客户端应用ChatBox、AnythingLLM及OpenWebUI部署使用详细步骤
  • 并发编程——累加器
  • 【华三】STP端口角色与状态深度解析
  • 仿函数 greater less
  • C++关键字:typename 用于依赖名消歧器(disambiguator)
  • C++进阶知识7 封装map和set
  • site网站连通率0%怎么解决/今日时政新闻热点
  • 服装公司网站建设策划书/2023年6月疫情恢复
  • 怎么用div做网站/超级优化大师下载
  • 宜昌 网站建设 公司/优化步骤
  • 辽宁建设厅勘察设计网站/b站在哪付费推广
  • 生物医药网站建设/株洲seo优化哪家好