一、冒泡排序和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;
}
其调用后结果如图:
以上就是本篇博客全部内容,如果你觉得这篇博客对你有所帮助的话,不要忘了点赞收藏和关注哦!