【问题标题】:How can I split "Segment" to two "Segments"? c++如何将“细分”拆分为两个“细分”? C++
【发布时间】:2018-12-04 08:54:40
【问题描述】:

给定以下类:

#include <vector>

using std::vector;

enum TypeSeg {
    OPEN, CLOSE, CLOSE_LEFT, CLOSE_RIGHT
};

template<class T>
class Segment {
    T left;
    T right;
    TypeSeg typeS;
public:
    Segment(T left, T right, TypeSeg typeS) :
            left(left), right(right), typeS(typeS) {
    }
    //.....
};

template<class T>
class SegCollection {
    vector<Segment<T>> segments;
public:
//.....
};

所以 Segment 描述了段 ?left, right? 而:
如果 typeS==OPEN 所以:(left,right).
如果 typeS==CLOSE 所以:[left,right].
如果 typeS==CLOSE_LEFT 所以:[left,right).
如果 typeS==CLOSE_RIGHTso :(left,right]

SegCollection 描述了段的集合,因此:
SegCollection no 包含两个相同的段,并且 no 包含两个相交的段(它将包含它们的并集),甚至 no 包含两个像这样的段:[1,4)[4,5)(例如),但是,它会包含[1,5)

我如何为 SegCollection 实现 operator-() 以从 SegCollection 中删除段,以便:此段不必在 SegCollection 中,而是 SegCollection 中存在的所有点(来自 SegCollection 中的所有段)和 将从 SegCollection 中存在的段中删除。

例如:给定:[1,7] , [9,12],如果我们将删除(2,5),那么我们将得到:[1,2] , [5,7] , [9,12]

我不知道(我考虑了几个小时..)如果我需要在删除段后拆分段(如示例中的 [1,7] ,更改为 [1,2] , [5,7] )?

注意:Segment 是一个模板类,因为它可以来自 (int, int) , (float,float) 例如

【问题讨论】:

  • 通常,您首先尝试手动完成这项工作。然后,为它编写代码。
  • @Ripi2 什么意思?
  • 举一些例子,你能用纸和铅笔做吗?你能解释一下你是怎么做的吗,有哪些步骤?使用rubber duck
  • @Ripi2 对不起,我还是不明白你想要什么(也就是说,我知道你说“使用橡皮鸭”时的意思,但我做到了,就像你可以从我的问题看,但我仍然不知道该怎么做)
  • 添加两个新段。起点/终点是 (3,5) 的 thouse。请注意这些新细分的“类型”-

标签: c++ class c++11 vector


【解决方案1】:

这个提示可能会有所帮助。

template<typename T>
class SegCollection {
    vector<Segment<T>> segments;
public:
    void push_back(Segment<T> seg)
    {
        segments.push_back(seg);
    }

    const SegCollection& operator-(const Segment<T> seg) 
    {  
        // implement some rules that recognize field 
        // TypeSeg and depending on it, changing segments' content
        // ...
        return *this;
    }
}

在下面找到您的假设的简短应用。由于访问原因,我已将 class 更改为 struct(您可以离开班级,但您需要提供一些 getter 才能访问私有成员)

#include <vector>
#include <algorithm>
using std::vector;

enum TypeSeg {
    OPEN, CLOSE, CLOSE_LEFT, CLOSE_RIGHT
};

template<typename T>
struct Segment {
    T left;
    T right;
    TypeSeg typeS;

    Segment(T left, T right, TypeSeg typeS) :
            left(left), right(right), typeS(typeS) {
    };
};

template<typename T>
struct SegCollection {

    vector<Segment<T>> segments;

    void push_back(Segment<T> seg)
    {
        segments.push_back(seg);
    }

    const SegCollection& operator-(const Segment<T> seg) 
    { 
        //Find segment that could be divided
        auto it = std::find_if(segments.begin(), segments.end(),
                          [&seg](auto i){ 
                              if (i.left <= seg.left)
                                 if (seg.right <= i.right) 
                                     return true;
                              return false;
                        });

        //If not found, return *this
        if (it == segments.end())
        {
            std::cout << "Cannot do this, Bro." << std::endl;
            return *this;
        }

        //Set boundaries for new segments
        int new_right = it->left + seg.left - it->left;            
        int new_left = seg.right;

        // Here you have to apply other conditions
        // I have used only one case - as you have mentioned in your post
        if (seg.typeS == OPEN)
        {
            Segment<T> seg_first(it->left, new_right, CLOSE);
            Segment<T> seg_second(new_left, it->right, CLOSE);
            *it = seg_second;
            this->segments.insert(it, seg_first);   

        } 

        return *this;
    }
};

【讨论】:

  • 您能说明如何处理以下情况吗?如果我想从我的 SegCollection = [2,7] , [10,15] 中删除段 (3,5) ,我怎样才能从 [2,7] 中删除段 [2,3] , [5,7] (删除后)?
  • 我不喜欢这个主意,因为你把所有Segment 都写成了公开的,这不是个好主意..
  • 正如我所提到的,如果您还想使用类和私有成员,则应该包含一些 getter(使您能够获取私有成员变量的公共方法)。
猜你喜欢
  • 2019-02-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多