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()的使用与模拟实现

目录

?C 库函数-?qsort()概念

?一个冒泡排序

? ? ? ? ??利用qsort解决

? ? ? ? ? ·void*?指针

??????????qsort 实现

利用qsort结构体排序

???名字的排序

??年龄的排序

?模拟实现qsort

?模拟qsort对数组的排序

????????解析

主函数

?比较函数

?交换函数

?基于冒泡排序的思想实现qsort的函数

?排序结构体数据

?结果

??结束语


C 库函数<stdlib.h>-?qsort()概念

qsort - 这个函数可以判刑任意类型的数据

为了防止歧义,这里引用了官方解释,下面我会详解

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

1.void* base //要排序的数据的起始位置

2.size_t num //待排序的数据元素的个数

3.size_t size? //待排序的数据元素的大小(单位是字节)

4.int (*compar)(const void*,const void*) //函数指针-一个比较函数

一个冒泡排序

//一个冒泡排序
void bubble_sort(int *arr, int sz)
{
	int i = 0;
	//趟数
	for ( i = 0; i < sz-1; i++)
	{
		int flag = 1;
		//交换
		int j = 0;
		for ( j = 0; j < sz-1-i; j++)
		{
			if (*(arr+j)>*(arr+j+1))
			{
				int tmp = *(arr + j);
				*(arr + j) = *(arr + j + 1);
				*(arr + j + 1) = tmp;
				flag = 0;
			}
		}
		if (flag)
		{
			break;
		}
	}
}

int main() {
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	//升序排序
	int sz = sizeof(arr) / sizeof(arr[0]);

	bubble_sort(arr, sz);


	int i = 0;
	for ( i = 0; i < sz; i++)
	{
		printf("%d ",arr[i]);
	}


	return 0;
}

利用qsort解决

void*?指针

在开始代码的时候我们先要了解?void*?指针的类型

//void* 的作用

int main()
{
	int a = 10;
	char* pa = &a;		//warning C4133: “初始化”: 从“int *”到“char *”的类型不兼容
						//类型不兼容是会报警告的
	//void* pv = &a;    //这样子就不会有问题了
}

通常我们使用指针的时候都是一一对应,什么类型的数据地址就应该用什么类型的指针来接收,但有的情况下我们并不知道我们所接收的数据的类型是什么,因此便有了?void*?指针,这个类型的指针可以接收任意类型数据的地址,以来存储使用

?qsort 实现

?--使用的时候记得引入头文件 <stdlib.h>

?#include<stdlib.h>
#include<stdio.h>
int cmp_int(const void*e1, const void*e2) 
{
	return ( *(int*)e1 - *(int*)e2 );	//直接返回数据就行了
            //这是升序排序,当我们想要降序判刑只要交换e1、e2的位置就行了,逻辑交换的道理
}

int main() {
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	//升序排序
	int sz = sizeof(arr) / sizeof(arr[0]);

	//bubble_sort(arr, sz);

	qsort(arr, sz, sizeof(arr[0]), cmp_int);

	int i = 0;
	for ( i = 0; i < sz; i++)
	{
		printf("%d ",arr[i]);
	}

	return 0;
}

?

//需要注意的是传过去的函数的规定
int compareMyType(const void* a, const void* b)
{
?? ??? ?if (*(MyType*)a < *(MyType*)b) return -1;?? ?//返回一个小于0的数
?? ??? ?if (*(MyType*)a == *(MyType*)b) return 0;?? //返回0
?? ??? ?if (*(MyType*)a > *(MyType*)b) return 1;?? ?//返回一个大于0的数
}

//还要注意的是要强制类型

结果和冒泡排序的效果是一样的?

利用qsort结构体排序

?名字的排序

#include<stdlib.h>
#include<stdio.h>
#include<string.h>

struct Stu
{
	char name[20];
	int age;
};

cmp_stu_by_name(const void* e1, const void* e2)
{
	return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
    //同样的需要强制转化类型成我们创立的结构体类型 (struct Stu*)
}

void test()
{
	//qsort来排序结构体数据
	struct Stu s[] = {{"zhangsan",15}, {"lisi",30}, {"wangwu",25}};  //创立一个结构体数据
	int sz = sizeof(s) / sizeof(s[0]);
	qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);    
}

int main() {

	test();

	return 0;
}

?

年龄的排序

#include<stdlib.h>
#include<stdio.h>
#include<string.h>

struct Stu
{
	char name[20];
	int age;
};

//按名字字母排序
cmp_stu_by_name(const void* e1, const void* e2)
{
	return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
}

//按年龄的升序排序
cmp_stu_by_age(const void* e1, const void* e2)
{
	return  ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}

