C/C++ qsort 함수 구현(버블 정렬)

 홈페이지:

아직 탐색을 기다리는 미지의 요소가 있습니다_데이터 구조, 소규모 프로젝트, C 언어의 어려움-CSDN 블로그

주제 열:

C 언어의 어려움_아직 탐색을 기다리는 알려지지 않은 블로그가 있습니다-CSDN 블로그

목차

I. 소개

2. 구현 설명

1. 정수 배열 정렬 

 정렬 구현

총 코드 

2. qsort에서 매개변수 cmp 함수를 구현하는 방법

1. 부동 소수점 유형

2. 구조 유형 


I. 소개

1. 첫 번째 매개변수는 void*base입니다. 정렬할 배열의 첫 번째 객체에 대한 포인터이며 void*로 변환됩니다.

2. 두 번째 매개변수는 size_t num입니다. 배열에서 기본이 가리키는 요소의 수입니다. size_t는 부호 없는 정수 유형입니다.

3. 세 번째 매개변수는 size_t입니다. size: 배열의 각 요소 크기(바이트)입니다. size_t는 부호 없는 정수 유형입니다.

4. 네 번째 매개변수는 int (*compar)(const void*p1, const void*p2))입니다. 두 요소를 비교하는 함수에 대한 포인터입니다.

버블 정렬이나 선택 정렬을 작성할 때 C 언어 라이브러리 함수의 qsort 함수의 매개 변수가 왜 그렇게 번거로운지 궁금하십니까? size_t size를 전달해야 하는 이유는 무엇입니까? 다들 이런 질문 있으신가요? 오늘은 자세히 설명드리겠습니다! (라이브러리 함수의 qsort 함수는 퀵 정렬인데, 저는 버블 정렬을 이용해서 구현했습니다) 

2. 구현 설명

1. 정수 배열 정렬 

 먼저 사용자 정의 함수의 매개변수를 먼저 디자인해야 하는데, 라이브러리 함수에 qsort 함수를 구현하고 있기 때문에 라이브러리 함수에 매개변수를 직접 작성하면 됩니다.

지금 정렬하려는 것은 정수 배열이므로 정수 배열도 필요합니다.

sz는 배열의 길이를 계산하는 데 사용됩니다.

질문: 사용자 정의 함수의 수신 배열 매개변수 유형이 int* 대신 void*인 이유는 무엇입니까?

답변: void*는 강제 유형 변환 없이 모든 유형의 데이터를 가리킬 수 있는 유형이 지정되지 않은 포인터입니다. 이는 arr 배열을 void*base에 전달하면 base 유형이 int*가 아닌 이유에 관계없이 void* 유형을 범용 유형으로 이해할 수 있음을 의미합니다. (참고: void* 유형의 변수는 역참조를 통해 직접 액세스할 수 없으며 포인터 연산도 수행할 수 없습니다. 위 연산을 수행하려면 강제 유형 변환이 필요합니다.)

#include<stdio.h>
int cmp(void* x, void* y)
{
	return *(int*)x - *(int*)y;
}
//声明自定义排序函数
void qsort_m(void* base, size_t num, size_t size,int (*compar)(const void* p1, const void* p2));
int main()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1 };//提供一个整型数组
	int sz = sizeof(arr) / sizeof(arr[0]);//计算数组的长度
	qsort_m(arr, sz, sizeof(arr[0]), cmp);//自定义排序函数的调用
	int i = 0;
	for (i = 0; i < sz; i++)//输出
		printf("%d ", arr[i]);
	return 0;
}

 정렬 구현

void qsort_m(void* base, size_t num, size_t size, int (*compar)(const void* p1, const void* p2))
{
	int i = 0, j = 0;
	for (int i = 0; i < num - 1; i++)
	{
		for (int j = 0; j < num - 1 - i; j++)
		{
			if (compar(((char*)base + j * size), (char*)base + (j + 1) * size) > 0)
			{
				//交换
				swap((char*)base + j * size, (char*)base + (j + 1) * size,size);
			}
		}
	}
}

