IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 轻松模拟实现qsort函数 -> 正文阅读

[C++知识库]轻松模拟实现qsort函数

qsort函数简单介绍

qsort函数C语言编译器函数库自带的排序函数。

是base所指数组进行排序。qsort函数包含在C 标准库 - <stdlib.h>中。

函数声明

void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*))

参数

  • base-- 指向要排序的数组的第一个元素的指针。

  • nitems-- 由 base 指向的数组中元素的个数。

  • size-- 数组中每个元素的大小,以字节为单位。

  • compar-- 用来比较两个元素的函数,即函数指针(回调函数)

回调函数:

回调函数就是一个通过函数指针调用的函数。如果把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,就说这是回调函数。

compar参数

compar参数指向一个比较两个元素的函数。比较函数的原型应该像下面这样。注意两个形参必须是const void *型,同时在调用compar 函数(compar实质为函数指针,这里称它所指向的函数也为compar)时,传入的实参也必须转换成const void *型。在compar函数内部会将const void *型转换成实际类型。

int compar(const void *p1, const void *p2);

如果compar返回值小于0(< 0),那么p1所指向元素会被排在p2所指向元素的左面;

如果compar返回值等于0(= 0),那么p1所指向元素与p2所指向元素的顺序不确定;

如果compar返回值大于0(> 0),那么p1所指向元素会被排在p2所指向元素的右面。

?模拟实现qsort函数

?这里我们用排int型举个简单例子

话不多说,直接上代码:

struct Stu
{
	char name[20];
	int age;
};
//比较两个int型变量大小
int cmp_int(const void*p1,const void*p2)
{
	return *(int*)p1- *(int*)p2;
}
//比较名字
int cmp_by_name(const void*e1, const void*e2)
{
	return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
}
//比较年龄
int cmp_by_age(const void* e1, const void* e2)
{
	return ((struct Stu*)e1)->age -((struct Stu*)e2)->age;
}
//进行交换
//这里为了对不同类型变量进行交换,我们用width变量来确定变量类型,以便更好交换
void Swap(char*p1, char* p2, size_t width)
{
	char tmp;
	int i = 0;
//这里我们逐字节交换
	for (i = 0; i < width; i++)
	{
		tmp = *p1;
		*p1 = *p2;
		*p2 = tmp;
		p1++;
		p2++;
	}
}
//模拟qsort函数
void BubbleSort(void*base,size_t num,size_t width,int (*cmp)(const void*p1,const void*p2))
{
	int i, j;
	for (i = 0; i < num; i++)
	{
		for (j = 0; j < num-1-i; j++)
		{
			if (cmp((char*)base + j * width, (char*)base + (j+1) * width)>0)

			{
				Swap( (char*)base + j * width, (char*)base + (j+1) * width, width );
			}
		}
    }
}
//测试自定义的BubbleSort() 
void test1()
{
	int arr[] = { 1,3,5,7,4,2,6,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	BubbleSort(arr,sz,sizeof(arr[0]),cmp_int);
	for(int i=0;i<sz;i++)
	{
		printf("%d ", arr[i]);
	}
}

void test2()
{
	struct Stu s[3] = { {"zhangsan", 15}, {"lisi", 30},{"wangwu", 10} };
	int sz = sizeof(s) / sizeof(s[0]);
//	按照名字排序
BubbleSort(s, sz, sizeof(s[0]), cmp_by_name);
//	按照年龄来排序
BubbleSort(s, sz, sizeof(s[0]), cmp_by_age);
}
int main()
{
	test1();
    test2();
	return 0;
}

那为什么需要进行逐字节交换呢?又为什么先强转char*呢?

? 因为不同的数据交换时所需要交换的字节数目不同,为了能够满足不同类型数据交换的要求,我们将每一种类型的数据都强转char*,再将所有数据逐字节交换.

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-06 10:59:24  更:2021-09-06 11:00:17 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 12:17:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码