比较器-各个数据结构的应用(c语言中的qsort函数)

 qsort()函数实现的是c语言库的快排功能,由于额外空间的处理,相比自己写的更为优化。
注释:自己写的快排由于额外空间冗余,实际运行时会出现超出限制的报错。

一、 一维

qsort调用所包含的头文件 & 函数原型:

#include <stdlib.h> 

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*)是需要使用者去完成的一个比较函数,即比较器。

比较函数的返回值:

return valuemeaning
<0The element pointed to by p1 goes before the element pointed to by p2
0The element pointed to by p1 is equivalent to the element pointed to by p2
>0The element pointed to by p1 goes after the element pointed to by p2

1.qsort函数实现int型排序

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

2.对 char 类型的数组排序

int char_cmp(const void* str1, const void* str2){
	return (char)str1 - (char)str2;
}

3.对 double 类型数组排序(需要特别注意)

int double_cmp(const void* arr1, const void* arr2){
	return (double)arr1 > (double)arr2 ? 1 : -1;
	//注意这里是用比较大小的方法,来返回正负
}

4.对结构体一级排序

1 #include<stdio.h>
 2 #include<stdlib.h>
 3 
 4 typedef struct Student
 5 {
 6     int x;
 7     int y;
 8     //按照x从小到大排序,当x相等时按照y从大到小排序
 9 }Student;
10 
11 Student student[7];
12 
13 int cmp(const void *a, const void *b)
14 {
15     Student* pa1 = (Student*)a;
16     Student* pa2 = (Student*)b;
17 
18     return (pa1->x) > (pa2->x) ? 1 : -1;
19 }
20 
21 //展示一下对于结构体里赋值的后的结果
22 void Display()
23 {
24     for (int i = 0; i < 7; ++i)
25     {
26         printf("%d\n",student[i].x);
27     }
28 }
29 
30 int main()
31 {
32     int arr[7] = { 1,3,5,2,6,9,7 };
33     for (int i = 0; i < 7; ++i)
34     {
35         //将数组arr中的元素赋值给结构体x中
36         student[i].x = arr[i];
37     }
38     Display();
39     qsort(student, 7, sizeof(Student), cmp);
40     for (int i = 0; i < 7; ++i)
41     {
42         printf("%d", student[i].x);
43     }
44 
45     return 0;
46 }

5.对机构体二级的排序
就对于4中的结构体来说,如果给x赋值,则x中的值都为0,那么就需要来比较y中的数组。

则可以将代码改为下面这样:

1 #include<stdio.h>
 2 #include<stdlib.h>
 3 
 4 typedef struct Student
 5 {
 6     int x;
 7     int y;
 8     //按照x从小到大排序,当x相等时按照y从大到小排序
 9 }Student;
10 
11 Student student[7];
12 
13 int cmp(const void *a, const void *b)
14 {
15     Student* pa1 = (Student*)a;
16     Student* pa2 = (Student*)b;
17 
18     if (pa1->x != pa2->x)
19     {
20         return (pa1->x) > (pa2->x) ? 1 : -1;
21     }
22     else
23     {
24         return (pa1->y) > (pa2->y) ? 1 : -1;
25     }
26 }
27 
28 //展示一下对于结构体里赋值的后的结果
29 void Display()
30 {
31     printf("x=");
32     for (int i = 0; i < 7; ++i)
33     {
34         printf("%d", student[i].x);
35     }
36     printf("\n");
37     printf("y=");
38     for (int i = 0; i < 7; ++i)
39     {
40         printf("%d", student[i].y);
41     }
42     printf("\n");
43 }
44 
45 int main()
46 {
47     int arr[7] = { 1,3,5,2,6,9,7 };
48     for (int i = 0; i < 7; ++i)
49     {
50         //将数组arr中的元素赋值给结构体x中
51         student[i].y = arr[i];
52     }
53     Display();
54     printf("排序结构体中的y:\n");
55     qsort(student, 7, sizeof(Student), cmp);
56     for (int i = 0; i < 7; ++i)
57     {
58         printf("%d", student[i].y);
59     }
60 
61     return 0;
62 }

