【问题标题】:Using the sort function on vectors on different variables对不同变量的向量使用排序函数
【发布时间】:2020-12-12 01:40:06
【问题描述】:

我有坐标给出的数据。我做了他们的课程,课程是由这个组成的:

Point2D (int x, int y)

Point3D (int z) //#include Point2D.h

Line2D (Point2D pt1, Point2D pt2)

Line3D (Point3D pt1, Point3D pt2)

现在,我应该能够根据任何过滤标准(每个类都是一个过滤标准)、任何排序标准(x, y, z 或其产品)和排序顺序(升序或降序)对数据进行排序 过滤条件指定要显示的记录集。

我创建了一个通用排序算法,但我应该使用 STL 算法中的排序函数。我在下面粘贴我的算法,但有人可以使用std::sort 函数简化它。

void sort(
   vector<Point2D*>& point2DList,
   vector<Point3D*>& point3DList,
   vector<Line2D*>& line2DList,
   vector<Line3D*>& line3DList,
   string filterCriteria, string sortingCriteria, string sortingOrder)
{
   if (filterCriteria == "Point2D")
   {
      for (int i = 0; i < (int)point2DList.size() - 1; i++)
      {
         int index = i;
         for (int j = i + 1; j < point2DList.size(); j++)
         {
            if (sortingOrder == "ASC")
            {
               if ((sortingCriteria == "x-ordinate" && point2DList[index]->getX() > point2DList[j]->getX()) || 
                  (sortingCriteria == "y-ordinate" && point2DList[index]->getY() > point2DList[j]->getY()))
                  index = j;
            }
            else if (sortingOrder == "DSC")
            {
               if ((sortingCriteria == "x-ordinate" && point2DList[index]->getX() < point2DList[j]->getX()) || 
                  (sortingCriteria == "y-ordinate" && point2DList[index]->getY() < point2DList[j]->getY()))
                  index = j;
            }
         }
         Point2D* ptr = point2DList[i];
         point2DList[i] = point2DList[index];
         point2DList[index] = ptr;
      }
   }
}

我只粘贴了算法的第一部分,其中涉及Point2D 对象,我也为其他 3 个类应用了相同的流程。

【问题讨论】:

  • 你能写一个函数来接受两个项目,如果第一个项目应该在第二个项目之前就返回 true 吗?这是您要传递给std::sort 的内容。

标签: c++ algorithm class sorting c++11


【解决方案1】:

据我了解,首先,您使用单个 sort 函数(非模板)对不同的数据结构进行排序。这不是您制作通用排序功能的方式。你需要去function templates

其次,指向这些数据结构的原始指针向量看起来不合适。 std::vector created/ 在空闲存储中动态分配它的下划线数据,这意味着您不需要将每个元素放入手动创建的内存中。如果这无法避免,我会建议 smart pointers 而不是那里的原始指针。

第三,filterCriteriasortingOrdersortingCriteria 可能是 enums 而不是 std::strings。

以下是修改后的sort函数,实际上只考虑了你使用std::sort的需求。另请注意,我已使用 lambda functions 自定义排序标准,您可以在此处阅读更多信息:What is a lambda expression in C++11?

// enumerations  for case checking!
enum class FilterCriteria { Point2D = 0, Point3D/*, other cases*/ };
enum class SortingCriteria { x_ordinate = 0, y_ordinate };
enum class SortingOrder { ASC = 0, DSC };

void sort(
   std::vector<Point2D*>& point2DList,
   std::vector<Point3D*>& point3DList,
   std::vector<Line2D*>& line2DList,
   std::vector<Line3D*>& line3DList,
   const FilterCriteria filterCriteria,
   const SortingOrder sortingOrder,
   const SortingCriteria sortingCriteria)
{
   const auto xLessCompare = [](const Point2D* lhs, const Point2D* rhs) { return lhs->x < rhs->x; };
   const auto yLessCompare = [](const Point2D* lhs, const Point2D* rhs) { return lhs->y < rhs->y; };
   const auto xGreaterCompare = [](const Point2D* lhs, const Point2D* rhs) { return lhs->x > rhs->x; };
   const auto yGreaterCompare = [](const Point2D* lhs, const Point2D* rhs) { return lhs->y > rhs->y; };

   switch (filterCriteria)
   {
   case FilterCriteria::Point2D:
   {
      if (sortingOrder == SortingOrder::ASC)
      {
         if (sortingCriteria == SortingCriteria::x_ordinate)
            std::sort(point2DList.begin(), point2DList.end(), xGreaterCompare);
         else if (sortingCriteria == SortingCriteria::y_ordinate)
            std::sort(point2DList.begin(), point2DList.end(), yGreaterCompare);
      }
      else if (sortingOrder == SortingOrder::DSC)
      {
         if (sortingCriteria == SortingCriteria::x_ordinate)
            std::sort(point2DList.begin(), point2DList.end(), xLessCompare);
         else if (sortingCriteria == SortingCriteria::y_ordinate)
            std::sort(point2DList.begin(), point2DList.end(), yLessCompare);

      }
      break;
   }
   case FilterCriteria::Point3D: {
      // ... code
      break;
   }
   default: break;
   };
}