compar(((char*)base + j * size), (char*)base + (j + 1) * size), 이 섹션에서는 기본을 char* 유형으로 변환해야 합니다. 목적은 이 char *는 더 많은 것을 나타낼 수 있습니다. 데이터 유형의 경우 char* 역참조는 1바이트의 데이터만 얻을 수 있는 반면 int*와 같은 다른 유형은 역참조 후에 char*보다 큰 더 많은 바이트의 데이터를 얻을 수 있으므로 char* 유형을 사용하면 모든 데이터가 전달되었으므로 이제 데이터 유형의 크기를 전달해야 하는 이유를 이해했습니다. j*size는 배열이 다음 공간의 데이터에 액세스할 수 있도록 허용합니다.

 결국 비교적 간단한 교환 기능이 남게 된다.

void swap(char* buf1, char* buf2, size_t size)
{
	int i = 0;
	for (int i = 0; i < size; i++)
	{
		int tmp;
		tmp = *(buf1 + i);
		*(buf1 + i) = *(buf2 + i);
		*(buf2 + i) = tmp;
	}
}

총 코드 

#include<stdio.h>
int cmp(void* x, void* y)
{
	return *(int*)x - *(int*)y;
}
void swap(char* buf1, char* buf2, size_t size);
void qsort_m(void* base, size_t num, size_t size, int (*compar)(const void* p1, const void* p2));
int main()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1 };//提供一个整型数组
	int sz = sizeof(arr) / sizeof(arr[0]);//计算数组的长度
	qsort_m(arr, sz, sizeof(arr[0]), cmp);//自定义排序函数的调用
	int i = 0;
	for (i = 0; i < sz; i++)//输出
		printf("%d ", arr[i]);
	return 0;
}
void qsort_m(void* base, size_t num, size_t size, int (*compar)(const void* p1, const void* p2))
{
	int i = 0, j = 0;
	for (int i = 0; i < num - 1; i++)
	{
		for (int j = 0; j < num - 1 - i; j++)
		{
			if (compar(((char*)base + j * size), (char*)base + (j + 1) * size) > 0)
			{
				//交换
				swap((char*)base + j * size, (char*)base + (j + 1) * size,size);
			}
		}
	}
}
void swap(char* buf1, char* buf2, size_t size)
{
	int i = 0;
	for (int i = 0; i < size; i++)
	{
		int tmp;
		tmp = *(buf1 + i);
		*(buf1 + i) = *(buf2 + i);
		*(buf2 + i) = tmp;
	}
}

2. qsort에서 매개변수 cmp 함수를 구현하는 방법

        cmp는 함수 포인터입니다. 이 함수 포인터는 함수를 가리킵니다. 이 함수의 반환 값은 int 유형입니다. 반환 값이 <0이면 p1이 가리키는 요소는 p2가 가리키는 요소보다 앞에 있고, 반환 값이 =0이면 p1이 가리키는 요소는 p2가 가리키는 요소와 동일하며, 반환 값 >0이면 p1이 가리키는 요소는 p2가 가리키는 요소 뒤에 있습니다.

더 자세히 알고 싶으시면 링크를 클릭하셔서 제가 이전에 쓴 글을 읽어보시기 바랍니다. 

C 언어의 qsort 기능 사용_아직 알려지지 않은 블로그가 탐색 대기 중입니다-CSDN 블로그

1. 부동 소수점 유형

int cmp(const void* p1, const void* p2)
{
	return *(float*)p1 - *(float*)p2;
}

2. 구조 유형 

typedef struct Stu
{
	char name[20];
	int score;
}Stu;
int cmp(const void* p1, const void* p2)
{
	return ((Stu*)p1)->score - ((Stu*)p2)->score;
}
int main()
{
	Stu s[3] = { { "张三",50 }, { "王五",70 }, { "李四",60 } };
	int sz = sizeof(s) / sizeof(s[0]);
	qsort(s, sz, sizeof(s[0]), cmp);
	for (int i = 0; i < sz; i++)
		printf("%s %d\n", s[i].name,s[i].score);
	return 0;
}

마지막으로, 귀하의 지원에 감사드립니다!

추천

출처blog.csdn.net/qq_73435980/article/details/133203433