버블 정렬 시뮬레이션은 qsort() 함수를 구현합니다.

머리말

qsort() 함수를 시뮬레이션하려면 먼저 qsort() 함수의 특성을 알아야 합니다.

  1. 빠른 정렬 방법을 사용하십시오.
  2. 모든 데이터 유형에 대한 정렬.

그러나 일부 학자들은 아직 퀵 정렬 알고리즘을 배우지 않았기 때문에 이 블로그에서는 버블 정렬을 사용하여 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() 함수는 버블 정렬에 의해 시뮬레이션되기 때문에 위의 코드를 기반으로 사용할 수 있으며 시뮬레이션 구현을 변경해야 합니다. 그러나 몇 가지 문제가 있습니다! !

  1. 정수뿐만 아니라 다양한 데이터 유형을 받아들이는 방법.
  2. 예를 들어 서로 다른 데이터의 경우 구조를 > 또는 <로 간단히 비교할 수 없습니다. 그렇다면 이를 달성하는 방법은 무엇입니까?
  3. 다른 데이터 유형의 경우 교환이 약간 다릅니다.

2. 솔루션 1, 다른 데이터를 받아들이는 방법

void*는 모든 유형의 데이터를 가리킬 수 있는 C 언어의 일반 포인터 유형입니다. 그래서 매개변수 base를 void* 유형 포인터로 정의하여 다른 데이터를 허용할 수 있습니다.

void* 사용 확장:

  1. 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. 엔딩

이것으로 이 블로그의 끝입니다. 도움이 된다면 세 배로 기억하세요! 당신의 지원에 감사드립니다! !

Supongo que te gusta

Origin blog.csdn.net/Zhenyu_Coder/article/details/131716197
Recomendado
Clasificación