1.冒泡排序原理及代码
冒泡排序的原理其实很简单,从左到右,相邻元素两两进行比较,并根据大小关系进行交换,直至完成整组数据的排序。例如,对 9, 8 ,7, 6, 5,4, 3,2,1,0,进行升序排序,其冒泡排序具体步骤如下:
|
9 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
第一次 |
8 |
9 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
第二次 |
8 |
7 |
9 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
第三次 |
8 |
7 |
6 |
9 |
5 |
4 |
3 |
2 |
1 |
0 |
...... |
|
|
|
|
|
|
|
|
|
|
...... |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
9 |
...... |
7 |
8 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
9 |
...... |
7 |
6 |
8 |
5 |
4 |
3 |
2 |
1 |
0 |
9 |
这样相邻的元素进行比较交换,逐步完成所有数据的升序排序。代码如下:
#include
void bubble_sort(int arr[], int sz)
{
int i = 0;
for (i = 0; i < sz - 1; i++)//冒泡排序的趟数
{
int flag = 1;//假设数组是排好序的
//一趟冒泡排序的过程
int j = 0;
for (j = 0;j < sz-1-i; j++)
{
if (arr[j] > arr[j + 1])
{
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
flag = 0;//有交换置0,说明数组存在无序
}
}
if (flag == 1)
{
break;
}
}
}
int main()
{
int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
//把数组排成升序
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr,sz);
int i = 0;
for (i = 0; i < sz; i++)//打印排序后的数组
{
printf("%d ",arr[i]);
}
return 0;
}
为了减少运算的情况,在上述代码中添加了 flag 变量,因为当数组元素无需进行交换时,数组元素是有序的,此时可跳出循环。
2.qsort()函数详解
上述的冒泡排序只能排序整形元素,实际在编程中会遇到各类需要排序的情况,如我们要对结构体的成员变量进行排序,此时我们要如何实现呢?C语言的库函数 qsort() 就能很好的帮助我们完成,qsort() 可以排序任意类型的数据,它使用了快速排序的思想,下面的代码给出了 qsort() 函数的定义:
void qsort(void* base, //排序数据的起始位置
size_t num, //待排序的数据元素个数
size_t width, //待排序数据元素大小(单位字节)
int(_cdecl* compare)(const void* elem1, const void* elem2)//函数指针-比较函数
);
//_cdecl - 函数调用约定
其中 void* 无具体类型的指针,可以接受任意类型的地址
void* 无具体类型的指针,不能解引用操作,也不能 + - 整数
3. qsort()函数实现对结构体成员的排序
我们根据qsort()函数的定义,向其转递合适的参数,首先我们演示了利用结构体成员的姓名来进行排序,代码如下:
#include
#include
#include
int cmp_stu_name(const void* e1, const void* e2)
{
return strcmp(((struct stu*)e1)->name, ((struct stu*)e2)->name);
//字符串比较strcmp,strcmp返回值<0,=0,>0,
}
struct stu
{
char name[20];
int age;
};
int main()
{
struct stu s[] = { {"zhangsan", 15}, {"lisi", 20}, {"wangwu", 25} };
int sz = sizeof(s) / sizeof(s[0]);
qsort(s, sz, sizeof(s[0]), cmp_stu_name);
return 0;
}
qsort() 函数需要按照自己的需求完成一个比较函数及其调用,在这里,由于进行的是名字的比较,因此调用了字符串比较函数 strcmp ,我们可通过调试观察到排序的结果,如下图所示:
排序前:
排序后:
同理,我们可以按照结构体成员年龄进行排序,需调整的代码如下:
int cmp_stu_age(const void* e1, const void* e2)
{
return ((struct stu*)e1)->age - ((struct stu*)e2)->age;
}
struct stu s[] = { {"zhangsan", 15}, {"lisi", 30}, {"wangwu", 25} };
int sz = sizeof(s) / sizeof(s[0]);
qsort(s, sz, sizeof(s[0]), cmp_stu_age);
排序前:
排序后:
4.利用冒泡排序代码的方式实现qsort()
写的这里,我们是否可以改造一下我们最开始的冒泡排序,使其具备 qsort() 函数同样的功能呢?答案是可以的。
首先是利用冒泡排序实现数组元素的升序
#include
#include
#include
int cmp_int(const void* e1, const void* e2)
{
return (*(int*)e1 - *(int*)e2);
}
void Swap(char* buf1, char* buf2, int width)
{
int i = 0;
for (i = 0; i < width; i++)
{
char temp = *buf1;
*buf1 = *buf2;
*buf2 = temp;
buf1++;
buf2++;
}
}
void bubble_sort(void* base, int sz, int width, int(*cmp)(const void* e1, const void* e2))
{
int i = 0;
for (i = 0; i < sz - 1; i++)//冒泡排序的趟数
{
int flag = 1;//假设数组是排好序的
//一趟冒泡排序的过程
int j = 0;
for (j = 0;j < sz-1-i; j++)
{
if (cmp((char*)base + j * width, (char*)base + (j + 1) * width)>0)
{
//交换
Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
flag = 0;
}
}
if (flag == 1)
{
break;
}
}
}
int main()
{
int arr[] = { 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]);
}
return 0;
}
同理只需更改成相应的比较函数,即可实现qsort()同样的功能,代码如下:
struct stu
{
char name[20];
int age;
};
int cmp_int(const void* e1, const void* e2)
{
return (*(int*)e1 - *(int*)e2);
}
int cmp_stu_name(const void* e1, const void* e2)
{
return strcmp(((struct stu*)e1)->name, ((struct stu*)e2)->name);
//字符串比较用strcmp,strcmp返回值<0,=0,>0,
}
int cmp_stu_age(const void* e1, const void* e2)
{
return ((struct stu*)e1)->age - ((struct stu*)e2)->age;
}
int main()
{
//int arr[] = { 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]);
//}
struct stu s[] = { {"zhangsan", 15}, {"lisi", 30}, {"wangwu", 25} };
int sz = sizeof(s) / sizeof(s[0]);
//bubble_sort(s, sz, sizeof(s[0]), cmp_stu_name);
bubble_sort(s, sz, sizeof(s[0]), cmp_stu_age);
return 0;
}
// bubble_sort()代码在前面,这里不再重复
最后,通过以上描述,我们可以完成多种需求的排序。