C语言---冒泡排序和qsort函数的应用

发布于:2025-06-30 ⋅ 阅读:(19) ⋅ 点赞:(0)

目录

1 冒泡排序实现

2 qsort函数 

 3 qsort函数的模拟实现


1 冒泡排序实现

实现一个冒泡排序函数,思路:两两相邻元素比较,如果不满足顺序就交换

例如,对int arr[10]={9,8,7,6,5,4,3,2,1,0};进行冒泡排序,产生一个升序的数组。

以此类推,10个元素进行9趟排序,n个元素进行n-1趟排序。

代码实现:

#include <stdio.h>
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 + 1] < arr[j])
			{
				flag = 0;
				int temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
		if (flag == 1)
		{
			break;
		}
	}
}
int main()
{
	int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	Bubble_sort(arr, sz);
	for ( int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	return 0;
}

代码中的函数只能排序整型数组,这样就有局限性,这就引出了qsort函数

2 qsort函数 

 qsort是用来排序的库函数,qsort函数可以排序任意类型的数据。使用时要用头文件<stdlib.h>

void qsort (void* base, size_t num, size_t size,   int (*compar)(const void*,const void*));

这个函数有4个参数

1 void* base是指针,指向的是待排序的数组的第一个元素

2 size_t num是base指向的待排序数组的元素个数

3 size_t size是base指向的待排序数组的元素大小

4 int (*compar)(const void*,const void*)是函数指针,指向的是两个元素的比较函数,比较函数用来比较两个数的函数大小,这个是根据不同类型数组进行排序时,由我们自行编写的。

如图,比较函数参数中的两个指针p1和p2,返回一个小于0的数字,p1排在p2前面; 返回一个大于0的数字,p2排在p1前面;如果相等,则返回0,那么我们就可以编写一段代码来使用以下qsort函数:

//一、qsort排列整型数据
#include <stdio.h>
#include <stdlib.h>
int int_cmp(const void* p1,const void* p2)
{
	return (*(int*)p1 - *(int*)p2);
}
int main()
{
	int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);//计算数组长度
	qsort(arr, sz, sizeof(arr[0]), int_cmp);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	return 0;
}

 输出结果:

比较函数

int int_cmp(const void* p1,const void* p2)
{
    return (*(int*)p1 - *(int*)p2);

这里的两个参数是固定的,我们要排序的序列是9 8 7 6 5 4 3 2 1 0,那么这两个指针指向的是整型类型的数据,而p1,p2是void*类型的指针,所以需要先进行强制类型转换,再做差,大于0时交换两个数据。这样再使用语句qsort(arr, sz, sizeof(arr[0]), int_cmp);就能把一个杂乱的数组排序成升序

如果要排列成降序呢?

只需要改变函数的逻辑:

int int_cmp(const void* p1,const void* p2)
{
    return (*(int*)p2 - *(int*)p1);

意义就是后一个数大于前一个数,交换两个数字。返回一个大于0的数字,p2排在p1前面

#include <stdio.h>
#include <stdlib.h>
int int_cmp(const void* p1,const void* p2)
{
	return (*(int*)p2 - *(int*)p1);
}
int main()
{
	int arr[10] = { 8,7,9,6,5,3,1,4,2,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);//计算数组长度
	qsort(arr, sz, sizeof(arr[0]), int_cmp);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	return 0;
}

输出结果,排列成降序:

再举一个例子。利用qsort排序结构体的数据:

//二、使用qsort实现结构体排序
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct Stu
{
	char name[20];
	int age;
};
int cmp_stu_by_name(const void* p1, const void* p2)
{
	return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);
}
int cmp_stu_by_age(const void* p1, const void* p2)
{
	return (((struct Stu*)p1)->age - ((struct Stu*)p2)->age);
}
int main()
{
	struct Stu arr[3] = { {"zhang san",20},{"li si",30},{"wang wu",40}};
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);//按照名字排序
	qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_age);//按照年龄排序
	return 0;
}

 3 qsort函数的模拟实现

#include <stdio.h>
#include <stdlib.h>
int cmp_int(const void* p1, const void* p2)
{
	return (*(int*)p1 - *(int*)p2);
}
void Print_arr(int* arr, int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}
void swap(char* buf1,char* buf2,size_t width)
{
	int i = 0;
	for (i = 0; i < width; i++)
	{
		char temp = *buf1;
		*buf1 = *buf2;
		*buf2 = temp;
		buf1++;
		buf2++;
	}
}
void bubble_sort(char* base, size_t sz, size_t width, int(*cmp)(const void* p1, const void* p2))
{
	int i = 0;//趟数
	for (i = 0; i < sz - 1; i++)
	{
		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);
			}
		}
	}
}
int main()//模拟实现qsort函数
{
	int arr[10] = { 9,7,8,6,3,5,4,1,2,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);
	Print_arr(arr,sz);
	return 0;
}

代码结构

cmp_int:用于比较两个整数的函数(升序),小于0时是降序

Print_arr:打印整型数组

swap:交换两个内存块的内容(按每个字节交换)

bubble_sort:通用的冒泡排序函数,支持任意数据类型。

交换函数

void swap(char* buf1,char* buf2,size_t width)
{
    int i = 0;
    for (i = 0; i < width; i++)
    {
        char temp = *buf1;
        *buf1 = *buf2;
        *buf2 = temp;
        buf1++;
        buf2++;
    }
}

逐字节交换 buf1 和 buf2 指向的 width 字节内存。使用char* 是因为char 是 1 个字节,可以处理任意数据类型(如 intstruct 等)。

通用冒泡排序函数

void bubble_sort(char* base, size_t sz, size_t width, int(*cmp)(const void* p1, const void* p2))
{
    int i = 0;//趟数
    for (i = 0; i < sz - 1; i++)
    {
        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);
            }
        }
    }

参数:

base:数组首地址,转换为 char* 以便按字节计算偏移,满足通用性。

 sz:元素个数。

width:每个元素的字节大小。

cmp:比较函数指针。 

逻辑:通过 base + j * width 计算第 j 个元素的地址。调用 cmp 比较相邻元素。如果 cmp 返回 > 0,调用 swap 交换内存内容

以上就是这篇文章的全部内容了,如果这篇文章对你有用,可以点点赞哦,你的支持就是我写下去的动力,后续会继续分享更多的知识。


网站公告

今日签到

点亮在社区的每一天
去签到