当前位置: 首页 > article >正文

C++11标准模板(STL)- 算法 - 对一个范围内的拥有一定未指定类型的元素排序(qsort, qsort_s)

定义于头文件 <stdlib.h>

算法库提供大量用途的函数(例如查找、排序、计数、操作),它们在元素范围上操作。注意范围定义为 [first, last) ,其中 last 指代要查询或修改的最后元素的后一个元素。

对一个范围内的拥有一定未指定类型的元素排序

qsort, 
qsort_s

定义于头文件 <stdlib.h>

void qsort( void *ptr, size_t count, size_t size,
            int (*comp)(const void *, const void *) );

(1)
errno_t qsort_s( void *ptr, rsize_t count, rsize_t size,

                 int (*comp)(const void *, const void *, void *),

                 void *context );
(2)(C11 起)

1) 对 ptr 所指向的数组以升序排序。数组包含 count 个长度为 size 字节的元素。用 comp 所指向的函数比较对象。

2) 同 (1) ,除了传递给 comp 附加环境参数 context ,还会在运行时检测下列错误,并调用当前安装的制约处理函数:

  • countsize 大于 RSIZE_MAX
  • keyptrcomp 是空指针(除非 count 为零)

同所有边界检查函数, qsort_s 仅若实现定义了 __STDC_LIB_EXT1__ ,且用户在包含 stdlib.h 前定义 __STDC_WANT_LIB_EXT1__ 为整数常量 1 才保证可用。

comp 指示两元素相等,则它们排序后的结果是未指定的。

参数

ptr-指向待排序的数组的指针
count-数组的元素数目
size-数组每个元素的字节大小
comp-比较函数。若首个参数小于第二个,则返回负整数值,若首个参数大于第二个,则返回正整数值,若两参数相等,则返回零。

比较函数的签名应等价于如下形式:

 int cmp(const void *a, const void *b);

该函数必须不修改传递给它的对象,而且在调用比较相同对象时必须返回一致的结果,无关乎它们在数组中的位置。

context-附加信息(例如,对照序列),作为第三个参数传递给 comp

返回值

1) (无)

2) 成功时为零,若检测到运行时制约违规,则为非零

注意

与名称无关,C 和 POSIX 标准都未要求此函数用快速排序实现,也未保证任何复杂度或稳定性。

与其他边界检查函数不同, qsort_s 不将零大小数组视作运行时强制违规,而是不修改数组并成功返回(另一个接受零大小数组的函数是 bsearch_s )。

qsort_s 之前,qsort 的用户通常用全局变量来将附加语境传递给比较函数。

调用示例

#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>
#include <iterator>
#include <time.h>

using namespace std;

struct Cell
{
    int x;
    int y;

    Cell &operator +=(const Cell &cell)
    {
        x += cell.x;
        y += cell.y;
        return *this;
    }

    bool operator <(const Cell &cell) const
    {
        if (x == cell.x)
        {
            return y < cell.y;
        }
        else
        {
            return x < cell.x;
        }
    }

    bool operator >(const Cell &cell) const
    {
        if (x == cell.x)
        {
            return y > cell.y;
        }
        else
        {
            return x > cell.x;
        }
    }
};

int compare_Cells_less(const void* a, const void* b)
{
    Cell arg1 = *(const Cell*)a;
    Cell arg2 = *(const Cell*)b;

    if (arg1 < arg2)
    {
        return -1;
    }
    if (arg1 > arg2)
    {
        return 1;
    }
    return 0;

    // return (arg1 > arg2) - (arg1 < arg2); // 可行的简写
    // return arg1 - arg2; // 错误的简写(若给出 INT_MIN 则会失败)
}

int compare_Cells_greater(const void* a, const void* b)
{
    Cell arg1 = *(const Cell*)a;
    Cell arg2 = *(const Cell*)b;

    if (arg1 < arg2)
    {
        return 1;
    }
    if (arg1 > arg2)
    {
        return -1;
    }
    return 0;
}

std::ostream &operator<<(std::ostream &os, const Cell &cell)
{
    os << "{" << cell.x << "," << cell.y << "}";
    return os;
}

