冒泡排序与qsort演示冒泡

冒泡排序简单来说就是相邻两数字进行比较,谁大排后面,比较完之后就得到了有序的数组

例如

我有一个待排的数字序列:3 5 8 10 2

第一次比较 3 5 8 2 10

第二次比较 3 5 2 8 10

第三次比较 3 2 5 8 10

第四次比较 2 3 5 8 10

由此我们可以知道,你的序列有几个,比较的次数是序列-1

那么我们的代码如下

#include <stdio.h>
void BubbleSort(int arr[], int sz)
{
	int i = 0;
	int j = 0;
	int tmp = 0;
	int flag = 1;//防止数组已经有序排列却还要进行比较的现象发生
	for ( i = 0; i < sz-1; i++)//排序次数等于数组总数减一
	{
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
				flag = 0;
			}
		}
		if (flag)
			break;
	}
}
int main()
{
	int arr[] = { 8,3,2,5,9,10,11 };
	int sz = sizeof(arr) / sizeof(arr[0]);//获取数组有几个元素
	int i = 0;
	BubbleSort(arr, sz);
	for ( i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

但我们这个代码是有缺点的,就是它只能比较整型的数字,因此我们可以使用C语言自带的qsort函数来进行排序,我们可以看qsort的详细介绍

这个是它的声明

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

我们可以发现这个函数需要四个形参

第一个形参需要接收的是指针,意思是该函数要数组的首元素地址

第二个参数是数组元素的个数

第三个参数是每个元素的大小,以字节为单位

第四个参数是函数指针,这是要我们自己写一个能比较两个元素大小的函数,然后把函数的地址传给这个形参。

代码如下

#include <stdio.h>
int compare(const void* e1, const void* e2)
{
	return (*(int*)e1 - *(int*)e2);
}
int main()
{
	int arr[] = { 8,3,2,5,9,10,11 };
	int i = 0;
	qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), compare);
	for ( i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

compare函数中的e1和e2都是指针,指向一个整数,通过它们指向的地址所存放的数字进行比较,返回它们相差的值。一般我们的指针都是有特定的类型的,比如int*,char*。但我们这里是放了void*,这是无具体类型的指针,能够接收任意类型的地址。但不能进行计算,不能加减整数,也不能解引用,因此我们要强制转换成int*类型进行运算。

qsort不仅能用于整数排序,也可以用在字符、浮点数、结构体等排序

以字符和结构体的为例

接下来是字符的

#include <stdio.h>
/*字符比较的是ascii码的大小*/
int char_compare(const void* e1, const void* e2)
{
	return *(char*)e1 - *(char*)e2;
}
int main()
{
	char arr[] = "hello";
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz - 1, sizeof(arr[0]), char_compare);
	//因为字符串有\0因此减1
	printf("%s", arr);
	return 0;
}

接下来是结构体的

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Stu
{
	char name[20];
	int age;
};
int point_compare_by_name(const void* e1, const void* e2)
{
	strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
}
int point_compare_by_age(const void* e1, const void* e2)
{
	return (((struct Stu*)e1)->age) - (((struct Stu*)e2)->age);
}
int main()
{
	int i = 0;
	struct Stu s[] = {{"zhangsan",15},{"lisi",30},{"wangwu",25}};
	int sz = sizeof(s) / sizeof(s[0]);
	qsort(s, sz, sizeof(s[0]), point_compare_by_name);
	for ( i = 0; i < sz; i++)
	{
		printf("%s %d\n", s[i].name, s[i].age);
	}
	qsort(s, sz, sizeof(s[0]), point_compare_by_age);
	for (i = 0; i < sz; i++)
	{
		printf("%s %d\n", s[i].name, s[i].age);
	}
	return 0;
}

接下来我们用冒泡排序去模拟qsort

代码如下

#include <stdio.h>
#include <stdlib.h>
//void Swap(const void* e1, const void* e2,int width)//char写法
//{
//	char tmp = 0;//最好写char跟后面的对应
//	int i = 0;
//	for ( i = 0; i < width; i++)
//	{
//		tmp = *((char*)e1 + i);
//		*((char*)e1 + i) = *((char*)e2 + i);
//		*((char*)e2 + i) = tmp;
//	}
//}
void Swap(const void* e1, const void* e2, int sz)//int写法
{
	int tmp = 0;
	int i = 0;
	tmp = *((int*)e1);
	*((int*)e1) = *((int*)e2);
	*((int*)e2) = tmp;
}
int compare(const void* e1, const void* e2)
{
	return (*(int*)e1 - *(int*)e2);
}
void BubbleSort(void* base, int sz, int width, int (*compare)(const void*, const void*))
{
	int i = 0;
	int j = 0;
	for ( i = 0; i < sz; i++)
	{
		for (j = 0; j < sz - 1 - i; j++)
		{
			/*if (compare((char*)base + j * width, (char*)base + (j+1) * width) > 0)
			{
				Swap((char*)base + j * width, (char*)base + (j+1) * width, width);
			}*/
			if (compare((int*)base + j , (int*)base + (j + 1)) > 0)
			{
				Swap((int*)base + j, (int*)base + (j + 1), sz);
			}
		}
	}
}
int main()
{
	int i = 0;
	int arr[] = { 1,7,5,4,9,8,2 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	BubbleSort(arr, sz, sizeof(arr[0]), compare);
	for ( i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

因为int能跳四个字节,而char只能跳一个字节,因此有不同的写法。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值