C语言库函数qsort的使用及模拟实现

 更新时间:2022年08月18日 15:44:51   作者:敲代码の流川枫  
这篇文章主要介绍了C语言库函数qsort的使用及模拟实现,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下

1.qsort函数的介绍

 函数定义:

函数参数 :

void* base

待排序的数据的起始位置

size_t num

待排序的数据元素的个数

size_t width

待排序的数据元素的大小,以字节为单位

int (*compar)(const void*,const void*)

是一个函数指针,函数功能是比较

因该排序算法要排序的数据的类型是不同的,比较方法也是有差异的,因此要给使用者提供一个自定义一个比较函数

2.qsort实现不同类型数据排序

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int cmp_int(const void* e1, const void* e2)
{
	return (*(int*)e1 - *(int*)e2);
}
void test1()
{
 
	int arr[] = {9,8,7,6,5,4,3,2,1,0};
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), cmp_int);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}
struct Stu
{
	char name[20];
	int age;
};
 
int cmp_stu_by_name(const void* e1, const* e2)
{
	return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
}
 
void test2()
{
	struct Stu s[] = { {"zhangsan",20},{"lisi",21},"wangwu",19};
	int sz = sizeof(s) / sizeof(s[0]);
	qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		printf("%s %d ", s[i].name, s[i].age);
	}
}
int main()
{
	test1();
    prinf("\n");
	test2();
	return 0;
}

 test1和test2两个函数分别对int类型数据和结构体类型数据进行排序,这里void*值得一提

void*指针的作用:

int main()
{
	int a = 10;
	char* pa = &a;
	return 0;
}

如警告所说,他们的类型是不兼容的,但如果用void*定义一个指针变量来接收int*数据就不会有警告,这说明void*指针是无具体类型的指针,可以接受任意类型的地址,是泛型的,也正因为它没有具体的类型,它不能解引用,也不能加减操作,想要对它解引用,只需要对地址强制类型转换即可,qsort的函数参数使用void*类型也是因为不知道使用者具体会传什么类型的数据的地址,用void*可以接收任意类型的地址,提高了qsort函数的实用性

3.qsort的模拟实现

分析:

参考qsort函数的参数我们知道:在设计函数的时候我们是不知道使用者要传什么类型的数据,因此会使用到void*型的指针来记录排序数据的起始位置,最后提供的一个比较函数也会用到void*;知道了元素个数和元素宽度,就能一一找到这些数据

如上图所示, base被强制类型转换为char*型指针后一次可以访问一个字节,如果转换为int *后一次跳过4个字节就太多了,转换为char*后结合width相当于通过起始位置加上偏移量的方法来比较,比较后通过Swap函数进行交换,达到排序的目的

 模拟实现:

//交换
void Swap(char* buf1, char* buf2, int width)
{
	int i = 0;
	for (i = 0; i < width; i++)
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}
void bubble_sort(void* base, int sz, int width, int(*cmp)(const void* e1, const void* e2))
{
	int i = 0;
	for (i = 0; i < sz - 1; i++)
	{
        //一趟排序
		int flag = 1;
		int j = 0;
		for (j = 0; j < sz - 1; j++)
		{
			if (cmp((char*)base + j * width, (char*)base + (j + 1) * width)>0)
			{
				Swap((char*)base + j * width, (char*)base + (j + 1) * width,width);
				flag = 0;
			}
		}
		if (flag == 1)
			break;
	}
}
int cmp_int(const void* e1, const void* e2)
{
	return (*(int*)e1 - *(int*)e2);
}
void test1()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), cmp_int);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}
struct Stu
{
	char name[20];
	int age;
};

int cmp_stu_by_name(const void* e1, const* e2)
{
	return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
}

void test2()
{
	struct Stu s[] = { {"zhangsan",20},{"lisi",21},"wangwu",19};
	int sz = sizeof(s) / sizeof(s[0]);
	 bubble_sort(s, sz, sizeof(s[0]), cmp_stu_by_name);
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		printf("%s %d ", s[i].name, s[i].age);
	}
}
int main()
{

	test1();
	printf("\n");
	test2();

	return 0;
}

到此这篇关于C语言库函数qsort的使用及模拟实现的文章就介绍到这了,更多相关C语言 qsort函数内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 巧妙使用RAII中的ScopeExit

    巧妙使用RAII中的ScopeExit

    Resource Acquisition Is Initialization,资源获取即初始化,将资源的生命周期与一个对象的生命周期绑定,这篇文章主要介绍了巧妙使用RAII中的ScopeExit,需要的朋友可以参考下
    2021-05-05
  • C++ QgraphicsScene类案例详解

    C++ QgraphicsScene类案例详解

    这篇文章主要介绍了C++ QgraphicsScene类案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • C++构造函数的初始化列表详解

    C++构造函数的初始化列表详解

    这篇文章主要为大家介绍了C++构造函数的初始化列表,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2021-12-12
  • C++中静态存储区与栈以及堆的区别详解

    C++中静态存储区与栈以及堆的区别详解

    本篇文章是对C++中静态存储区与栈以及堆的区别进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • 浅谈C/C++中指针和数组的不同

    浅谈C/C++中指针和数组的不同

    本文主要解析了C/C++中数组和指针的区别,文章简单易懂,对各位的工作学习有所帮助,有需求的朋友可以了解下
    2020-05-05
  • C语言实现职工工资管理系统的示例代码

    C语言实现职工工资管理系统的示例代码

    这篇文章主要为大家详细介绍了C语言如何实现职工工资管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08
  • C语言中continue的用法详解

    C语言中continue的用法详解

    在C语言当中的continue和break语句是有一些类似的,但是它并不是强制进行终止的,下面这篇文章主要给大家介绍了关于C语言中continue用法的相关资料,需要的朋友可以参考下
    2022-11-11
  • C++栈(stack)的模板类实现代码

    C++栈(stack)的模板类实现代码

    这篇文章主要为大家详细介绍了C++栈(stack)的模板类实现代码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-06-06
  • C++ 利用硬件加速矩阵乘法的实现

    C++ 利用硬件加速矩阵乘法的实现

    这篇文章主要介绍了C++ 利用硬件加速矩阵乘法的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • C++设计模式之模板方法模式

    C++设计模式之模板方法模式

    这篇文章主要介绍了C++设计模式之模板方法模式,本文讲解了什么是模板方法模式、模板方法模式的UML类图、模板方法模式的使用场合等内容,需要的朋友可以参考下
    2014-10-10

最新评论