버블 정렬 시뮬레이션은 qsort 기능을 구현합니다.
머리말
qsort() 함수를 시뮬레이션하려면 먼저 qsort() 함수의 특성을 알아야 합니다.
- 빠른 정렬 방법을 사용하십시오.
- 모든 데이터 유형에 대한 정렬.
그러나 일부 학자들은 아직 퀵 정렬 알고리즘을 배우지 않았기 때문에 이 블로그에서는 버블 정렬을 사용하여 qsort()와 유사한 bubble_sort 함수를 시뮬레이션합니다.
C 라이브러리는 qsort() 함수를 설명합니다.
qsort() 함수의 매개변수에 대해 얻은 정보:
void qsort(void* base, //指向排序的第一个元素
size_t num, //排序元素的个数
size_t size,//一个元素的大小,单位为字节
int (*cmp)(const void*, const void*)//函数指针类型 — 这个函数指针指向的函数,能够比较base指向数组的两个元素
);
1. 분석
먼저 정수 데이터를 정렬하는 일반 버블 정렬을 살펴보겠습니다.
void bubblr_sort(int arr[], int sz)
{
//排序趟数
for (int i = 0; i < sz - 1; i++)
{
int tmp = 0;
//每趟比较对数
for (int j = 0; j < sz - 1 - i; j++)
{
//假设升序,交换元素
if (arr[i] > arr[i + 1])
{
tmp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = tmp;
}
}
}
}
int main()
{
int arr[10] = {
10,9,8,7,6,5,4,3,2,1 };
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr, sz);
return 0;
}
qsort() 함수는 버블 정렬에 의해 시뮬레이션되기 때문에 위의 코드를 기반으로 사용할 수 있으며 시뮬레이션 구현을 변경해야 합니다. 그러나 몇 가지 문제가 있습니다! !
- 정수뿐만 아니라 다양한 데이터 유형을 받아들이는 방법.
- 예를 들어 서로 다른 데이터의 경우 구조를 > 또는 <로 간단히 비교할 수 없습니다. 그렇다면 이를 달성하는 방법은 무엇입니까?
- 다른 데이터 유형의 경우 교환이 약간 다릅니다.
2. 솔루션 1, 다른 데이터를 받아들이는 방법
void*는 모든 유형의 데이터를 가리킬 수 있는 C 언어의 일반 포인터 유형입니다. 그래서 매개변수 base를 void* 유형 포인터로 정의하여 다른 데이터를 허용할 수 있습니다.
void* 사용 확장:
- void* 포인터를 사용할 때 포인터 타입의 크기를 모르기 때문에 특정 포인터 타입으로 변환해야 동작한다. 예를 들어 void 포인터를 int 포인터로 변환한 다음 *할당하거나 역참조할 수 있습니다.
2. void *는 untyped 포인터로 산술 연산을 수행할 때 이동할 바이트 수를 결정하기 위해 포인터가 가리키는 특정 데이터 유형의 크기를 알아야 하므로 직접 산술 연산을 수행할 수 없습니다.
3. 솔루션 2, 서로 다른 데이터의 비교를 실현하는 방법
데이터 유형마다 비교 방법이 다르기 때문에 시뮬레이션된 bubble_sort() 함수 매개변수에 함수 포인터를 추가할 수 있습니다. 두 요소의 비교 방법을 함수 매개변수 형태로 전달합니다.
팁:
- 현재 들어오는 데이터는 예로 정수이므로 cmp_int라는 비교 함수를 정의합니다. 기사의 끝에서 구조 데이터를 전달하기 위한 구현 코드가 제공됩니다.
암호
//bubble_sort()实参传入
bubble_sort(arr,sz, sizeof(arr[0]), cmp_int);
//bubble_sort()函数参数实现
void bubble_sort(void* base, int num, int size, int (*cmp)(const void*, const void*))
//cmp_int函数实现
int cmp_int(const void* p1, const void* p2)
{
//强制类型转换为int* ,在进行解引用
return (*(int*)p1 - *(int*)p2);//假设升序,则返回>0的数
//至于为什么返回这个数据,参考qsort()函数模仿即可
}
4. 솔루션 3, 다른 데이터 교환을 실현하는 방법
다른 데이터의 경우 두 숫자의 시작 주소를 (char*)로 변환한 다음 두 데이터의 크기를 계산하고 마지막으로 두 숫자를 하나씩 교환할 수 있습니다.
암호
//数据交换我们封装一个Swap()函数
void Swap(char* buf1, char* buf2, int size)//交换arr[i]和arr[i+1]
{
char tmp = 0;
while (size--)
{
tmp = *buf1;
*buf1 = *buf2;
*buf2 = tmp;
buf1++;
buf2++;
}
}
5. 정수를 정렬하고 모든 코드를 구현하는 bubble_sort() 함수를 시뮬레이션합니다.
버블 정렬을 기반으로 정렬이 구현되기 때문에 정렬 트립 횟수와 각 정렬 트립의 로그는 변경되지 않습니다. 위의 문제를 해결하고 관련 코드를 교체하기만 하면 됩니다.
암호
#include <stdio.h>
int cmp_int(const void* p1, const void* p2)
{
return (*(int*)p1 - *(int*)p2);
}
void Swap(char* buf1, char* buf2, int size)//交换arr[i]和arr[i+1]
{
char tmp = 0;
while (size--)
{
tmp = *buf1;
*buf1 = *buf2;
*buf2 = tmp;
buf1++;
buf2++;
}
}
void bubble_sort(void* base, int num, int size, int (*cmp)(const void*, const void*))
{
int i = 0;
//趟数
for (i = 0; i < num; i++)
{
//一趟比较对数
//假设升序
for (int j = 0; j < num - 1 - i; j++)
{
if (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0)//比较两个元素,需要将arr[j]和arr[j+1]的地址传给cmp
{
//交换
Swap((char*)base + j * size, (char*)base + (j + 1) * size, size);
}
}
}
}
//测试bubble_sort排序整型数据
void test1()
{
int arr[] = {
4,2,5,8,3,8,34,23,1,54 };
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr,sz, sizeof(arr[0]), cmp_int);
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
}
int main()
{
test1();
return 0;
}
작업 결과:
6. 구조 정렬 구현
구조를 정렬할 때 Swap()과 bubble_sort()의 구현은 동일하며 다음 int_cmp 함수만 변경하면 됩니다(참고: int_cmp() 함수의 이름은 비교 데이터에 따라 다르며 블로거마다 다름)
암호
#include <stdio.h>
#include <string.h>
void Swap(char* buf1, char* buf2, int size)//交换arr[i]和arr[i+1]
{
char tmp = 0;
while (size--)
{
tmp = *buf1;
*buf1 = *buf2;
*buf2 = tmp;
buf1++;
buf2++;
}
}
void bubble_sort(void* base, int num, int size, int (*cmp)(const void*, const void*))
{
int i = 0;
//趟数
for (i = 0; i < num; i++)
{
//一趟比较对数
//假设升序
for (int j = 0; j < num - 1 - i; j++)
{
//比较两个元素,需要将arr[j]和arr[j+1]的地址传给cmp
if (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0)
{
//交换
Swap((char*)base + j * size, (char*)base + (j + 1) * size, size);
}
}
}
}
//测试bubble_sort排序结构体数据
struct Stu
{
char name[20];
int age;
};
int cmp_stu_by_name(const void* p1, const void* p2)
{
//比较两个字符时,需要借助函数strcmp()来实现
return strcmp(((struct Stu*)p1)->name ,((struct Stu*)p2)->name);
}
void test2()
{
struct Stu arr[] = {
{
"zahngsan",20},{
"lisi",12},{
"wangwu",43} };
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);
}
int main()
{
test2();
return 0;
}
작업 결과:
7. 엔딩
이것으로 이 블로그의 끝입니다. 도움이 된다면 세 배로 기억하세요! 당신의 지원에 감사드립니다! !