• C语言——qsort()函数_学习笔记


    一、qsort()介绍

    在这里插入图片描述
    在这里插入图片描述

    qsort()函数是一个库函数,包含在头文件 中,用来对数据进行排序操作的函数,它可以排序任意类型的数据!!!

    二、参数详解

    qsort()函数排序是从小到大排序,内部是采用快速排序思想排序数据的。qsort()函数有四个参数,解释如下:

    void qsort(void* base, //base指向待排序的第一个元素
               size_t num,  //待排序的元素个数
               size_t size, //待排序的数组元素的大小,单位是字节
               int (*compar)(const void*, const void*) //compar是一个函数指针,指向的函数能够比较2个元素
                );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1. 第一个参数 void* base 。类型是 void* 类型的,填入待排序的第一个元素的地址,比如:要排序数组就填数组名(这里直接填数组名表示首元素的地址),要排序结构体填结构体的名字…
    2. 第二个参数 size_t num。类型是size_t类型的(即无符号整形),填入的是待排序的元素个数,比如:要排序一个数组a,可以用 sizeof(a)/sizeof(a[0]) 计算要排序的元素个数。
    3. 第三个参数 size_t size 。类型也是size_t类型的(即无符号整形),填入的是待排序的数组或结构体单个元素的大小,单位是字节。比如:要排序一个数组a ,可以用 sizeof(a[0])计算得出结果。
    4. 第四个参数 int (* compar)(const void*, const void*) 。是一个函数指针类型,指向的函数的返回值类型是int,指向的函数的参数有两个,类型都是 const void * 类型的,这个是qsort 函数的可以排序任意数据的关键。要自己构建一个比较的函数,把自己构建好的函数的函数名当作参数传进来就好,但是构建的函数要符合前文提到的几个要求:
      ①返回值要是int类型的
      ②有两个参数,参数类型都是const void * 类型的
      ③函数返回的值有三种情况(大于0返回大于0的数或返回1,等于0返回0,小于0返回小于0的数或返回-1),如下
      在这里插入图片描述

    三、qsort()函数应用举例

    3.1 排序数组类型的数据

    代码如下:

    
    #include 
    #include 
    
    void Print(int a[], int sz)
    {
    	int i = 0;
    	for (i = 0; i < sz; i++)
    	{
    		printf("%d ", a[i]);
    	}
    	printf("\n");
    }
    
    int Cmp(const void* x, const void* y)
    {
    	return *((int*)x) - *((int*)y);
    }
    
    int main()
    {
    	int a[] = {2,5,3,1,6,7,9,8,0,4};
    	int sz = sizeof(a) / sizeof(a[0]);
    	printf("排序前:");
    	Print(a, sz);
    	qsort(a, sz, sizeof(a[0]), Cmp);
    	printf("排序后:");
    	Print(a, sz);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    运行结果如下:
    在这里插入图片描述

    3.2 排序结构体类型的数据

    代码如下:

    #include 
    #include 
    #include 
    
    struct Stu
    {
    	char name[10];
    	int height;
    };
    
    int ComparByHeight(const void* e1, const void* e2)
    {
    
    	return *(int*)e1 - *(int*)e2;
    }
    
    int ComparByName(const void* e1, const void* e2)
    {
    
    	return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
    }
    
    
    void Print(struct Stu s[], int sz)
    {
    	int i = 0;
    	for (i = 0; i < sz; i++)
    	{
    		printf("%s ", s[i].name);
    		printf("%d ", s[i].height);
    		printf("\n");
    	}
    }
    
    int main()
    {
    	struct Stu s[] = { {"qiu",160},{"li",180},{"ban",176},{"xiao",165} };
    	int sz = sizeof(s) / sizeof(s[0]);
    	printf("排序前:\n");
    	Print(s, sz);
    	printf("按身高排序后:\n");
    	qsort(s, sz, sizeof(s[0]), ComparByHeight);
    	Print(s, sz);
    	printf("按姓氏排序后:\n");
    	qsort(s, sz, sizeof(s[0]), ComparByName);
    	Print(s, sz);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    运行结果如下:
    在这里插入图片描述

    四、模拟实现qsort()函数

    用冒泡排序的思想模拟实现qsort()函数

    4.1 冒泡排序简单介绍

    这里简单介绍一下冒泡排序,冒泡排序和前文中提到的快速排序一样,是一种排序算法。冒泡排序的核心思想就是,相邻元素之间两两进行比较。

    如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行,直到没有相邻元素需要交换,也就是说该元素列已经排序完成。

    这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”

    4.2 实现bubble_sort()函数

    bubble_sort()函数的实现,参数部分的设置可以模仿qsort函数,设置四个参数。只不过是把内部排序的方法改为冒泡排序。

    代码如下:

    #include 
    
    
    //模拟实现qsort()
    
    //实现两个元素的交换的函数,冒泡排序的核心
    void swap(char* x, char* y, size_t byte)
    {
    	int i = 0;
    	for (i = 0; i < byte; i++)
    	{
    		char temp = *x;
    		*x = *y;
    		*y = temp;
    		x++;
    		y++;
    	}
    }
    
    void bubble_sort(void* base, //base指向待排序的第一个元素
    				 size_t sz,  //待排序的元素个数
    				 size_t size, //待排序的数组元素的大小,单位是字节
    				 int (*compar)(const void*, const void*))//函数指针,用户自己构造比较方法,后面当参数使用
    {
    	int i = 0;
    	for (i = 0; i < sz - 1; i++)//确定冒泡排序的趟数
    	{
    		int j = 0;
    		for (j = 0; j < sz - 1 - i; j++)//一趟冒泡排序
    		{
    			if ((compar(((char*)base + j * size), ((char*)base + (j + 1) * size))) > 0)//若相邻两元素比较结构大于0 ,则两个元素交换位置
    			{
    				swap(((char*)base + j * size), ((char*)base + (j + 1) * size), size);//两个元素的交换
    			}
    		}
    	}
    }
    
    //定义结构体
     struct Stu
    {
    	char name[10];
    	int height;
    };
     
    //编辑比较方法函数
    int ComparByHeight(const void* e1, const void* e2)
    {
    
    	return *(int*)e1 - *(int*)e2;
    }
    
    int ComparByName(const void* e1, const void* e2)
    {
    
    	return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
    }
    
    //编辑打印结构体的函数
     void Print(struct Stu s[], int sz)
    {
    	int i = 0;
    	for (i = 0; i < sz; i++)
    	{
    		printf("%s ", s[i].name);
    		printf("%d ", s[i].height);
    		printf("\n");
    	}
    }
    
    int main()
    {
    	struct Stu s[] = { {"qiu",160},{"li",180},{"ban",176},{"xiao",165} };
    	int sz = sizeof(s) / sizeof(s[0]);
    	printf("排序前:\n");
    	Print(s, sz);
    	printf("按身高排序后:\n");
    	bubble_sort(s, sz, sizeof(s[0]), ComparByHeight);
    	Print(s, sz);
    	printf("按姓氏排序后:\n");
    	bubble_sort(s, sz, sizeof(s[0]), ComparByName);
    	Print(s, sz);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84

    运行结果如下:
    在这里插入图片描述

  • 相关阅读:
    一文了解JVM(中)
    uview的安装和功能
    JAVA面试八股文之JVM
    视觉大模型调研(Survey of Visual Foundation Model)
    math 库中常用的数学运算和常量【GO 基础】
    Redisson的看门狗watchDog机制是怎么实现的?
    基于Android的仓库管理系统APP设计与实现
    中国汽车供应商远赴德国,中国智驾方案能否远渡重洋?
    Spring Data JPA与Mybatis的对比
    AI学习指南机器学习篇-随机森林原理
  • 原文地址:https://blog.csdn.net/yjagks/article/details/132692552