查找向量的唯一条目并删除区间之外的条目[cMin,cMax]

时间:2018-01-21 15:06:53

标签: c++

我已经设法实现了我计划正确执行的大部分工作,但不知怎的,我在使用独特的切割方法。

唯一方法应该对矢量进行排序并删除多次出现的所有条目,并且应该用缩短的on覆盖原始矢量。 cut方法应删除所有条目< cMin或> CMAX。

到目前为止,这是我的尝试:

#include <cassert>
#include <iostream>

using std::cout;
using std::endl;

class Vector {
private:
    int n;
    double* coeff;

public:
    Vector(int, double = 0);
    ~Vector();

    Vector(const Vector&);
    Vector& operator=(const Vector&);

    int size() const;
    double& operator()(int);
    const double& operator()(int) const;

    double max() const;
    void sort();
    void unique();
    void cut(double Cmin, double Cmax);

    void print() const;
};

Vector::Vector(int n, double init)
{
    assert(n >= 0);

    this->n = n;

    if (n == 0) {
        coeff = (double*)0;
    }
    else {
        coeff = new double[n];
    }

    for (int i = 0; i < n; i++) {
        coeff[i] = init;
    }
}

Vector::Vector(const Vector& rhs)
{
    n = rhs.n;

    if (n > 0) {
        coeff = new double[n];
    }
    else {
        coeff = (double*)0;
    }

    for (int i = 0; i < n; i++) {
        coeff[i] = rhs.coeff[i];
    }
}

Vector::~Vector()
{
    if (n > 0) {
        delete[] coeff;
    }
}

Vector& Vector::operator=(const Vector& rhs)
{
    if (this != &rhs) {
        if (n != rhs.n) {
            if (n > 0) {
                delete[] coeff;
            }
            n = rhs.n;
            if (n > 0) {
                coeff = new double[n];
            }
            else {
                coeff = (double*)0;
            }
        }

        for (int i = 0; i < n; i++) {
            coeff[i] = rhs.coeff[i];
        }
    }
    return *this;
}

int Vector::size() const
{
    return n;
}

double& Vector::operator()(int j)
{
    assert(j >= 1 && j <= n);
    return coeff[j - 1];
}

const double& Vector::operator()(int j) const
{
    assert(j >= 1 && j <= n);
    return coeff[j - 1];
}

double Vector::max() const
{
    double max = coeff[0];

    for (int i = 1; i < n; i++) {
        if (coeff[i] > max) {
            max = coeff[i];
        }
    }

    return max;
}

void Vector::sort()
{ //bubble-sort
    double tmp = 0;

    for (int i = 0; i < n - 1; i++) {
        for (int j = 0; j < n - 1; j++) {
            if (coeff[j] > coeff[j + 1]) {
                tmp = coeff[j];
                coeff[j] = coeff[j + 1];
                coeff[j + 1] = tmp;
            }
        }
    }
}

void Vector::unique()
{
    sort();

    int counter = 0;

    Vector kopie = *this;

    for (int i = 0; i < n; i++) {
        if (i == 0 && coeff[i] != coeff[i + 1]) {
            counter++;
        }
        if (i == n - 1 && coeff[i] != coeff[i - 1]) {
            counter++;
        }
        if (i != 0 && i != n - 1 && coeff[i] != coeff[i - 1] && coeff[i] != coeff[i + 1]) {
            counter++;
        }
    }

    delete[] coeff;
    coeff = new double[counter];

    //to be continued...
}

void Vector::cut(double Cmin, double Cmax)
{
    sort();

    int counter = 0;
    int j = 0;
    Vector kopie = *this;

    for (int i = 0; i < n; i++) {
        if (coeff[i] >= Cmin && coeff[i] <= Cmax) {
            counter++;
        }
    }

    delete[] coeff;
    coeff = new double[counter];

    for (int i = 0; i < n; i++) {
        if (kopie.coeff[i] >= Cmin && kopie.coeff[i] <= Cmax) {
            coeff[j] = kopie.coeff[i];
            j++;
            if (j == n) {
                break;
            }
        }
    }
}

void Vector::print() const
{
    for (int i = 0; i < n; i++) {
        cout << coeff[i] << " ";
    }
}

int main()
{
    Vector X(8);

    X.print();
    cout << endl;

    X(1) = 1.;
    X(2) = 7.;
    X(3) = 2.;
    X(4) = 5.;
    X(5) = 6.;
    X(6) = 5.;
    X(7) = 9.;
    X(8) = 6.;

    X.print();
    cout << endl;

    X.sort();
    X.print();
    cout << endl;

    //X.unique();
    //X.print();
    //cout << endl;

    X.cut(2, 6);
    X.print();
    cout << endl;
    return 0;
}

4 个答案:

答案 0 :(得分:0)

