C进阶:指针(2),qsort函数,模拟实现冒泡算法(下)

简介: C进阶:指针(2),qsort函数,模拟实现冒泡算法(下)

cmp_int 函数解释:

三.模拟实现冒泡算法

1.什么是冒泡排序

冒泡排序

冒泡排序(英语:Bubble Sort)是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序(如从大到小、首字母从A到Z)错误就把他们交换过来。

过程演示:

图解:

下面来看一个实例:

1. void bubble_sort(int arr[], int len)
2.  {
3. int i, j, temp;
4. for (i = 0; i < len - 1; i++)    //确定趟数
5.     {
6. for (j = 0; j < len - 1 - i; j++)  //对一趟进行冒泡排序
7.         {
8. if (arr[j] > arr[j + 1]) 
9.             {
10.                 temp = arr[j];
11.                 arr[j] = arr[j + 1];
12.                 arr[j + 1] = temp;
13.             }
14.         }
15.     }
16. }
17. int main() 
18. {
19. int arr[] = { 22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70 };
20. int len = (int) sizeof(arr) / sizeof(*arr);
21. bubble_sort(arr, len);
22. int i;
23. for (i = 0; i < len; i++)
24. printf("%d ", arr[i]);
25. return 0;
26. }

其实我们会发现,上面这种方法有一定的局限性,它只能排整型数据,那我们可不可以写一个类似于冒泡排序算法的函数来实现可以排序任何数据呢?

这就需要利用到回调函数了

2.模拟实现冒泡算法

通过上文我们知道,qsort 是一个可以快速排序的库函数,它使用起来很方便,那么我们就可以模仿 qsort 函数的定义来实现 一个可以排任何数据的冒泡函数 bubble_sort;

函数名有了,接下来就是函数参数和返回值的设计了,仿照 qsort ,我们可以这么设计:

void bubble ( void*base , size_t  sz  ,size_t  width, void (*cmp) (const void * ,const void * )

1.第一个参数 是指向要排序的数组的第一个元素的指针;

2.第二个参数 是数组元素的个数;

3.第三个参数 是数组每个元素的大小,也可以理解成宽度,单位是字节;

4.第四个参数 是一个函数指针,且需要我们自己设计

那么这个函数要怎么设计呢?

我们知道冒泡排序是两个相邻元素之间的比较,所以说在设计函数参数时,参数应该指向的是数组中两个相邻的元素,可是我们在设计函数时并不知道参数的具体类型,又该怎么向函数传数组中的两个相邻元素呢?

请看下图:

两个相邻的元素找到了,下面就是交换了

交换就需要创建一个中间变量,可是我们并不知道要交换的两个数据的类型,那自然就不知道该怎么定义中间变量的类型,但是众所周知,所有的数据类型中 char 是最小的,只占1个字节,那么其他的数据类型我们都可以看成是由若干个 char 组成的,所以我们可以定义一个 char 变量来作为中间变量,然后对数据进行一个一个字节的交换,交换终止的条件由 width 决定,所以我们定义的 width 也要传到交换函数里面去。

具体代码:

1. void Swap(char* buf1, char* buf2, int width)  
2. {
3.  int i = 0;
4.  for (i = 0; i < width; i++)  //循环由 width 控制
5.  {
6.    char tmp = *buf1;   //一个一个字节进行交换
7.    *buf1 = *buf2;
8.    *buf2 = tmp;
9.    buf1++;      //一个字节交换完后 ,buf1++ buf2++,再进行下一轮的字节交换
10.     buf2++;
11.   }
12. }

实例:

1. int cmp_int(const void* e1, const void* e2)
2. {
3.  return *((int*)e2) - *((int*)e1);
4. } 
5. //交换函数
6. void Swap(char* buf1, char* buf2, int width)
7. {
8.  int i = 0;
9.  for (i = 0; i < width; i++)
10.   {
11.     char tmp = *buf1;
12.     *buf1 = *buf2;
13.     *buf2 = tmp;
14.     buf1++;
15.     buf2++;
16.   }
17. }
18. //模拟实现冒泡算法,并使它可以排任何类型的数据
19. void bubble_sort(void* base, int sz, int width, int (*cmp)(const void* e1, const void* e2))
20. {
21.   int i = 0, j = 0;
22.   for (i = 0; i < sz - 1; i++)  //确定趟数
23.   {
24.     for (j = 0; j < sz - 1 - i; j++) //一趟比较
25.     {
26.       if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
27.       {
28.         Swap((char*)base + j * width, (char*)base + (j + 1) * width, width); //交换
29.       }
30.     }
31.   }
32. }
33. //打印数组
34. void print(int arr[], int sz)
35. {
36.   int i = 0;
37.   for (i = 0; i < sz; i++)
38.   {
39.     printf("%d ", arr[i]);
40.   }
41.   printf("\n");
42. }
43. void test4()
44. {
45.   int arr[10] = { 1,3,5,7,9,2,4,6,8,10 };
46.   int sz = sizeof(arr) / sizeof(arr[0]);
47.   bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);
48.   print(arr, sz);
49. }
50. int main()
51. {
52.   test4();
53.   return 0;
54. }

运行结果:

  😸😼本篇文章到此就结束啦,如有错误或是建议,欢迎小伙伴们指出。🐆🐅

  😻😽谢谢你的阅读。🦖🦄                


目录
相关文章
|
2月前
|
存储
指针进阶详解(下)
指针进阶详解(下)
22 0
|
2月前
|
C++
定义和使用指向函数的指针变量
定义和使用指向函数的指针变量
15 1
|
1月前
|
搜索推荐 C语言 C++
【C指针(五)】6种转移表实现整合longjmp()/setjmp()函数和qsort函数详解分析&&模拟实现3
【C指针(五)】6种转移表实现整合longjmp()/setjmp()函数和qsort函数详解分析&&模拟实现
|
6天前
|
搜索推荐 C语言
详解指针进阶2
详解指针进阶2
|
19天前
|
存储 C语言
指针数组作为main函数的形参
指针数组作为main函数的形参
14 0
|
23天前
|
算法
|
2月前
|
存储 编译器 C语言
指针进阶详解(上)
指针进阶详解(上)
87 0
指针进阶详解(上)
|
2月前
|
存储 算法 搜索推荐
【算法】七大经典排序(插入,选择,冒泡,希尔,堆,快速,归并)(含可视化算法动图,清晰易懂,零基础入门)
【算法】七大经典排序(插入,选择,冒泡,希尔,堆,快速,归并)(含可视化算法动图,清晰易懂,零基础入门)
|
2月前
|
安全 C语言 C++
字符指针做函数参数
字符指针做函数参数
10 1