回调函数之经典案例 快速排序(冒泡法)

本文介绍了回调函数的概念,并通过一个具体的冒泡排序算法实例展示了如何使用回调函数来进行灵活的比较操作。通过将比较逻辑封装成独立的函数,使得排序算法更加通用且易于维护。

回调函数:回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事或条件进行响应。

#include<stdio.h>
int int_cmp(const void * p1,const void * p2)
{
  return  (*(int *)p1 >  *(int *)p2);
}
void _swap(void * p1, void * p2,int sz)
{
  int i = 0;
  for( i = 0;i < sz; i++)
  {
    char tmp = *((char *)p1 + i);
    *((char *)p1 + i) = *((char *)p2 + i);
    *((char *)p2 + i) = tmp;
  }
}
void bubble(void * base,int count ,int sz, int(*cmp)(const void *,const void *))
{
  int  i = 0;
  int j = 0;
  for(i = 0; i < count - 1; i++)
  {
   for(j = 0; i < count - 1 -i; i++)
   {
     if(cmp((char *)base + j*sz,(char *)base + (j + 1)*sz) > 0)
     {
      _swap((char *)base + j*sz,(char *)base + (j + 1)*sz,sz);
     }
   }
  }
}
int main()
{
    int arr[] = {1,3,5,7,9,2,4,6,8,0};
    int i = 0;
    int sz = sizeof(arr)/sizeof(arr[0]);
    bubble(arr, sz, sizeof(int),int_cmp );
    for(i = 0; i < sz; i++)
    {
        printf("%d ",arr[i]);
    }
    printf("\n");
 return 0; 
}
C语言程序设计基础 数据类型: 数据类型定义与格式化调用一致(涉及强制转换(涉及void任意型)) 整型与字符型之间存在对应关系(涉及ascii表及isxxxxx类库函数) 除for()内的i,n或Arr的下标外均可将int换为long long 运算过程中可能会溢出int甚至long long(涉及取模运算) 注意有时long long不宜直接进行非整除得double? 注意有时需要unsigned int或unsigned long long型 注意区分1(默认int),1LL,1ULL(常见于位运算>>或<<中) 指针根据指向对象亦有类型;变量地址必为size_t整型 函数根据返回的情况具有数据类型,注意函数参数所需类型 int,long long,double型分别对应绝对值函数abs,llabs,fabs 标准整型比较: return (a > b) -(a < b); 若a > b返回1 数据结构: 条件语句: if-else或if-else if-else,避免并列if的出现 注意:()后无分号;运算符及其优先级(括号);非0即真 选择语句: switch-case-break-default 注意break的对跃出当前case的作用 循环语句: for/while/do-while(L.不定组输入);break;continue;goto 注意:for中i的首末及增量;while死循环;do-while至少执行一次 注意:i++和++i的差异及初值经循环后的意义;注意for()后的分号 注意:多级循环注意下标检索的区分;提前break或continue可优化 注意:break仅跳出一层循环,可考虑sign或flag等额外标记处理之 注意:goto A;A:后不能直接连定义语句,而需分号空语句单独占一行 注意:时间复杂度(数据的预处理及检索;不要反复调用strlen等函数) 输入输出: 输入基础: scanf(不支持空格/换行),fgets(不支持换行符),getchar(支持字符) scanf:需对非字符串型取地址&传入;字符(匹配)或字符串前消空白 scanf:可返回正确输入的个数;遇EOF(cntrl^Z)失败 fgets:可能会占用str余下位置填充’\n’;len(str)=strlen(str)-1;删换行 getchar:getchar()可消去”%c””%s”scanf输入前的空白字符 多组输入: 若仅需实现提问次数的限制,直接while(n--)即可,否则建议for()处理 可考虑数组存储 不定输入: while(scanf(“%d%d”)==2)//正常输入则继续 while((c=getchar())!EOF&&c!=’\n’)//非终止或换行则继续 while(fgets(str,sizeof(str),stdin!=NULL)//非空则继续至换行 while(1){终止条件} 可考虑数组存储 输出基础: printf(注意添加换行);puts(自动换行) printf格式化输出(符号;前导;宽度;精度);注意特殊转义’\’;%% 一次输入可直接对应一次输出,或采用数组存储一次性输入输出 常量变量: 常量可采用宏定义:EPS;MAX_N且:acos(-1)=π;exp(1)=e str[]=”Hello”为不可修改的字符串常量;拓展:指针常量与常量指针 变量分全局变量和局部变量;函数调用时全局变量不在形参列表中 变量必须先定义再调用;定义和调用需要数据类型的对应 变量名之间不应重复,注意一般变量名与数组名需要不同 尽量避免重定义 浮点精度 浮点数的二进制存储方式 浮点数比较:EPS精度控制;fabs(a-b)<=EPS判断相等? /截断;floor下取整;ceil上取整;round四舍五入;int(x+0.5)强制转换? 模拟浮点数:整数部分先输出,小数部分借助.x输出,得形式上的浮点数 超高精度的四则运算及阶乘等:涉及数组与进位模拟(可能需四舍五入) 位运算 基本运算:&(位与),|(位或),^(异或),~(取反),>>(右移),<<(左移) 基础取位操作:(x>>i)&1可取x第i位的二进制数 基础置位操作:x&=~(1LL<<i);x|=(1LL<<i)分别将第i位置0,1 基础翻转操作:x^= (1LL << i)可将第i位翻转 a^b^a=b可实现二元数值交换,节省一中间变量 快速计算与奇偶判断:快速幂;二的乘方与幂次判断;奇偶数判断 数组 定义n长数组下标从0到n-1; 不允许定义以变量为长度的数组 较大数组需放main外(建议统一外置);会自动初始化为全零数组 数组初始化需要注意初始化数值对后续输入数据的影响 数组前后元素比较时,循环下标可自i=1开始,比较[i-1]和[i]防越界 数组在最值求解时需要直接预设其为[0]而非自设初始值 数组在频率统计等问题中涉及到数组嵌套,注意含义解析 数组可用于记忆化/判断是否已操作! 数组的前缀和/差项的应用! 二维数组定义时第一维可缺省,内存会自动分配 二维数组字符串列表,调用一维A[i]即调用i对应字符串 二维数组可用于矩阵/坐标/图案/字符串或状态列表等 任意维数组都可划归为一维数组,都可用指针代替 sizeof()返回数组总字节数;strlen()遇’\0’记其前元素数 字符串 字符串本质是以’\0’作结的字符数组;有时需要强制补’\0’ 字符串列表可以二维数组形式表现,二维缺省以一维下标查找 字符串比较:strcmp;strncmp strcmp(s1,s2):全等返回0;字典序s1[i]>s2[i]返回正差值 strncmp(s1,s2,n):比较下标[0]到[n-1],返回情况同上所述 字符串拼接:strcat;strncat strcat(dest,s1):s1置于dest后,会删除dest后’\0’;注意长度 strncat(dest,s1,n):s1前至多n符置于dest后,可能需要强制补’\0’ 字符串复制strcpy;strncpy strcpy(dest,s1):将s1复制入dest;注意长度 strncpy(dest,s1,n):将s1至多n符复制入dest,可能需要强制补’\0’ 字符串子串strstr strstr(target,s1):在target中找s1,返回其子串首指针,否则NULL 字符查找strchr;strrchr strchr(target,c):在target中查找字符c并返回首次出现c的指针 查找范围包括’\0’,因此:strchr(s,’\0’)可获取字符串末尾 strrchr(target,c):在target中查找字符c并返回末次出现c的指针 数串转换:sprintf;snprintf;sscanf sscanf(str,xxx%dxxx,num)实现str中格式化提取%d等(类正则) sprintf(dest,”%d”,num):实现将num强制转换为字符形式的’0’-‘9’ snprintf(des,n,”%d,num);实现仅对至多n位num执行上述操作 指针视角下str+i可实现字符串首元素偏移 指针 涉及对变量地址的访问,涉及取地址和解引用;通过地址访问变量值 数组和字符串均可通过指针形式访问具体元素,+i表示偏移i位次 指针涉及:常量指针,指针常量,多级指针,函数指针;注意指针类型 指针经典运用:swap函数通过地址对a,b实现值交换 库函数 <stdio.h>标准输入输出库 格式化输出printf, fprintf, sprintf, snprint 格式化输入scanf, fscanf, sscanf 读一个字符getchar, getc, fgetc 写一个字符putchar, putc, fputc 读字符串fgets 写字符串fputs, puts <stdlib.h>通用工具库 动态内存分配与释放malloc, calloc, realloc, free 字符串转整数/浮点数atoi, atol, atoll, atof 更安全的字符串转数字strtol, strtoul, strtod 求绝对值abs, labs, llabs 快速排序qsort 二分查找bsearch <string.h>字符串和内存操作 字符串拷贝strcpy, strncpy 字符串拼接strcat, strncat 字符串比较strcmp, strncmp 获取字符串长度strlen 查找字符strchr, strrchr 查找子串strstr 字符串分割(破坏原串)strtok <math.h>数学函数库 三角函数(弧度) sin, cos, tan 反三角函数asin, acos, atan 指数与对数exp, log, log10 乘方与开方pow(x, y), sqrt 向某端取整ceil, floor 舍入与截断round, trunc 浮点绝对值fabs 浮点取模fmod <ctype.h>字符类型判断与转换 是否字母isalpha 是否数字isdigit 是否字母或数字isalnum 是否小写/大写islower, isupper 是否空白字符isspace 转小写/大写tolower, toupper 函数 自定义函数注意:形参列表及返回值数据类型,数组应传长度 自定义函数可在形参列表不包含的情况下运用定义的全局变量 自定义函数必须先声明,可统一声明后再写函数功能函数或调用 自定义函数支持嵌套,但要注意开销 递归 形式上是函数的自调用;每次调用效果近似且问题收敛于可终止的情况 构造递归无需全程模拟,只需要保证问题可拆为近似的子问题且可终止 可考虑记忆化递归避免每次调用的重复计算 排序 经典排序:冒泡排序;快速排序(+三路快排);归并排序 如何实现排序规则的自定义和排序的二元及多元扩展 查找 经典查找:线性查找;二分查找 二分查找多形式可选(顺位首下标/顺位末下标/首次检索?) 宏 宏定义不要与变量名混淆 思想方法 线性规划:连续优化(含部分坐标模拟) 动态规划:子问题+记忆化;状态定义+转移方程+边界条件 贪心算法:每一步最优易得全局最优(需:贪心选择性质+最优子结构) 深度优先搜索:单路径深入与分支回溯 广度优先搜索:由远及近遍历树或图 分治法:子问题分解与递归合并结果 回溯法:穷尽尝试与上一步回退重选 数论:推导与规律
最新发布
12-03
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值