------------------------------------------------------------
author: hjjdebug
date: ? 2023年 12月 13日 星期三 17:30:41 CST
descriptor: qsort & bsearch 算法的使用
------------------------------------------------------------
qsort 用来排序,bsearch用来搜索,是这个意思,但具体怎样使用呢?
qsort 不仅可以用来排序一个整数数组,还可以排序一个结构数组.例子中给出了使用方法.
它真的会在内存中把数据不断的搬移来完成数据的排序.
如果你觉得排序结构数组比较浪费时间,可以让它排序指针.
qsort 在/usr/include/stdlib.h 中定义,
排序数组基地址为base, 数组元素个数nmemb, 每个元素大小为size, 用__compar来比大小
/* Sort NMEMB elements of BASE, of SIZE bytes each,
? ?using COMPAR to perform the comparisons. ?*/
extern void qsort (void *__base, size_t __nmemb, size_t __size,
?? ??? ? ? __compar_fn_t __compar) __nonnull ((1, 4));
bsearch 在/usr/include/stdlib.h 中定义, 就在qsort 函数的上方
bsearch 二分搜索方法,是需要一个排序的数组的,所以先排序数组,然后让bsearch 搜索key
告诉它比较大小的方法,它就能返回能不能找到这个key了
二进制搜索一个key, 在BASE地址, 元素个数NMEMB, 元素大小SIZE,比较函数__COMPAR
/* Do a binary search for KEY in BASE, which consists of NMEMB elements
? ?of SIZE bytes each, using COMPAR to perform the comparisons. ?*/
extern void *bsearch (const void *__key, const void *__base,
?? ??? ? ? ? ?size_t __nmemb, size_t __size, __compar_fn_t __compar)
有了这么好的功能,我们要利用起来, 下面是样例代码:
$ cat main.cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
?* ?用途: 在命令行输入月份的简写, 它会告诉你是几月.
?* ?例如: ./bsearch aug , 会输出 8
?* ?实现方法: 当然是先建立一个表,然后让它找了.
?* ?由于这个表是我们人类方便查阅的方式给出的,为了编程的需要,先把它按月份名称的ascii顺序排序,
?* ?然后就可以用二分法来查找这个表了.
?* ?使用了c库中的qsort 函数, bsearch 函数
?*/
//定义一个"月份信息" 结构 month_info, 月份号,月份名称
struct month_info {
?? ?int nr;
?? ?const char *name;
} months[] = {
?? ?{ 1, "jan" }, { 2, "feb" }, { 3, "mar" }, { 4, "apr" },
?? ?{ 5, "may" }, { 6, "jun" }, { 7, "jul" }, { 8, "aug" },
?? ?{ 9, "sep" }, {10, "oct" }, {11, "nov" }, {12, "dec" }
};
#define nr_of_months (sizeof(months)/sizeof(months[0]))
//"月份信息" 变量"大小"比较, 就是它们的名字比较
static int comp_mi(const void *m1, const void *m2)
{
?? ?struct month_info *mi1 = (struct month_info *) m1;
?? ?struct month_info *mi2 = (struct month_info *) m2;
?? ?return strcmp(mi1->name, mi2->name);
}
int main(int argc, char **argv)
{
?? ?printf("before sort:\n");
?? ?for(size_t i=0;i<nr_of_months;i++)
?? ?{
?? ??? ?printf("#%d,%s ",months[i].nr,months[i].name);
?? ?}
?? ?printf("\n");
?? ?//按照ascii 顺序把结构数组重新排序
?? ?qsort(months, nr_of_months, sizeof(struct month_info), comp_mi);
?? ?printf("after sort:\n");
?? ?for(size_t i=0;i<nr_of_months;i++)
?? ?{
?? ??? ?printf("#%d,%s ",months[i].nr,months[i].name);
?? ?}
?? ?printf("\n");
?? ?for (int i = 1; i < argc; i++) {
?? ??? ?struct month_info key, *res;
?? ??? ?key.name = argv[i];
?? ??? ?res = (struct month_info *)bsearch(&key, &months, nr_of_months, sizeof(struct month_info), comp_mi);
?? ??? ?if (res == NULL)
?? ??? ??? ?printf("'%s': unknown month\n", argv[i]);
?? ??? ?else
?? ??? ??? ?printf("%s: month #%d\n", res->name, res->nr);
?? ?}
?? ?exit(EXIT_SUCCESS);
}
下面是执行结果:
$ ./bsearch aug jan
before sort:
#1,jan #2,feb #3,mar #4,apr #5,may #6,jun #7,jul #8,aug #9,sep #10,oct #11,nov #12,dec?
after sort:
#4,apr #8,aug #12,dec #2,feb #1,jan #7,jul #6,jun #3,mar #5,may #11,nov #10,oct #9,sep?
aug: month #8
jan: month #1
?