int main()
{
    srand((unsigned)time(NULL));;

    std::cout.setf(std::ios_base::boolalpha);

    auto func1 = []()
    {
        int n = std::rand() % 10 + 100;
        Cell cell{n, n};
        return cell;
    };

    Cell cells[] = {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}};
    std::generate(std::begin(cells), std::end(cells), func1);
    std::cout << "cells :               ";
    std::copy(std::begin(cells), std::end(cells), std::ostream_iterator<Cell>(std::cout, " "));
    std::cout << std::endl;

    std::cout << "is_sorted:            " << std::is_sorted(std::begin(cells), std::end(cells));
    std::cout << std::endl << std::endl;

    qsort(cells, std::distance(std::begin(cells), std::end(cells)), sizeof(Cell), compare_Cells_less);
    std::cout << "cells :               ";
    std::copy(std::begin(cells), std::end(cells), std::ostream_iterator<Cell>(std::cout, " "));
    std::cout << std::endl;
    std::cout << "is_sorted:            " << std::is_sorted(std::begin(cells), std::end(cells));
    std::cout << std::endl << std::endl;

    auto is_sortf = [](const Cell & a, const Cell & b)
    {
        if (a.x == b.x)
        {
            return a.y > b.y;
        }
        return a.x > b.x;
    };

    std::generate(std::begin(cells), std::end(cells), func1);
    std::cout << "cells :               ";
    std::copy(std::begin(cells), std::end(cells), std::ostream_iterator<Cell>(std::cout, " "));
    std::cout << std::endl;

    std::cout << "is_sorted:            " << std::is_sorted(std::begin(cells), std::end(cells), is_sortf);
    std::cout << std::endl << std::endl;

    qsort(cells, std::distance(std::begin(cells), std::end(cells)), sizeof(Cell), compare_Cells_greater);
    std::cout << "cells :               ";
    std::copy(std::begin(cells), std::end(cells), std::ostream_iterator<Cell>(std::cout, " "));
    std::cout << std::endl;
    std::cout << "is_sorted:            " << std::is_sorted(std::begin(cells), std::end(cells), is_sortf);
    std::cout << std::endl << std::endl;

    return 0;
}

输出

cells :               {109,109} {106,106} {107,107} {106,106} {108,108}
is_sorted:            false

cells :               {106,106} {106,106} {107,107} {108,108} {109,109}
is_sorted:            true

cells :               {103,103} {105,105} {108,108} {109,109} {108,108}
is_sorted:            false

cells :               {109,109} {108,108} {108,108} {105,105} {103,103}
is_sorted:            true


http://www.kler.cn/a/398997.html

相关文章:

  • Linux 命令 | 每日一学,文本处理三剑客之awk命令实践
  • Android Osmdroid + 天地图 (一)
  • stdin文件流指针
  • Gin 框架中间件详细介绍
  • 从建立TRUST到实现FAIR:可持续海洋经济的数据管理
  • 基于大语言模型意图识别和实体提取功能;具体ZK数值例子:加密货币交易验证;
  • Flutter中的Material Theme完全指南:从入门到实战
  • 深入解析 Vue 3 中的 `v-model` 与相关知识点
  • 架构篇(理解架构的模式1)
  • SSH 与 SSL:主要区别及用途说明
  • 【论文模型复现】深度学习、地质流体识别、交叉学科融合?什么情况,让我们来看看
  • Linux dpkg命令详解
  • AI 提示词(Prompt)入门 十:最佳实践|详细询问,提供细节!
  • 给阿里云OSS绑定域名并启用SSL
  • vue3 如何调用第三方npm包内部的 pinia 状态管理库方法
  • Python脚本实现批量文件重命名与清单生成
  • 前端隐藏元素的方式有哪些?HTML 和 CSS 中隐藏元素的多种方法
  • Spring纯注解开发
  • 【数据库】mysql数据库迁移前应如何备份数据?
  • 机器学习的概览
  • 【金融风控】样本不均衡和异常点检测
  • 随机森林(Random Forest, RF)筛选回归数据(处理异常值)
  • sql注入之二次注入(sqlilabs-less24)
  • JSON.stringify的应用说明
  • ARM(安谋) China处理器
  • 多进程/线程并发服务器