6.模仿qsort的功能实现一个通用的冒泡排序

 1 //用回调函数模拟实现qsort(冒泡排序的方式)
 2 
 3 #include <stdio.h>
 4 
 5 int int_cmp(const void * p1, const void * p2) 
 6 { 
 7     return (*(int *)p1 > *(int *)p2); 
 8 }
 9 
10 void _swap(void *p1, void * p2, int size) 
11 { 
12     int i = 0;
13     for (i = 0; i < size; i++) 
14     { 
15         char tmp = *((char *)p1 + i);
16         *((char *)p1 + i) = *((char *)p2 + i);
17         *((char *)p2 + i) = tmp; 
18     } 
19 }
20 
21 void bubble(void *base, int count, int size, int(*cmp)(void *, void *)) 
22 { 
23     int i = 0;
24     int j = 0;
25     for (i = 0; i < count - 1; i++) 
26     { 
27         for (j = 0; j < count - i - 1; j++) 
28         { 
29             if (cmp((char *)base + j * size, (char *)base + (j + 1)*size) > 0) 
30             { 
31                 _swap((char *)base + j * size, (char *)base + (j + 1)*size, size); 
32             } 
33         } 
34     } 
35 } 
36 int main() {
37     int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };
38     //char *arr[] = {"aaaa","dddd","cccc","bbbb"};    
39     int i = 0;
40     bubble(arr, sizeof(arr) / sizeof(arr[0]), sizeof (int), int_cmp);
41     for (i = 0; i< sizeof(arr) / sizeof(arr[0]); i++)
42     {
43         printf( "%d ", arr[i]);
44     }
45     printf("\n");
46     return 0; 
47 }

二、多维

对于malloc动态申请的多维数组(指针数组)

以一个例子解析:
要求——
打算操作一个数组,数组的每个元素是一个指针,指向2个元素的数组。元素的大小关系为先比较第一个元素,第一个元素相同比较第二个元素。

  1. 首先,通过malloc对指针数组进行分配:
    先分配一个指向元素为int *的一维数组,所以数组类型为int **
  2. 然后,针对每一个数组里的int *型指针,分配一个一维数组,数组类型为int。
int *b,**a;
    a = (int**)malloc(500000*sizeof(int*)); //这里是对int*来分配。
    for(i=0;i<500000;i++)
    {
        b = malloc(2*sizeof(int));
        a[i] = b;
    }
   

//这样申请的数组,不是直接free(a),而是如下释放方式:
for(i=0;i<n;i++) { 	//因为malloc和free要一一对应
	free(a[i]); 
} 

排序用法:

qsort(a, n, sizeof(a[0]), cmp);

qsort的cmp的写法:
入参实际是数组元素的指针,这里元素是int*,所以入参应该是int**,而要比较的数组是这个指针指向的内容

void* a强制转型为本来的样子int **,然后ap指针指向a的第一个元素(这个元素也是指针,指向一个int型一维数组);

int cmp(const void *a,const void *b)
{
    int *ap = *(int **)a;       
    int *bp = *(int **)b;

    if(ap[0] == bp[0])
        return ap[1] - bp[1];
    else
        return ap[0] - bp[0];
} 

对于非malloc申请的多维数组

比如:二维数组 int a[5][2];
要求:按照二维数组每一维的第一个元素排序。
比较算法cmp:

int cmp(const void *a, const void *b)
{
    return ((int *)a)[0] - ((int *)b)[0];
}

结构体

结构体排序相对简单。
例如——
结构体的结构:

typedef struct node{
    int x;              
    int y;              
    int z;              
}Node;

比较算法cmp,切记强制转型不如 ->优先级高

int cmp(const void *a, const void *b)
{
//    return (Node *)a->x - (Node *)b->x;   //错误写法!
//    return ((Node *)a)->x - ((Node *)b)->x;   //正确写法1
    return (*(Node *)a).x - (*(Node *)b).x;     //正确写法2
}

参考

qsort对多维数组和结构体的排序
qsort函数排序各种类型的数据。

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值