C语言详解-冒泡排序与qsort()函数

1.冒泡排序原理及代码

冒泡排序的原理其实很简单,从左到右,相邻元素两两进行比较,并根据大小关系进行交换,直至完成整组数据的排序。例如,对 9876543210,进行升序排序,其冒泡排序具体步骤如下:

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 ,我们可通过调试观察到排序的结果,如下图所示:

排序前:

C语言详解-冒泡排序与qsort()函数_第1张图片

排序后:

C语言详解-冒泡排序与qsort()函数_第2张图片

同理,我们可以按照结构体成员年龄进行排序,需调整的代码如下:

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);

排序前:

C语言详解-冒泡排序与qsort()函数_第3张图片

排序后:

C语言详解-冒泡排序与qsort()函数_第4张图片

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()代码在前面,这里不再重复

最后,通过以上描述,我们可以完成多种需求的排序。

你可能感兴趣的:(c语言,开发语言,排序算法,算法)