(一)冒泡排序实现对整形数组的排序
在以前,我们只会使用冒泡排序的方法对整行数组进行排序,简单的两个for循环,外层循环控制循环次数,内层循环控制比较次数,就像下面代码,便可实现:
#include<stdio.h>
int main()
{
int arr[10]={11,9,8,7,6,5,4,3,2,1};
int i=0;
int j=0;
int tmp=0;
for(j=0;j<10;j++)
{ for(i=0;i<10-j;i++)
if(arr[i]>arr[i+1])
{
tmp=arr[i];
arr[i]=arr[i+1];
arr[i+1]=tmp;
}
}
for(i=0;i<10;i++)
printf("%d ",arr[i]);
return 0;
在此基础上我们可以使用回调函数,能够同时实现对整形数组和字符串的排序
(二)什么是回调函数
回调函数就是一个通过函数指针(void (*perfect)(int ))调用的函数 。如果你把函数的指针(地址)作为参数传递给另一个函数void myCallback(void (*perfect)(int ),int n),当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。
通俗一点的可以这样理解,你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打了你的电话,然后你接到电话后就到店里去取了货。在这个例子里,你的电话号码就叫回调函数,你把电话留给店员就叫登记回调函数,店里后来有货了叫做触发了回调关联的事件,店员给你打电话叫做调用回调函数,你到店里去取货叫做响应回调事件。回答完毕。
为什么要使用回调函数?
因为可以把调用者与被调用者分开。调用者不关心谁是被调用者,所有它需知道的,只是存在一个具有某种特定原型、某些限制条件(如返回值为int)的被调用函数。
下面便是一个简单的回调函数例子,相比其他的那些复杂的代码,我觉得这个更容易理解:
#include<stdio.h>
#include<stdlib.h>
void perfect(int n)
{
int i=1;
int count=0;
for(i=1;i<n;i++)
{
if(0==n%i)
{
count+=i;
}
}
if(count==n)
printf("%d是完数\n",n);
else printf("%d不是完数\n",n);
}
void myCallback(void (*perfect)(int ),int n)
{
perfect(n);
}
int main()
{
int n;
printf("请输入一个正整数\n");
scanf("%d",&n);
myCallback(perfect,n);
return 0;
}
(三)回调函数实现对整形数组和字符串的排序
冒泡排序可以实现对任意类型的数据进行排序,函数原型如下:
void bubble(void *base, int count, int length, int(*cmp)(const void *,const void *))
其中:
void *base:待排序数组的首地址
int count:数组中待排序元素的个数
int length:各个元素占用空间的大小
int(*cmp)(const void *,const void *):指向比较函数的指针,用于确定排序的顺序
compare的函数原型为:
int cmp_char(const void *p1,const *p2)
{
assert(p1);
assert(p2);
return strcmp((char *)(*(int *)p1), (char *)(*(int *)p2));
}
以下代码写出了字符数组和整形数组的比较函数:
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
/*整型数组比较函数*/
int cmp_int(const void *p1, const void *p2)
{
assert(p1);//检测指针的有效性
assert(p2);
//由于只要满足(*(int *)p1 > *(int *)p2))>0时才交换,其余情况都不交换
return (*(int *)p1 > *(int *)p2) ? 1 : -1;
//if (*(int *)p1 > *(int *)p2)
// return 1;
//else if (*(int *)p1 == *(int *)p2)
// return 0;
//else return -1;
}
/*字符型数组比较函数*/
int cmp_char(const void *p1,const *p2)
{
assert(p1);
assert(p2);
return strcmp((char *)(*(int *)p1), (char *)(*(int *)p2));//将p1强制类型转化为整形,然后截引用,因为进行的是字符串的比较,所以又要将它再次强制类型转化为字符类型
}
/*交换函数*/
void swap(void *p1, void *p2, int size)
{
int i = 0;
assert(p1);
assert(p2);
for (i = 0; i < size; i++)
{
char temp = *((char *)p1+i);
*((char *)p1+i) = *((char *)p2+i);
*((char *)p2+i) = temp;
}
}
/*冒泡排序*/
void bubble(void *base, int count, int length, int(*cmp)(const void *,const void *))//利用回调函数实现
{
int i = 0;
int j = 0;
assert(base);
for (i = 0; i < count-1; i++)
{
for (j = 0; j < count - i - 1; j++)
{
if (cmp((char*)base + length*j, (char*)base + length*(j + 1))>0)
swap((char*)base + length*j, (char*)base + length*(j + 1),length);
}
}
}
int main()
{
int arr[] = { 2, 3, 6, 7, 0, 9, 1, 5, 4, 8 };
char *str[] = { "cdefc", "dcbar", "aefva", "beksf","cbsle", "cdefg"};
int len = sizeof(arr) / sizeof(arr[0]);
int size = sizeof(str) / sizeof(str[0]);
int i ,j;
bubble(arr, len,sizeof(int *),cmp_int);
bubble(str, size,sizeof(char *),cmp_char);
for (i = 0; i < len; i++)
{
printf("%d ",arr[i]);
}
printf("\n");
for (j = 0; j < size; j++)
{
printf("%s\n", str[j]);
}
system("pause");
return 0;
}