void test()
{
	//qsort来排序结构体数据
	struct Stu s[] = {{"zhangsan",15}, {"lisi",30}, {"wangwu",25}};
	int sz = sizeof(s) / sizeof(s[0]);
	//qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);
	qsort(s, sz, sizeof(s[0]), cmp_stu_by_age);
}

int main() {

	test();

	return 0;
}

?一样的配方,一样的味道

模拟实现qsort

模拟qsort对数组的排序全代码

//模拟qsort对数组的排序
#include<stdio.h>

int cmp_int(const void* e1, const void* e2)
{
	return (*(int*)e1 - *(int*)e2);	//直接返回
			//这是升序排序,当我们想要降序判刑只要交换e1、e2的位置就行了,逻辑交换
}

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++;
	}
}

//基于冒泡排序的思想实现qsort
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 - 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);
				flag = 0;
			}
		}
		if (flag)
		{
			break;
		}
	}
}

int main() {
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	//升序排序
	int sz = sizeof(arr) / sizeof(arr[0]);

	//冒泡排序模拟qsort
	bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);

	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	return 0;
}

解析

主函数

int main() {
?? ?int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
?? ?//升序排序
?? ?int sz = sizeof(arr) / sizeof(arr[0]);

?? ?//冒泡排序模拟qsort
?? ?bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);? //这里毋庸置疑是把数组首元素的地址、

?? ?int i = 0;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//元素个数元素字节大小和一个比较函数的地址
?? ?for (i = 0; i < sz; i++)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //传给了我们自定义的函数bubble_sort
?? ?{
?? ??? ?printf("%d ", arr[i]);
?? ?}
?? ?printf("\n");
?? ?return 0;
}?

比较函数

int cmp_int(const void* e1, const void* e2)
{
	return (*(int*)e1 - *(int*)e2);	//直接返回
							//这是升序排序,当我们想要降序判刑只要交换e1、e2的位置就行了,逻辑交换
}

交换函数

void Swap(char* buf1, char* buf2, int width)? ?//接收数据的宽度,这样在下面的循环中就可以
{? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//保证正常循环不溢出
?? ?int i = 0;
?? ?for (i = 0; i < width; i++)?//需要注意的是这里是字节的交换哦,全部字节交换也就是数据交换
?? ?{ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??????//在一开始我们是默认不知道传过来的数据是什么类型的
?? ??? ?char tmp = *buf1;? ?//因此我们使用char类型开始,这样什么类型的开始都可以向后找到
?? ??? ?*buf1 = *buf2;? ? ? ??
?? ??? ?*buf2 = tmp;
?? ??? ?*buf1++;
?? ??? ?*buf2++;
?? ?}
}?

基于冒泡排序的思想实现qsort的函数

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 - i; j++)
?? ??? ?{
?? ??? ??? ?if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
?? ??? ??? ?{? ? ? //这里将它转为为chaf*类型的指针,再加上元素位置乘以一个宽度,这样就可以
?? ??? ??? ??? ?//交换? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //找到对应的元素了
?? ??? ??? ??? ?Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
?? ??? ??? ??? ?flag = 0;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //这里记得把宽度传过去,便于后面交换
?? ??? ??? ?}
?? ??? ?}
?? ??? ?if (flag)
?? ??? ?{
?? ??? ??? ?break;
?? ??? ?}
?? ?}
}?

排序结构体数据

?
#include<stdio.h>
#include<string.h>

 struct Stu
{
	char name[20];
	int age;
};


int cmp_int(const void*e1, const void*e2) 
{
	return ( *(int*)e1 - *(int*)e2 );	//直接返回
							//这是升序排序,当我们想要降序判刑只要交换e1、e2的位置就行了,逻辑交换
}


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

cmp_stu_by_age(const void* e1, const void* e2)
{
	return  ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}

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++;
	}
}


//基于冒泡排序的思想实现qsort
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-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);
				flag = 0;
			}
		}
		if (flag)
		{
			break;
		}
	}
}

void test()
{
	//qsort来排序结构体数据
	struct Stu s[] = { {"zhangsan",15}, {"lisi",30}, {"wangwu",25} };
	int sz = sizeof(s) / sizeof(s[0]);
	bubble_sort(s, sz, sizeof(s[0]), cmp_stu_by_age);//如果按名字排序,改函数名字就可以了
}                                                    //cmp_stu_by_name

int main() {

	//结构体排序
	test();

	return 0;
}

?

结果

按年龄

?按姓名

?结束语

? ? ? ? ????????????????????????四年

四年很快啊,暮然之际已经过去一年了,我进入学习编程也已经一个学期半年时光了,用这个记录自己学习的时光,以后就可以回顾这些记忆了……

未完持续更新中……?

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-07-04 23:13:18  更:2022-07-04 23:13:54 
 
开发: 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/25 23:30:41-

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