排序规则的原理
C 语言提供的快速排序算法,内部包含4个参数,第一个参数是要排序数组的地址,第二个参数是数字的长度,第三个参数是数组元素的大小,第四个参数是回到函数:用来定义快速排序的规则。
在快速排序或任何其他比较排序算法中,比较函数决定了排序的方向。在你给出的代码片段中,val
变量的赋值实际上定义了元素*a
和*b
之间的相对大小,从而影响了排序结果。
当*a > *b
时,val
被设为1
;当*a < *b
时,val
被设为-1
;当两者相等时,val
被设为0
。
在qsort()
函数的上下文中,排序算法会基于val
的值来决定如何交换元素。具体来说:
- 当
val
为1
时(即*a > *b
),这表示a
应该排在b
之后,以保持升序排列。如果a
在b
之前,qsort()
会将它们交换,使b
在前,a
在后。 - 当
val
为-1
时(即*a < *b
),这表示a
应该排在b
之前,以保持升序排列。如果a
已经在b
之前,那么不需要交换。 - 当
val
为0
时(即*a == *b
),意味着两个元素相等,无论它们的位置如何都不会改变排序状态。
因此,当qsort()
使用这个比较函数时,它会根据val
的值来调整元素位置,确保最终的结果是按升序排列的。这是因为qsort()
在递归过程中会将较大的元素推到数组的右边,较小的元素推到左边,而等于的元素则维持原位,从而实现排序。
注:以上的规则是基于升序排序而言降序排序是同样的原理,修改a 和 b 比较的符号即可。
升序排序
/*
快速排序算法排序规则
*/
int32_t CmpCb(const void* _a, const void* _b)
{
uint16_t* a = (uint16_t*)_a;
uint16_t* b = (uint16_t*)_b;
int32_t val = 0;
if (*a > *b)
{
val = 1;
}
else if (*a < *b)
{
val = -1;
}
else
{
val = 0;
}
return val;
}
int main()
{
// 创建局部数组
uint16_t num[10] = { 5,7,8,1,26,52,9,3,14,56 };
uint16_t sz = sizeof(num) / sizeof(num[0]);
// C语言库函数提供的排序函数
qsort(num, sz, sizeof(num[0]), CmpCb);
// for循环打印输出排序玩成后的数据
for (uint8_t i = 0; i < sz; i++)
{
printf("num[%d] = %d.\n",i,num[i]);
}
}
结果:
降序排序
#define _CRC_SECURE_NO_WARNINGS
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
/*
快速排序算法排序规则
*/
#if 0
int32_t CmpCb(const void* _a, const void* _b)
{
uint16_t* a = (uint16_t*)_a;
uint16_t* b = (uint16_t*)_b;
int32_t val = 0;
if (*a > *b)
{
val = 1;
}
else if (*a < *b)
{
val = -1;
}
else
{
val = 0;
}
return val;
}
#else
/*
快速排序算法排序规则
*/
int32_t CmpCb(const void* _a, const void* _b)
{
uint16_t* a = (uint16_t*)_a;
uint16_t* b = (uint16_t*)_b;
int32_t val = 0;
if (*a > *b)
{
val = -1;
}
else if (*a < *b)
{
val = 1;
}
else
{
val = 0;
}
return val;
}
#endif
int main()
{
// 创建局部数组
uint16_t num[10] = { 5,7,8,1,26,52,9,3,14,56 };
uint16_t sz = sizeof(num) / sizeof(num[0]);
// C语言库函数提供的排序函数
qsort(num, sz, sizeof(num[0]), CmpCb);
// for循环打印输出排序玩成后的数据
for (uint8_t i = 0; i < sz; i++)
{
printf("num[%d] = %d.\n",i,num[i]);
}
}
结果:
结构体排序
#define _CRC_SECURE_NO_WARNINGS
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
// 排序结构体
typedef struct
{
uint16_t id;
uint8_t score;
}StuInfo_t;
#if 0
int32_t CmpCb(const void* _a, const void* _b)
{
uint16_t* a = (uint16_t*)_a;
uint16_t* b = (uint16_t*)_b;
int32_t val = 0;
if (*a > *b)
{
val = 1;
}
else if (*a < *b)
{
val = -1;
}
else
{
val = 0;
}
return val;
}
#else
/*
快速排序算法排序规则
*/
int32_t CmpCb(const void* _a, const void* _b)
{
uint16_t* a = (uint16_t*)_a;
uint16_t* b = (uint16_t*)_b;
int32_t val = 0;
if (*a > *b)
{
val = -1;
}
else if (*a < *b)
{
val = 1;
}
else
{
val = 0;
}
return val;
}
int32_t StuCmpCb(const void* _a, const void* _b)
{
StuInfo_t* a = (StuInfo_t*)_a;
StuInfo_t* b = (StuInfo_t*)_b;
int32_t val = 0;
if (a->score > b->score)
{
val = -1;
}
else if (a->score < b->score)
{
val = 1;
}
else
{
val = 0;
}
return val;
}
#endif
int main()
{
// 创建局部数组
uint16_t num[10] = { 5,7,8,1,26,52,9,3,14,56 };
uint16_t sz = sizeof(num) / sizeof(num[0]);
// C语言库函数提供的排序函数
qsort(num, sz, sizeof(num[0]), CmpCb);
// for循环打印输出排序玩成后的数据
for (uint8_t i = 0; i < sz; i++)
{
printf("num[%d] = %d.\n",i,num[i]);
}
// 定义一个结构体数组
StuInfo_t stuInfo[5] =
{
{1,90},
{2,95},
{3,69},
{4,70},
{5,80}
};
// C语言库函数提供的排序函数
qsort(stuInfo, 5, sizeof(stuInfo[0]), StuCmpCb);
// for循环打印输出排序玩成后的数据
for (uint8_t i = 0; i < 5; i++)
{
printf("student_id = %d, score = %d.\n", stuInfo[i].id, stuInfo[i].score);
}
}