使用冒泡排序模拟实现qsort函数

本文详细介绍了如何用冒泡排序算法模拟C标准库中的qsort函数,包括参数理解、比较函数的编写以及如何处理不同类型的元素,通过逐字节操作实现元素间的比较和交换。
摘要由CSDN通过智能技术生成

一、冒泡排序和qsort函数

在模拟qsort函数之前,我们先回顾一下排序和qsort函数:

冒泡排序:不断的把最大的、第二大的、第三大的数···排到正确的位置。

#include<stdio.h>
int main() {
	int arr[] = { 3,2,6,4,5,1,9,7,0,8 };
	int i = 0;
	for (i = 0; i < 9; i++) {
		int j = 0;
		for (j; j < 9 - i; j++) {
			if (arr[j] > arr[j + 1]) {
				int temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;

			}
		}
	}
	for (i = 0; i < 10; i++) {
		printf("%d", arr[i]);
	}
	return 0;
}

qsort函数:void __cdecl qsort(void *_Base, size_t _NumOfElements, size_t _SizeOfElements, _CoreCrtNonSecureSearchSortCompareFunction _CompareFunction)

这里仅以int类型数组排序举例:

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

二、模拟构思

如我们所见,qsort函数需要的参数有:需要排序的数组(字符串)、数组(字符串)长度、每个元素的大小和一个需要自己来完成的比较两个元素大小的函数。

用冒泡排序模拟的qsort函数的运行流程应为:

1、传参;

2、以上文中提到的冒泡排序的排序方式(即不断地将(剩下的数组中)最大的元素转移到后面;

3、由于我们在模拟qsort函数时不知道要排序的变量类型,所以需要另写一个函数来给出比较两个元素大小的方式(即qsort函数中需要使用者完成的compare function部分);

4、在进行比较之后,如需将两个元素调换,则我们需要写出一个给两个元素调换位置的函数。

三、函数模拟

首先我们写出冒泡排序函数主体部分,并预留出cmp(比较)和-swap(调换)的部分。

void* bubble_sort(void* arr, size_t len, size_t size, int (*cmp)(const void* e1, const void* e2)) {
	int i = 0;
	for (i = 0; i < len - 1; i++) {
		int j = 0;
		for (j; j < len - 1 - i; j++) {//以上为冒泡排序函数主体逻辑部分
			if(cmp)//比较方式
				_swap()//调换方式
		}
	}
}

接下来我们来完成-swap函数,即比较后调换两个元素的函数。

要写出-swap函数,我们需要将两个元素传递给swap。同时,因为我们不知道需要排序的两个元素的变量类型,而且bubble_sort函数接受的arr也是void类型的,所以我们在swap中使用void函数来进行接收。

void swap(void* e1, void* e2) {

}

在写cmp和swap函数中,我们可以发现:因为我们并不知道变量类型,所以我们不能像平常那样直接使用*e1-*e2(int/char)。在这里,我们可以将所有元素都强制类型转化为char类型,对每个元素逐字节进行比较和调换。那在强制类型转换为char类型之后,我们该如何表示某个元素和其下一个元素呢?这时,每个元素的size就派上了用场。

我们可以把第j个元素写为(char*)arr+j*size,则第j+1个元素为(char*)arr+(j+1)*size;同时,因为在swap中进行调换时也是逐字节调换的,所以我们需要将size也作为参数传递给swap函数。

代码如下:

void _swap(void* e1, void* e2, size_t size) {
	int i = 0;
	for (i; i < size; i++) {
		char temp = *((char*)e1 + i);
		*((char*)e1 + i) = *((char*)e2 + i);
		*((char*)e2 + i) = temp;
	}
}

四、全部代码及其使用(以int类型举例)

//fun.h
#pragma once
#include<stdio.h>
void* bubble_sort (void* arr, size_t len, size_t size, int (*cmp)(const void* e1, const void* e2));
void _swap(void* e1, void* e2, size_t size);
//fun.c
#include"fun.h"
void _swap(void* e1, void* e2, size_t size) {
	int i = 0;
	for (i; i < size; i++) {
		char temp = *((char*)e1 + i);
		*((char*)e1 + i) = *((char*)e2 + i);
		*((char*)e2 + i) = temp;
	}
}
void* bubble_sort(void* arr, size_t len, size_t size, int (*cmp)(const void* e1, const void* e2)) {
	int i = 0;
	for (i = 0; i < len - 1; i++) {
		int j = 0;
		for (j; j < len - 1 - i; j++) {
			if (cmp((char*)arr + j * size, (char*)arr + (j + 1) * size) > 0)
				_swap((char*)arr + j * size, (char*)arr + (j + 1) * size,size);
		}
	}
}
//main,函数使用
#include"fun.h"
int int_cmp(const void* e1, const void* e2) {
	return *(int*)e1 - *(int*)e2;
}
int main() {
	int arr[] = { 6,2,3,4,7,5,1,9,8,0 };
	bubble_sort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(arr[0]), int_cmp);
	for (int i = 0; i < (sizeof(arr) / sizeof(arr[0])); i++){
		printf("%d", arr[i]);
	}
	return 0;
}

其调用后结果如图:

以上就是本篇博客全部内容,如果你觉得这篇博客对你有所帮助的话,不要忘了点赞收藏和关注哦!

  • 11
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值