冒泡排序的工作原理
它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行,直到没有相邻元素需要交换,也就是说该元素列已经排序完成。
一般冒泡排序
一般的冒泡排序只适用于特定类型元素的排序,例如只能排整形元素,对于浮点型或者结构体就不再适用,这是它的一大缺点。
推广后的冒泡排序
推广后的冒泡排序既可以排序整形数组,又可以排浮点型和结构体。但相对与一般的冒泡排序,推广后的冒泡排序实现起来相对复杂,需要耐心地去理解。
知识铺垫
void*
>void*类型的指针可以接收任意类型的地址
>void*类型的指针不能进行解引用操作,因为void*无具体类型,访问几个字节不确定
>void*类型的指针不能进行+-整数的操作,因为void* 无具体类型,一次向前或向后跳几个字节不确定
qsort函数---任意类型数组排序的通用函数,结构体也可以
void qsort( 1 , 2 , 3 , 4 )
>1 待排序数组的首元素地址,一般情况下为数组名。
>2 待排序数组的元素个数
>3 待排序数组的每个元素大小
>4 接收比较函数的指针(比较函数需自己定义)---该函数的两个参数是待比较的两个元素的地址
qsort(arr, sz1, sizeof(arr[0]), cmp_int);
【.】可以对结构体的内容进行访问
自己实现的推广冒牌排序就是模仿上述库函数来实现的。
代码还会涉及到强制类型转换等知识。下面请看代码(可复制 ):
代码实现
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
struct student
{
char name[20];
int age;
};
void Swap(char* buf1, char* buf2, int width)
//把宽度传过来才知道一个元素有几个字节,要交换几次
{
int i = 0;
for (i = 0; i < width; i++)
//每完成一趟循环交换一个字节,利用了char++跳过一个字节的特性
{
char tmp = 0;
tmp = *buf1;
*buf1 = *buf2;
*buf2 = tmp;
buf1++;
buf2++;
}
}
//整形的比较方法
int cmp_int(void* e1, void* e2)
{
return *(int*)e1 - *(int*)e2;
}
//浮点型的比较方法
int cmp_float(const float* e1, const float* e2)
{
return (int)(*(float*)e1) - (int)(*(float*)e2);
}
//结构体的比较方法
int cmp_stu_s_by_age(const void* e1, const void* e2)
{
return ((struct student*)e1) ->age - ((struct student*)e2) ->age;
}
void bubble_sort(void* base, int sz, int width, int (*cmp)(void* e1, void* e2))
{
int i = 0;
for (i = 0; i < sz - 1; i++)//i表示趟数,比元素个数少1
{
int j = 0;
for (j = 0; j < sz - 1 - i; j++)//每一趟中要比较的对数
{
if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)//升序
{
//(char*)base指向第一个元素,加上width后,正好跳过一个int类型的宽度,指向下一个元素
Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
}
}
}
}
void test1()
{
int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);//调用自定义的排序函数
int i = 0;
for (i = 0; i < sz; i++)//打印排列后的数组元素
{
printf("%d ", arr[i]);
}
printf("\n");
}
void test2()
{
float f[] = { 9.0,8.0,7.0,6.0,5.0,4.0 };
int sz = sizeof(f) / sizeof(f[0]);
bubble_sort(f, sz, sizeof(f[0]), cmp_float);
int n = 0;
for (n = 0; n < sz; n++)
{
printf("%f ", f[n]);
}
printf("\n");
}
void test3()
{
struct student s[] = { {"zhangsan",20},{"lisi",15},{"wangwu",13} };
bubble_sort(s, 3, sizeof(s[0]), cmp_stu_s_by_age);
int n = 0;
for (n = 0; n < 3; n++)
{
printf("%d ", s[n].age);
}
}
int main()
{
test1();//整形
test2();//浮点型
test3();//结构体
return 0;
}