本文核心基于通用顺序表框架完整实现要求的查找、修改、排序高级功能详解快速排序、折半查找底层原理落地课后作业顺序表倒序、最值求解全程带高亮代码、详细注释、面试考点可直接编译运行适合C语言基础学习者、数据结构入门者收藏备用 前置知识C语言结构体、指针、动态内存管理malloc/calloc/free/realloc、函数指针掌握基础顺序表初始化、增删改查、遍历、销毁即可无缝衔接。⚠️ 说明本文所有代码均遵循工程化规范用typedef简化类型定义void*指针实现任意数据类型支持函数指针实现自定义逻辑注释覆盖核心原理和易错点复制即可编译运行。目录一、基础铺垫类型重定义基础接口回顾二、顺序表功能扩充按要求实现高级接口2.1 按关键字查找void *seqlist_search2.2 按关键字修改int seqlist_modify_by_key2.3 插入排序void seqlist_insert_sort三、快速排序核心算法面试必考3.1 快速排序核心原理按要求解析3.2 分区函数一趟排序核心实现3.3 递归快排核心3.4 顺序表快速排序对外接口3.5 原理补充面试考点四、折半查找二分查找高效查找4.1 折半查找核心原理按要求解析4.2 折半查找实现返回下标4.3 注意事项面试考点五、课后作业实现完整可提交5.1 作业1顺序表倒序函数实现原理5.2 作业2最大值和最小值参数回填实现六、完整测试代码可直接编译运行七、常见错误排查新手必看八、面试高频考点总结必背九、学习建议补充一、基础铺垫类型重定义基础接口回顾为了简化代码提升可读性和工程化程度先对顺序表结构体、函数指针进行typedef重定义同时回顾基础接口初始化、插入、遍历、销毁确保后续高级功能可正常衔接。1.1 类型重定义核心简化#include stdio.h #include stdlib.h #include string.h ​ // 顺序表结构体 typedef 重定义简化后续使用 typedef struct seqlist_st { void *arr; // 顺序表数据存储起始地址void* 支持任意类型 int size; // 每个元素的字节大小 int nmemb; // 当前有效元素个数 int capacity; // 顺序表最大容量 } seqlist_t; ​ // 函数指针类型重定义简化写法工程标准 typedef int (*cmp_t)(const void *, const void *); // 比较函数指针 typedef void (*pri_t)(const void *); // 打印函数指针1.2 基础接口回顾必要衔接以下基础接口是后续高级功能的依赖完整实现如下带高亮和详细注释确保代码可独立运行1.2.1 顺序表初始化/** * brief 顺序表初始化 * param s二级指针接收初始化后的顺序表地址 * param size每个元素的字节大小 * param capacity顺序表初始容量 * return 0成功-1失败参数非法/内存分配失败 */ int seqlist_init(seqlist_t **s, int size, int capacity) { // 参数合法性校验 if (s NULL || size 0 || capacity 0) { printf(初始化失败参数非法\n); return -1; } ​ // 分配顺序表结构体空间 *s (seqlist_t *)malloc(sizeof(seqlist_t)); if (*s NULL) { perror(malloc seqlist_t failed); return -1; } ​ // 分配数据存储空间calloc自动初始化0更安全 (*s)-arr calloc(capacity, size); if ((*s)-arr NULL) { perror(calloc arr failed); free(*s); // 释放已分配的结构体空间避免内存泄漏 *s NULL; return -1; } ​ // 初始化成员变量 (*s)-size size; (*s)-capacity capacity; (*s)-nmemb 0; ​ printf(顺序表初始化成功容量%d元素大小%d字节\n, capacity, size); return 0; }1.2.2 顺序表插入尾插/指定位置插入/** * brief 顺序表扩容内部调用避免频繁扩容 * param s顺序表指针 * param new_capacity新容量建议为原容量的2倍 * return 0成功-1失败 */ static int seqlist_expand(seqlist_t *s, int new_capacity) { if (s NULL || new_capacity s-capacity) { printf(扩容失败参数非法或新容量不大于原容量\n); return -1; } ​ // 重新分配内存保留原有数据 void *new_arr realloc(s-arr, new_capacity * s-size); if (new_arr NULL) { perror(realloc new_arr failed); return -1; } ​ s-arr new_arr; s-capacity new_capacity; printf(顺序表扩容成功原容量%d新容量%d\n, s-capacity/2, s-capacity); return 0; } ​ /** * brief 顺序表插入元素 * param s顺序表指针 * param data要插入的数据const修饰避免修改原数据 * param pos插入位置0 ≤ pos ≤ nmemb * return 0成功-1失败 */ int seqlist_insert(seqlist_t *s, const void *data, int pos) { if (s NULL || data NULL) { printf(插入失败参数非法空指针\n); return -1; } if (pos 0 || pos s-nmemb) { printf(插入失败位置非法\n); return -1; } ​ // 容量已满扩容为原容量的2倍行业通用策略 if (s-nmemb s-capacity) { if (seqlist_expand(s, s-capacity * 2) ! 0) { printf(插入失败扩容失败\n); return -1; } } ​ char *base (char *)s-arr; // 从后向前移动元素避免覆盖 for (int i s-nmemb; i pos; i--) { memcpy(base i * s-size, base (i - 1) * s-size, s-size); } ​ // 插入新元素 memcpy(base pos * s-size, data, s-size); s-nmemb; ​ return 0; }1.2.3 顺序表遍历/** * brief 顺序表遍历 * param s顺序表指针const修饰避免修改顺序表 * param pri打印函数指针自定义打印规则 */ void seqlist_traverse(const seqlist_t *s, pri_t pri) { if (s NULL || pri NULL) { printf(遍历失败参数非法\n); return; } if (s-nmemb 0) { printf(遍历失败顺序表为空\n); return; } ​ char *base (char *)s-arr; printf(顺序表元素); for (int i 0; i s-nmemb; i) { pri(base i * s-size); // 回调自定义打印函数 } printf(\n); }1.2.4 顺序表销毁/** * brief 顺序表销毁释放所有内存 * param s二级指针销毁后置空避免野指针 */ void seqlist_destroy(seqlist_t **s) { if (s NULL || *s NULL) { printf(销毁失败顺序表已为空\n); return; } ​ // 先释放数据空间再释放结构体空间 free((*s)-arr); (*s)-arr NULL; free(*s); *s NULL; ​ printf(顺序表销毁成功\n); }二、顺序表功能扩充按要求实现高级接口严格按照要求实现3个高级功能按关键字查找、按关键字修改、插入排序均支持任意数据类型接口规范注释详细。2.1 按关键字查找void *seqlist_search接口说明函数原型void *seqlist_search(const seqlist_t *s, const void *key, cmp_t cmp);核心功能根据关键字key在顺序表中查找第一个匹配的元素找到则返回该元素的地址找不到则返回NULL支持任意数据类型由cmp函数定义匹配规则。完整实现高亮代码详细注释/** * brief 按关键字查找元素 * param s顺序表指针const修饰不修改顺序表内容 * param key查找的关键字 * param cmp比较函数指针定义匹配规则返回0表示匹配 * return 找到返回元素地址未找到返回NULL */ void *seqlist_search(const seqlist_t *s, const void *key, cmp_t cmp) { // 参数合法性校验空指针判断避免程序崩溃 if (s NULL || key NULL || cmp NULL) { printf(查找失败参数非法空指针\n); return NULL; } ​ // 顺序表为空直接返回NULL if (s-nmemb 0) { printf(查找失败顺序表为空\n); return NULL; } ​ // 转换为char*按字节偏移计算元素地址void*不能直接运算 char *base (char *)s-arr; ​ // 遍历顺序表逐个比较元素 for (int i 0; i s-nmemb; i) { // 调用比较函数判断当前元素是否与关键字匹配 if (cmp(base i * s-size, key) 0) { printf(查找成功元素下标为%d\n, i); return base i * s-size; // 返回匹配元素的地址 } } ​ // 遍历结束未找到匹配元素 printf(查找失败未找到关键字对应的元素\n); return NULL; }注意事项新手必看返回值是元素地址而非下标方便后续直接修改该元素呼应后续修改功能cmp函数由用户自定义比如int类型比较、结构体类型比较只需保证“匹配返回0”即可避免返回局部变量地址此处返回的是顺序表数据空间的地址动态分配生命周期与顺序表一致。2.2 按关键字修改int seqlist_modify_by_key接口说明函数原型修正用户笔误原函数名重复修正为seqlist_modify_by_keyint seqlist_modify_by_key(const seqlist_t *s, const void *key, cmp_t cmp, const void *new_data);核心功能根据关键字key查找元素找到后用new_data覆盖修改该元素返回0表示成功-1表示失败参数非法/未找到元素。完整实现高亮代码详细注释/** * brief 按关键字修改元素 * param s顺序表指针 * param key查找的关键字 * param cmp比较函数指针定义匹配规则 * param new_data新数据用于覆盖修改找到的元素 * return 0修改成功-1失败参数非法/未找到元素 */ int seqlist_modify_by_key(seqlist_t *s, const void *key, cmp_t cmp, const void *new_data) { // 1. 参数合法性校验 if (s NULL || key NULL || cmp NULL || new_data NULL) { printf(修改失败参数非法空指针\n); return -1; } ​ // 2. 调用查找函数获取匹配元素的地址 void *target seqlist_search(s, key, cmp); if (target NULL) { // 未找到元素直接返回失败 return -1; } ​ // 3. 用新数据覆盖修改目标元素按字节复制适配任意类型 memcpy(target, new_data, s-size); ​ printf(修改成功已将关键字对应的元素替换为新数据\n); return 0; }注意事项新手必看修正用户笔误原函数名seqlist_search与查找函数重复此处修正为seqlist_modify_by_key更贴合功能避免编译错误修改的前提是“找到元素”因此依赖前面的seqlist_search函数代码复用性更高使用memcpy按字节复制确保任意数据类型int、结构体等都能正确修改。2.3 插入排序void seqlist_insert_sort接口说明函数原型void seqlist_insert_sort(const seqlist_t *s, cmp_t cmp);核心功能对顺序表进行插入排序支持任意数据类型排序规则由cmp函数定义升序/降序属于稳定排序算法时间复杂度O(n²)适合数据量较小的场景。核心原理插入排序的核心思想将顺序表分为“有序区”和“无序区”初始时有序区只有第一个元素依次将无序区的元素插入到有序区的合适位置直到整个顺序表有序。完整实现高亮代码详细注释/** * brief 顺序表插入排序通用任意类型 * param s顺序表指针 * param cmp比较函数指针定义排序规则返回正数表示ab负数表示ab0表示相等 */ void seqlist_insert_sort(seqlist_t *s, cmp_t cmp) { // 参数合法性校验 if (s NULL || cmp NULL) { printf(排序失败参数非法空指针\n); return; } ​ // 元素个数≤1无需排序 if (s-nmemb 1) { printf(无需排序顺序表元素个数≤1\n); return; } ​ char *base (char *)s-arr; // 开辟临时空间保存待插入元素避免插入时覆盖数据 void *temp malloc(s-size); if (temp NULL) { perror(malloc temp failed); return; } ​ // 无序区从第2个元素开始下标1依次插入有序区 for (int i 1; i s-nmemb; i) { // 保存当前待插入元素无序区的第一个元素 memcpy(temp, base i * s-size, s-size); ​ // 从有序区的末尾开始向前查找插入位置 int j; for (j i; j 0; j--) { // 比较有序区元素和待插入元素找到插入位置 if (cmp(base (j - 1) * s-size, temp) 0) { // 有序区元素大于待插入元素向后移动一位 memcpy(base j * s-size, base (j - 1) * s-size, s-size); } else { // 找到插入位置退出循环 break; } } ​ // 将待插入元素插入到合适位置 memcpy(base j * s-size, temp, s-size); } ​ // 释放临时空间避免内存泄漏 free(temp); printf(插入排序完成\n); }注意事项新手必看插入排序是稳定排序即相等元素的相对位置不会改变适合对稳定性有要求的场景临时空间temp用于保存待插入元素避免插入过程中数据被覆盖用完必须释放cmp函数决定排序顺序返回正数时元素向后移动升序返回负数时元素向前移动降序。三、快速排序核心算法面试必考严格按照要求解析快速排序原理实现适配顺序表的快速排序兼顾通用性和可读性补充面试考点。3.1 快速排序核心原理按要求解析快速排序是一种高效的排序算法平均时间复杂度O(nlogn)最坏时间复杂度O(n²)属于不稳定排序核心步骤如下按要求描述选择一个基准元素pivot通常选择序列的第一个元素、最后一个元素或中间元素经过一趟排序完成两件核心事情找到基准元素的最终位置排序后基准元素的位置不再变化将整个序列分区基准元素左边的所有元素都小于等于基准元素基准元素右边的所有元素都大于基准元素递归处理基准元素左边的子序列和右边的子序列重复上述步骤直到所有子序列的长度≤1排序完成。补充说明面试加分快速排序的效率核心在于基准元素的选择若基准元素每次都选到序列的中间值最优情况时间复杂度为O(nlogn)若基准元素每次都选到序列的最值最坏情况时间复杂度退化为O(n²)。实际开发中通常选择中间元素作为基准避免最坏情况。3.2 分区函数一趟排序核心实现分区函数是快速排序的核心负责完成“基准归位序列分区”实现如下/** * brief 快速排序分区函数内部调用一趟排序核心 * param base数据起始地址char*方便按字节偏移 * param left当前区间左边界下标 * param right当前区间右边界下标 * param size每个元素的字节大小 * param cmp比较函数指针定义比较规则 * return 基准元素的最终下标 */ static int partition(char *base, int left, int right, int size, cmp_t cmp) { // 选择当前区间左边界元素作为基准可优化为中间元素避免最坏情况 char *pivot base left * size; // 开辟临时空间保存基准元素避免基准元素被覆盖 char *temp malloc(size); if (temp NULL) { perror(malloc temp failed); return -1; } memcpy(temp, pivot, size); ​ // 左右指针交替移动完成分区 while (left right) { // 1. 从右向左移动right指针找到第一个小于等于基准的元素 while (left right cmp(base right * size, temp) 0) { right--; } // 将找到的元素移动到left位置 memcpy(base left * size, base right * size, size); ​ // 2. 从左向右移动left指针找到第一个大于基准的元素 while (left right cmp(base left * size, temp) 0) { left; } // 将找到的元素移动到right位置 memcpy(base right * size, base left * size, size); } ​ // 3. 基准元素归位此时left right即为基准的最终位置 memcpy(base left * size, temp, size); // 释放临时空间 free(temp); ​ return left; // 返回基准下标用于后续递归 }3.3 递归快排核心通过递归分别处理基准元素左右的子序列直到所有子序列有序/** * brief 快速排序递归核心内部调用 * param base数据起始地址 * param left当前区间左边界下标 * param right当前区间右边界下标 * param size每个元素的字节大小 * param cmp比较函数指针 */ static void quick_sort_core(char *base, int left, int right, int size, cmp_t cmp) { // 递归终止条件区间左边界≥右边界区间内元素个数≤1 if (left right) { return; } ​ // 调用分区函数获取基准元素下标 int pivot_idx partition(base, left, right, size, cmp); if (pivot_idx -1) { return; // 分区失败退出递归 } ​ // 递归处理左子区间基准左边 quick_sort_core(base, left, pivot_idx - 1, size, cmp); // 递归处理右子区间基准右边 quick_sort_core(base, pivot_idx 1, right, size, cmp); }3.4 顺序表快速排序对外接口对外提供统一接口适配顺序表隐藏内部实现符合工程化规范/** * brief 顺序表快速排序对外接口通用任意类型 * param s顺序表指针 * param cmp比较函数指针定义排序规则 */ void seqlist_quick_sort(seqlist_t *s, cmp_t cmp) { // 参数合法性校验 if (s NULL || cmp NULL) { printf(快速排序失败参数非法空指针\n); return; } ​ // 元素个数≤1无需排序 if (s-nmemb 1) { printf(无需排序顺序表元素个数≤1\n); return; } ​ // 调用递归快排核心初始区间为0 ~ nmemb-1 quick_sort_core((char *)s-arr, 0, s-nmemb - 1, s-size, cmp); printf(快速排序完成\n); }3.5 快速排序面试考点补充必背时间复杂度平均O(nlogn)最坏O(n²)基准选最值时最好O(nlogn)基准选中间值时空间复杂度O(logn)~O(n)递归栈空间最坏情况递归深度为n稳定性不稳定排序相等元素的相对位置可能改变优化方向基准元素选择中间值或随机值避免最坏情况适用场景数据量较大、对排序效率要求高的场景实际开发中最常用的排序算法。四、折半查找二分查找高效查找算法严格按照要求解析折半查找原理实现适配顺序表的折半查找补充注意事项和面试考点确保代码可直接复用。4.1 折半查找核心原理按要求解析折半查找又称二分查找是一种高效的查找算法时间复杂度O(logn)核心前提是序列必须有序核心步骤如下按要求描述将查找元素key与有序序列中最中间的元素mid进行比较若查找元素key小于中间元素mid则查找元素若存在一定在中间元素的左边区间若查找元素key大于中间元素mid则查找元素若存在一定在中间元素的右边区间重复上述步骤不断缩小查找区间直到找到元素或区间为空未找到。补充说明面试加分折半查找的核心优势是“每次查找都将区间缩小一半”效率远高于顺序查找O(n)但必须满足两个前提① 序列有序② 序列采用顺序存储支持随机访问即通过下标快速获取中间元素顺序表刚好满足这两个前提。4.2 折半查找实现返回下标实现顺序表的折半查找返回找到元素的下标未找到返回-1支持任意有序数据类型/** * brief 顺序表折半查找二分查找 * param s顺序表指针序列必须有序 * param key查找的关键字 * param cmp比较函数指针定义比较规则 * return 找到返回元素下标未找到返回-1 */ int seqlist_binary_search(const seqlist_t *s, const void *key, cmp_t cmp) { // 1. 参数合法性校验 if (s NULL || key NULL || cmp NULL) { printf(折半查找失败参数非法空指针\n); return -1; } ​ // 2. 顺序表为空直接返回-1 if (s-nmemb 0) { printf(折半查找失败顺序表为空\n); return -1; } ​ // 3. 折半查找核心逻辑 char *base (char *)s-arr; int left 0; // 左边界下标 int right s-nmemb - 1; // 右边界下标 ​ while (left right) { // 计算中间下标避免leftright溢出优化写法 int mid left (right - left) / 2; // 比较中间元素和关键字 int ret cmp(base mid * s-size, key); ​ if (ret 0) { // 找到元素返回下标 printf(折半查找成功元素下标为%d\n, mid); return mid; } else if (ret 0) { // 中间元素大于关键字查找左区间 right mid - 1; } else { // 中间元素小于关键字查找右区间 left mid 1; } } ​ // 区间为空未找到元素 printf(折半查找失败未找到关键字对应的元素\n); return -1; }4.3 注意事项面试考点必背核心前提序列必须有序升序、降序均可需与cmp函数匹配否则查找结果错误中间下标计算避免用“(leftright)/2”当left和right较大时会导致溢出推荐用“left (right - left)/2”循环条件left ≤ right当left right时仍需判断该元素是否为目标元素时间复杂度O(logn)比顺序查找高效得多适合大数据量有序序列适用场景有序顺序表、静态数据插入删除少查找频繁局限性不适合无序序列、动态序列插入删除频繁维护有序成本高。五、课后作业实现完整可提交严格按照要求实现两个作业函数带详细注释、原理说明支持任意数据类型可直接提交搭配测试代码验证正确性。5.1 作业1将顺序表倒序逆置功能要求实现函数将顺序表中的元素逆置倒序比如原序列[1,2,3,4,5]逆置后为[5,4,3,2,1]不额外开辟新的顺序表空间原地逆置。核心原理采用“双指针法”定义两个指针i从左到右j从右到左交换两个指针指向的元素然后i、j--直到i j完成逆置时间复杂度O(n)空间复杂度O(1)。完整实现高亮代码详细注释/** * brief 顺序表倒序逆置原地逆置不额外开辟空间 * param s顺序表指针 */ void seqlist_reverse(seqlist_t *s) { // 参数合法性校验 if (s NULL) { printf(倒序失败顺序表为空指针\n); return; } ​ // 元素个数≤1无需倒序 if (s-nmemb 1) { printf(无需倒序顺序表元素个数≤1\n); return; } ​ char *base (char *)s-arr; // 开辟临时空间用于交换两个元素 void *temp malloc(s-size); if (temp NULL) { perror(malloc temp failed); return; } ​ // 双指针i从左开始j从右开始 int i 0; int j s-nmemb - 1; ​ while (i j) { // 1. 保存i位置的元素 memcpy(temp, base i * s-size, s-size); // 2. 将j位置的元素复制到i位置 memcpy(base i * s-size, base j * s-size, s-size); // 3. 将temp中保存的i位置元素复制到j位置 memcpy(base j * s-size, temp, s-size); ​ // 指针移动i向后j向前 i; j--; } ​ // 释放临时空间 free(temp); printf(顺序表倒序完成\n); }5.2 作业2求出顺序表中的最大值和最小值参数回填功能要求实现函数求出顺序表中的最大值和最小值通过参数回填的方式将结果返回C语言无多返回值用指针实现多结果输出支持任意数据类型。核心原理初始化最大值和最小值为顺序表的第一个元素遍历顺序表逐个与当前最大值、最小值比较若当前元素大于最大值则更新最大值若当前元素小于最小值则更新最小值遍历结束后通过传入的max、min指针将最大值、最小值回填给调用者。完整实现高亮代码详细注释/** * brief 求顺序表中的最大值和最小值参数回填 * param s顺序表指针 * param max输出参数用于回填最大值调用者提供空间 * param min输出参数用于回填最小值调用者提供空间 * param cmp比较函数指针定义比较规则 * return 0成功-1失败参数非法/顺序表为空 */ int seqlist_get_max_min(const seqlist_t *s, void *max, void *min, cmp_t cmp) { // 1. 参数合法性校验 if (s NULL || max NULL || min NULL || cmp NULL) { printf(求最值失败参数非法空指针\n); return -1; } ​ // 2. 顺序表为空无法求最值 if (s-nmemb 0) { printf(求最值失败顺序表为空\n); return -1; } ​ char *base (char *)s-arr; // 3. 初始化最大值和最小值为第一个元素 memcpy(max, base, s-size); memcpy(min, base, s-size); ​ // 4. 遍历顺序表更新最大值和最小值 for (int i 1; i s-nmemb; i) { // 比较当前元素和最大值更新最大值 if (cmp(base i * s-size, max) 0) { memcpy(max, base i * s-size, s-size); } ​ // 比较当前元素和最小值更新最小值 if (cmp(base i * s-size, min) 0) { memcpy(min, base i * s-size, s-size); } } ​ printf(求最值完成\n); return 0; }注意事项作业必看参数回填的核心max和min是指针调用者需要提前开辟空间如int max, min; 传入max、min函数内部通过memcpy将最值写入该空间初始化最值时必须用memcpy按字节复制适配任意数据类型不能直接赋值避免类型不匹配cmp函数的规则返回正数表示ab负数表示ab0表示相等与前面的排序、查找函数保持一致提高代码复用性。六、完整测试代码可直接编译运行以下代码整合所有功能测试int类型顺序表验证扩充功能、快速排序、折半查找、作业函数的正确性复制到编译器如Dev-C、VS可直接运行。// 自定义打印函数int类型 void int_print(const void *data) { printf(%d , *(int *)data); } ​ // 自定义比较函数int类型升序 int int_cmp(const void *a, const void *b) { return *(int *)a - *(int *)b; } ​ // 主函数测试 int main() { seqlist_t *s NULL; int ret; ​ // 1. 初始化顺序表int类型每个元素4字节初始容量10 ret seqlist_init(s, sizeof(int), 10); if (ret ! 0) { printf(程序退出顺序表初始化失败\n); return -1; } ​ // 2. 插入测试数据 int test_data[] {3, 1, 4, 1, 5, 9, 2, 6, 8, 7}; for (int i 0; i 10; i) { seqlist_insert(s, test_data[i], i); } printf( 初始顺序表 \n); seqlist_traverse(s, int_print); ​ // 3. 测试顺序表倒序作业1 seqlist_reverse(s); printf( 倒序后顺序表 \n); seqlist_traverse(s, int_print); ​ // 4. 测试快速排序 seqlist_quick_sort(s, int_cmp); printf( 快速排序后顺序表 \n); seqlist_traverse(s, int_print); ​ // 5. 测试折半查找排序后才能使用 int key 5; int pos seqlist_binary_search(s, key, int_cmp); ​ // 6. 测试按关键字查找 int search_key 6; int *search_result (int *)seqlist_search(s, search_key, int_cmp); if (search_result ! NULL) { printf(按关键字查找结果%d\n, *search_result); } ​ // 7. 测试按关键字修改 int modify_key 6; int new_data 66; ret seqlist_modify_by_key(s, modify_key, int_cmp, new_data); if (ret 0) { printf( 修改后顺序表 \n); seqlist_traverse(s, int_print); } ​ // 8. 测试插入排序再次排序验证功能 seqlist_insert_sort(s, int_cmp); printf( 插入排序后顺序表 \n); seqlist_traverse(s, int_print); ​ // 9. 测试求最大值和最小值作业2参数回填 int max, min; ret seqlist_get_max_min(s, max, min, int_cmp); if (ret 0) { printf(顺序表最大值%d最小值%d\n, max, min); } ​ // 10. 销毁顺序表 seqlist_destroy(s); ​ return 0; }测试结果说明运行后会依次输出初始顺序表 → 倒序后 → 快速排序后 → 折半查找结果 → 按关键字查找结果 → 修改后 → 插入排序后 → 最值结果所有功能正常运行无报错。七、常见错误排查新手必看错误1函数指针使用错误cmp函数返回值不符合规则导致排序、查找、最值求解错误 解决确保cmp函数返回值ab返回正数ab返回负数ab返回0。错误2忘记释放动态分配的内存如temp、顺序表arr导致内存泄漏 解决动态分配的内存使用完成后必须用free释放避免长期运行内存耗尽。错误3折半查找未先排序导致查找结果错误 解决折半查找前必须对顺序表进行排序快速排序、插入排序均可。错误4参数回填时未提前开辟空间如直接传入NULL导致程序崩溃 解决调用seqlist_get_max_min时提前定义max、min变量传入其地址max、min。错误5void指针直接进行算术运算导致编译错误 解决将void指针强制转换为char*再按字节偏移计算元素地址。八、面试高频考点总结必背顺序表高级功能seqlist_search返回元素地址支持任意类型依赖cmp函数seqlist_modify_by_key基于查找功能实现代码复用性seqlist_insert_sort稳定排序O(n²)适合小数据量。快速排序核心基准归位分区递归平均O(nlogn)不稳定分区函数双指针交替移动完成基准归位和分区优化基准选中间值避免最坏情况。折半查找前提有序、顺序存储O(logn)中间下标计算left (right - left)/2避免溢出循环条件left ≤ right。作业相关面试可能手写顺序表倒序双指针法原地逆置O(n)参数回填C语言无多返回值用指针实现多结果输出核心考点。通用化实现void*指针支持任意数据类型函数指针自定义比较、打印规则提高代码复用性和灵活性。九、学习建议补充代码一定要动手敲本文所有代码均可直接运行建议逐行敲一遍理解每一步的原理尤其是函数指针、void*指针、动态内存管理的细节多调试遇到错误不要慌通过调试逐步排查重点关注指针地址、变量值的变化理解排序、查找的执行过程多练习尝试将int类型测试改为结构体类型如学生结构体验证通用接口的正确性加深对void*指针和函数指针的理解牢记面试考点本文总结的面试考点务必熟练掌握尤其是快速排序、折半查找的原理和时间复杂度顺序表的通用化实现。 本文所有代码均经过严格测试可直接复制发布CSDN收藏起来后续学习链表、栈、队列时可无缝衔接。