以升序为例:
a.比较相邻的两个数字,若前者大于后者,则交换两个数字的顺序,反之则不交换;(ps:交换两个数字的顺序)
b.重复上述操作,直到最大的数字“沉”入最右边,最小的数字“浮”在最左边为止。
假如有 N 个数字排序,那么需要比较 N-1 趟,在每一趟的比较中,比较次数有所不同,第 i 趟比较需要比较 N-1-i 次。
/*
* 函数名称:BubbleSort
*
* 函数功能:冒泡排序(升序)方法1
*
* 入口参数:a, len
*
* 出口参数:无
*
* 返回类型:void
*/
void BubbleSort(int * a, int len)
{
int i = 0;
int j = 0;
assert(NULL != a);
for (i=0; i a[j+1]) {
a[j] = a[j] ^ a[j+1];
a[j+1] = a[j] ^ a[j+1];
a[j] = a[j] ^ a[j+1];
}
}
}
return;
}
不足:即使所给数字是有序的,上述算法仍会对其进行一趟又一趟的比较,这样效率太低。
改进:考虑设置一个标志位,假如在某一趟比较中没有发生任何数字的交换,那么说明此刻已经是一个有序的序列,不需要再进行比较了。
首先设置一个标志位 flag = 1,每次进入循环后先把 flag 置 0,假如发生了数字交换,再把 flag 置 1,最后判断 flag 的值,假如为 0 则结束循环。
/*
* 函数名称:BubbleSort
*
* 函数功能:冒泡排序(升序)方法2
*
* 入口参数:a, len
*
* 出口参数:无
*
* 返回类型:void
*/
void BubbleSort(int * a, int len)
{
int i = 0;
int j = 0;
int flag = 1;
assert(NULL != a);
while (flag) {
flag = 0;
for (i=0; i a[j+1]) {
a[j] = a[j] ^ a[j+1];
a[j+1] = a[j] ^ a[j+1];
a[j] = a[j] ^ a[j+1];
flag = 1;
}
}
}
if (0 == flag)
break;
}
return;
}
不足:代码繁琐,多次判断 flag 。
改进:考虑在外层循环中同时判断 flag 以及外层循环变量。
/*
* 函数名称:BubbleSort
*
* 函数功能:冒泡排序(升序)方法3
*
* 入口参数:a, len
*
* 出口参数:无
*
* 返回类型:void
*/
void BubbleSort(int * a, int len)
{
int i = 0;
int j = 0;
int flag = 1;
assert(NULL != a);
for (i=0; (i a[j+1]) {
a[j] = a[j] ^ a[j+1];
a[j+1] = a[j] ^ a[j+1];
a[j] = a[j] ^ a[j+1];
flag = 1;
}
}
}
return;
}
当然,也可以使用指针来实现冒泡排序。
/*
* 函数名称:BubbleSort
*
* 函数功能:冒泡排序(升序)方法4 (指针实现)
*
* 入口参数:pArr, len
*
* 出口参数:无
*
* 返回类型:void
*/
void BubbleSort(int * pArr, int len)
{
int * left = pArr;
int * right = pArr + len - 1;
int * current = pArr;
int flag = 1;
assert(NULL != pArr);
for (left=pArr; (left *(current+1)) {
*current = (*current) ^ (*(current+1));
*(current+1) = (*current) ^ (*(current+1));
*current = (*current) ^ (*(current+1));
flag = 1;
}
}
}
return;
}
#define _CRT_SECURE_NO_WARNINGS 1
/*
* Copyright (c) 2018, code farmer from sust
* All rights reserved.
*
* 文件名称:BubbleSort.c
* 功能:冒泡排序算法实现(升序)
*
*/
# include
# include
# include
# define ARRAY_LEN 4
/*
* 函数名称:Input
*
* 函数功能:输入数据
*
* 入口参数:pNum, length
*
* 出口参数:无
*
* 返回类型:void
*/
void Input(int * pNum, int length)
{
int k = 0;
if ((NULL != pNum) && (length > 0)) {
for (k=0; k 0)) {
for (m=0; m
#define _CRT_SECURE_NO_WARNINGS 1
/*
* Copyright (c) 2018, code farmer from sust
* All rights reserved.
*
* 文件名称:StringBubbleSort.c
* 功能:冒泡排序之排序多个字符串
*
*/
# include
# include
# include
/*
* 函数名称:StringBubbleSort
*
* 函数功能:多个字符串冒泡排序(升序)
*
* 入口参数:str, len
*
* 出口参数:void
*
* 返回类型:void
*/
void StringBubbleSort(char * *str, int len)
{
int i = 0;
int flag = 1;
assert((NULL != str));
for (i=0; (i 0) {
char * tmp = str[j];
str[j] = str[j+1];
str[j+1] = tmp;
flag = 1;
}
}
}
return;
}
/*
* 函数名称:OutputStr
*
* 函数功能:输出字符串
*
* 入口参数:str, len
*
* 出口参数:void
*
* 返回类型:void
*/
void OutputStr(char * *str, int len)
{
int i = 0;
assert((NULL != str));
for (i=0; i
/*
* 函数名称:Swap
*
* 函数功能:交换内容
*
* 入口参数:s1, s2, width
*
* 出口参数:void
*
* 返回类型:void
*/
void Swap(char * s1, char * s2, int width)
{
int i = 0;
assert((NULL != s1) && (NULL != s2));
for(i=0; i 0) {
Swap((char *)base + width * j, (char *)base + width * (j+1), width);
}
}
}
return;
}
接下来以排序结构体中的姓名为例,
#define _CRT_SECURE_NO_WARNINGS 1
/*
* Copyright (c) 2018, code farmer from sust
* All rights reserved.
*
* 文件名称:CommonBubbleSort.c
* 功能:不区分数据类型的冒泡排序
* void qsort( void *base, size_t num, size_t width,
* int (__cdecl *compare)(const void *elem1, const void *elem2) );
*
*/
# include
# include
# include
struct Student
{
char name[20];
int age;
};
/*
* 函数名称:CmpStructName
*
* 函数功能:比较结构体中的姓名
*
* 入口参数:e1, e2
*
* 出口参数:大于0 or 小于0 or 等于0
*
* 返回类型:int
*/
int CmpStructName(const void * e1, const void * e2)
{
assert((NULL != e1) && (NULL != e2));
return strcmp(((struct Student *)e1)->name, ((struct Student *)e2)->name);
}
/*
* 函数名称:PrintStructData
*
* 函数功能:打印结构体内容
*
* 入口参数:stu, len
*
* 出口参数:void
*
* 返回类型:void
*/
void PrintStructData(struct Student stu[], int len)
{
int i = 0;
for (i=0; i