对于独特的功能,我只想检查你当前的元素和下一个元素是否相同,而不是检查向前移动计数器是否合法。如果是,则设置下一个元素的指针以跳过重复元素。

Pseduocode:

For(int i = 0; i < n-1; i++) {
     if(coef[i] == coef[i+1]) {
         //Keep moving next element pointer until not equal. Probably use a while loop
      }
 }

答案 1 :(得分:0)

我能想到的最简单的解决方案就是这样:

void Vector::unique()
{
  size_t counter = 0;

  double* copy = new double[n];

  copy[counter++] = coeff[0]; // The first element is guaranteed to be unique

  // Since coeff is sorted, copy will be sorted as well. 
  //   Therefore, its enough to check only the last element of copy to 
  //   the current element of coeff
  for (size_t i = 1; i < n; i++) 
  {
    if (coeff[i] != copy[counter]) 
    {
      copy[counter++] = coeff[i];
    }
  }

  // copy already contains the data in the format that you want, 
  //   but the reserved memory size may be larger than necessary. 
  //   Reserve the correct amount of memory and copy the data there
  delete[] coeff;
  coeff = new double[counter];

  std::memcpy(coeff, copy, counter*sizeof(double));
}

对于cut(),您可以使用类似的算法:

void Vector::cut(double Cmin, double Cmax)
{
  size_t counter = 0;

  double* copy = new double[n];

  for (size_t i = 0; i < n; i++) 
  {
    if (coeff[i] > Cmin && coeff[i] < Cmax) 
    {
      copy[counter++] = coeff[i];
    }
  }

  // Same story with memory size here as well
  delete[] coeff;
  coeff = new double[counter];

  std::memcpy(coeff, copy, counter*sizeof(double));
}

答案 2 :(得分:0)

你有什么理由不能使用标准库吗?

void Vector::unique() {
    std::sort(coeff, std::next(coeff, n));
    auto it = std::unique(coeff, std::next(coeff, n));
    double* tmp = new double[n = std::distance(coeff, it)];
    std::copy(coeff, it, tmp);
    delete[] std::exchange(coeff, tmp);
}

void Vector::cut(double Cmin, double Cmax) {
    auto it = std::remove_if(coeff, std::next(coeff, n),
        [=] (double d) { return d < Cmin || d > Cmax; });
    double* tmp = new double[n = std::distance(coeff, it)];
    std::copy(coeff, it, tmp);
    delete[] std::exchange(coeff, tmp);
}

答案 3 :(得分:-1)

要删除重复项和排序,您可以通过三种方式实现它

只需使用vector,sort + unique

 sort( vec.begin(), vec.end() ); 
 vec.erase( unique( vec.begin(), vec.end() ), vec.end() );

转换为设置(手动)

set<int> s;
unsigned size = vec.size(); 
for( unsigned i = 0; i < size; ++i ) 
s.insert( vec[i] ); vec.assign( s.begin(), s.end() );

转换为set(使用构造函数)

set<int> s( vec.begin(), vec.end() ); 
vec.assign( s.begin(), s.end() );

这三种都有不同的表现。您可以使用一个,具体取决于您的大小和重复数量。

要削减你可以使用算法库

std::remove, std::remove_if

语法

template< class ForwardIt, class T >
constexpr ForwardIt remove( ForwardIt first, ForwardIt last, const T& value );

可能的实施

第一版

template< class ForwardIt, class T > ForwardIt remove(ForwardIt first, ForwardIt last, const T& value) 
{ first = std::find(first, last, value); 
if (first != last) 
for(ForwardIt i = first; ++i != last; ) 
if (!(*i == value)) 
*first++ = std::move(*i); return first; }

第二版

template<class ForwardIt, class UnaryPredicate> ForwardIt remove_if(ForwardIt first, ForwardIt last, UnaryPredicate p) 
{ first = std::find_if(first, last, p); 
if (first != last) 
for(ForwardIt i = first; ++i != last; ) 
if (!p(*i)) *first++ = std::move(*i); 
return first; }

实施例

以下代码通过将所有非空格字符向左移动然后删除额外字符来删除字符串中的所有空格。这是擦除 - 删除习语的一个例子。

运行此代码

#include <algorithm> 
#include <string> 
#include <iostream> 
#include <cctype>   
int main() 
{ std::string str1 = "Text with some spaces"; str1.erase(std::remove(str1.begin(), str1.end(), ' '), str1.end()); 
std::cout << str1 << '\n';   
std::string str2 = "Text\n with\tsome \t whitespaces\n\n"; str2.erase(std::remove_if(str2.begin(), str2.end(), [](unsigned char x)
{return std::isspace(x);}), str2.end()); 
std::cout << str2 << '\n'; }

输出:

Textwithsomespaces 
Textwithsomewhitespaces