• C++ 获取序列最大(或最小)的 N 个元素


    经常遇到一个事情,就是获取一个图片中所有像素值的最大和最小 2% 的值,所以封装了一个 LimitArray 的类,用于把一个序列中最大(或最小)的 N 个值给提取出来。

    代码如下:

    #include <iostream>
    #include <vector>
    #include <array>
    #include <limits>
    #include <type_traits>
    #include <algorithm>
    #include <iterator>
    
    
    /// <summary>
    /// 极限值数组
    /// 用于获取序列的最小或者最大的多个值.
    /// </summary>
    /// <typeparam name="T">数据类型</typeparam>
    template <typename T,size_t _size,bool _minimum>
    class LimitArray:public std::array<T,_size> {
        static_assert(std::is_arithmetic<T>::value,
            "template parameter must arithmetic types");
        static_assert(_size > 1, "please use min_element or max_element");
    public:
        LimitArray()
        {
            if (_minimum) {
                this->fill(std::numeric_limits<T>::max());
            }
            else {
                this->fill(std::numeric_limits<T>::lowest());
            }
        }
        /// <summary>
        /// 添加一个值 value
        /// 如果获取小值,且 value < fornt 则所有元素后移一位,弹出 back, value作为首元素
        /// 如果获取大值,且 value > back 则所有元素前移一位,弹出 front, value作为末元素
        /// </summary>
        /// <param name="value"></param>
        inline void push(T value)
        {
            if (_minimum) {
                // 留小不留大,如果比当前最大值都大,就不用继续了
                if (value >= this->back()) { return; }
                // 下面的操作就是,把最大的元素移除,把 value 插入合适位置
                // 查找合适的插入点;第一个大于 value 的元素的迭代器
                auto iter = std::upper_bound(this->begin(), this->end(), value);
                // 移动 [插入点,倒数第二个] 数据往后一位
                // 注意,参数是半闭半开区间 ,第三个参数是目标序列的最后一个的后一个
                std::move_backward(iter, this->end() - 1, this->end());
                *iter = value;
            }
            else {
                // 留大不留小
                if (value <= this->front()) { return; }
                // 查找合适的插入点;第一个不小于 value 的元素的迭代器的前一个
                auto iter = std::lower_bound(this->begin(), this->end(), value) - 1;
                // 移动 [第二个,插入点] 数据往前一位
                std::move(this->begin() + 1, iter+1, this->begin());
                *iter = value;
            }
        }
    };
    
    // 简单测试一下
    int main()
    {
      std::vector<int> v = {1,3,2,6,4,7,5,0,9,8};
      LimitArray<int,7,true> la1;
      LimitArray<int,2,false> la2;
      for(size_t i=0;i<v.size();++i){
        la1.push(v[i]);
        la2.push(v[i]);
      }
      std::copy(la1.begin(), la1.end(),
                  std::ostream_iterator<int>(std::cout, " "));
        std::cout << '
    ';
        std::copy(la2.begin(), la2.end(),
                  std::ostream_iterator<int>(std::cout, " "));
        std::cout << '
    ';
      return 0;
    }
    

    运行输出如下:

    0 1 2 3 4 5 6 
    8 9
    
    
  • 相关阅读:
    C++--第25课
    C++--第24课
    C++--第23课
    C++--第22课
    C++--第21课
    C++--第20课
    C++--第19课
    C++--第18课
    C++--第17课
    Windows程序设计学习笔记(1):一个简单的windows程序
  • 原文地址:https://www.cnblogs.com/oloroso/p/13387686.html
Copyright © 2020-2023  润新知