See here for an example code onlone

【讨论】:

    【解决方案2】:

    我没有你的类定义,所以我做了这些,我希望它们和你的一样。

    如果你想使用std::sort,你有两个选择:

    1. 为类(或结构)定义 less (
    2. 传递 lambda,作为较少的比较器

    如果多次使用排序,或者如果类存储在容器中,则使用 1 选项,这需要较少的运算符(如 std::setstd::map) 如果您仅在整个代码中的一个位置对某些结构体进行排序并且您需要内联它,或者您必须重载当前指定的 less 运算符,则 2 选项很好

    这是包含两个选项的代码,希望对您有所帮助。如果有什么让您感到困惑的,请随时发表评论

    #include <algorithm>
    #include <vector>
    #include <iostream>
    #include <random>
    
    struct Point2D
    {
        int x;
        int y;
    
        Point2D(const int x, const int y) : x{x}, y{y} {}
    
        inline friend bool operator<(const Point2D& p1, const Point2D& p2)
        {
            return ( p1.x == p2.x ? p1.y < p2.y : p1.x < p2.x );
        }
    };
    
    // print operator
    std::ostream& operator<<(std::ostream& o, const Point2D& p)
    {
        return o << "( x=" << p.x << ", y=" << p.y << ")";
    }
    
    struct Point3D : public Point2D
    {
        Point3D(const int x, const int y, const int z) : Point2D{ x,y }, z{z} {}
    
        int z;
    };
    
    // print operator
    std::ostream& operator<<(std::ostream& o, const Point3D& p)
    {
        return o << "( z=" << p.z << ", x=" << p.x << ", y=" << p.y << ")";
    }
    
    // supportive functions for printing
    template<typename T>
    void print_collection( const std::vector<T>& vec, const char* collection_name )
    {
        std::cout << collection_name << ": ";
        for(const auto& var : vec)
            std::cout << var << ", ";
    
        std::cout << std::endl;
    }
    
    template<typename T>
    void print_ptr_collection( const std::vector<T>& vec, const char* collection_name )
    {
        std::cout << collection_name << ": ";
        for(const auto& var : vec)
            std::cout << *var << ", ";
    
        std::cout << std::endl;
    }
    
    // support functions for random numbers
    int rng()
    {
        std::random_device engine;
        std::uniform_int_distribution<int> ranges{ -100, 100 };
        return ranges(engine);
    }
    
    int main()
    {
        std::vector<Point2D> vec1; vec1.reserve(5);
        std::vector<Point3D*> vec2; vec2.reserve(5);
    
        // fill
        for(int i = 0; i < 5; i++)
        {
            vec1.emplace_back( rng(), rng() );
            vec2.emplace_back( new Point3D{ rng(), rng(), rng() } );
        }
    
        // print unsorted
        print_collection( vec1, "vec1 unsorted");
        print_ptr_collection( vec2, "vec2 unsorted");
    
        // sort with std::sort
        std::sort( vec1.begin(), vec1.end() );
        std::sort( vec2.begin(), vec2.end(), [](const Point3D* p1, const Point3D* p2) -> bool {
            return ( p1->z == p2->z ? (*p1) < (*p2) : p1->z < p2->z );
        } );
    
        // print sorted
        print_collection( vec1, "vec1 sorted" );
        print_ptr_collection( vec2, "vec2 sorted" );
    
        // cleanup
        for(int i = 0; i < vec2.size(); i++)
        {
            delete vec2[i];
            vec2[i] = nullptr;
        }
    
    }
    

    这是输出:

    vec1 unsorted: ( x=3, y=66), ( x=-1, y=-65), ( x=-9, y=-70), ( x=29, y=16), ( x=32, y=56), 
    vec2 unsorted: ( z=-51, x=-57, y=-87), ( z=58, x=49, y=43), ( z=-71, x=-63, y=-87), ( z=23, x=-22, y=13), ( z=-57, x=94, y=-7), 
    vec1 sorted: ( x=-9, y=-70), ( x=-1, y=-65), ( x=3, y=66), ( x=29, y=16), ( x=32, y=56), 
    vec2 sorted: ( z=-71, x=-63, y=-87), ( z=-57, x=94, y=-7), ( z=-51, x=-57, y=-87), ( z=23, x=-22, y=13), ( z=58, x=49, y=43), 
    

    编辑:忘记在末尾添加删除指针:)

    【讨论】:

      猜你喜欢
      • 2015-12-31
      • 2018-02-21
      • 2011-10-15
      • 1970-01-01
      • 2013-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多