【问题标题】:How to find the N smallest values in a 2 dimensional array (c++)如何在二维数组中找到 N 个最小值(c++)
【发布时间】:2015-11-15 12:34:53
【问题描述】:

您好,我目前正在编写一个程序来计算溶剂中氢键构型的稳定性。 问题是目前我选择用两个分子 i 和 j 之间的距离制作二维数组。 如何在给定 i 的数组中找到 N 个(给定)最小值,而不会在排序时丢失索引。 在标准库中是否有类似的东西,我首先想到使用 std::min 但没有成功。

编辑: 其中 MAXBONDS 是上面提到的 N i。 类是

class item{ // ITEM the molecule itself
private:
            //part for molecule charazerization

    std::vector<double> coordinates;
    std::vector<int> bondings;
public:
double calculateSolvents(double dist[][], std::vector<item> items);
}



double item::calculateSolvents(double dist[][], std::vector<item> items){  
for(int i=0; i <= items.size()-1;i++){
  if(items[i].bondings.size()<MAXBONDS){
  for(int j=0;j<= items.size()-1 ;j++){
      if(items[j].bondings.size()< MAXBONDS && 
        (find(items[i].bondings.begin(),items[i].bondings.end(),j)==items[i].bondings.end()) &&
        (find(items[j].bondings.begin(),items[j].bondings.end(),i)==items[j].bondings.end())){


  }}
  }}

并且类的实例存储在一个向量中

 std::vector<item> items

是的,我的意思是对于给定的 i,我想要所有可能的 j 的 N (MAXBONDS) 个最小值。

编辑2: 这实际上是一个图算法问题 dist[][] 表示分子 i 和 j 之间的距离。我需要(就像在 TSP 问题中一样)所有分子之间的整体最短路径(并且我需要知道哪个分子与哪个分子相连)。并且每个分子都应该与其他分子有 MAXBONDS 连接(它们实际上也位于最大距离内,但我已经在 dist 数组中考虑了这一点)所以我的贪婪方法是对所有可能的 j 取 N(MAXBONDS) 最短距离给定 i 形成数组 dist。

【问题讨论】:

  • 请给我们一些代码。 i 和 j 代表什么?
  • 你的意思是对于给定的 i,你想为所有可能的 j 找到 n 个最小值??
  • 我编辑了问题希望现在事情更清楚了坦克你
  • 对不起,这对我来说仍然难以辨认,也许我缺乏关于溶剂中氢键稳定性的化学知识。这里的其他人(很可能)有相同的限制(因为这是一个编程站点),您能进一步解释一下吗?为什么 dist 是二维数组?距离什么?项目在该功能中代表什么?最重要的是,“在排序时获取数组的 N 个最小值而不丢失索引”是什么意思?
  • 所以我希望现在很清楚(请参阅 EDIT2),您实际上可以将其视为 grah 算法问题。其中每个节点都必须有 N 条边,边必须尽可能短。

标签: c++ arrays algorithm graph-algorithm


【解决方案1】:

我给你一个算法来找出给定距离矩阵的 N 个最近邻居。我不会进一步猜测你对分子化合物的建模,所以我使用的是一种非常简化的方法。

#include <iostream>
#include <cmath>
#include <vector>
#include <map>
#include <limits>

struct Point3D {
    double x;
    double y;
    double z;
};

double squareDistance(const Point3D &a, const Point3D &b) {
    double dx = a.x - b.x;
    double dy = a.y - b.y;
    double dz = a.z - b.z;
    return dx*dx + dy*dy + dz*dz;
}

struct Molecule {
    // more meaningfull stuff omitted 
    // ...
    Point3D _pos;
};

我正在使用地图来存储分子 j 的索引以及与分子 i 的距离。

#define MAX_NEIGHBOUR 4 

struct Neighbours {
    std::map<double,size_t> _n;
    double _limit;

    Neighbours() : _limit(std::numeric_limits<double>::infinity()) {}

    double add(double dd, size_t index) {
        if (dd <= _limit) {     // update neighbours only when necessary
            _n[dd] = index;
            if ( _n.size() > MAX_NEIGHBOUR ) {
                auto itn = _n.end();
                _n.erase(--itn);
                if ( dd < _limit ) _limit = dd;
            }
        }
    }

    friend std::ostream & operator<<( std::ostream & out, const Neighbours & nn) {
        for ( auto i : nn._n) {
            out << i.second << " at " << std::sqrt(i.first) << ", ";
        }
        return out << std::endl;
    }
};

我假设距离矩阵是对称的(除非您使用相同的奇怪拓扑)并将其存储在单个向量中。

struct DistMol {
    DistMol(const std::vector<Molecule> & mols) :   _rows(mols.size()),
                                                    _d(_rows*(_rows-1)/2+1),
                                                    _near(_rows),
                                                    _mol(mols){}

    void evaluate() {       // The "matrix" of distances is simmetric
        auto id = _d.begin();
        for (size_t i=0; i<_rows; i++) {
            for (size_t j=i+1; j<_rows; j++) {
                *id = squareDistance(_mol[i]._pos,_mol[j]._pos);
                _near[i].add(*id,j);
                _near[j].add(*id,i);
                ++id;
            }
        }
    }

    double distance(size_t i, size_t j) { // remember that I have only half the matrix
        long int dij = i - j;

        if ( dij > 0 && i < _rows ) 
            return std::sqrt(_d[j*_rows - j*(j+1)/2 + dij - 1]);
        else if ( dij < 0 && j < _rows)
            return std::sqrt(_d[i*_rows - i*(i+1)/2 - dij - 1]);
        else return 0.0;
    }
    void showDistances() {
        std::cout << std::fixed;
        for ( size_t i=0; i<_rows; i++) {
            for (size_t j=0; j<_rows; j++) {
                std::cout << distance(i,j) << ' ';
            }
            std::cout << std::endl;
        }
    }
    void showNearest() {
        size_t i = 0;
        for ( auto n : _near) {
            std::cout << i++ << ": " << n;
        }
    }

    size_t _rows;
    std::vector<double> _d;
    std::vector<Neighbours> _near;
    const std::vector<Molecule> & _mol;
};

这是一个使用示例及其输出:

int main() {
    std::vector<Molecule> mo   {{1.0,0.0,0.5}, {2.0,0.5,1.2}, {4.8,2.3,1.9},
                                {3.7,3.9,8.7}, {2.1,0.5,1.3}, {5.8,2.5,4.4},
                                {5.7,4.1,2.3}, {1.7,0.8,6.2}, {0.8,0.3,1.0}};
    DistMol dm {mo};

    dm.evaluate();
    dm.showDistances();
    dm.showNearest();

    return 0;
}

哪些输出:

0.000000 1.319091 4.657252 9.473120 1.449138 6.670832 6.491533 5.798276 0.616441 
1.319091 0.000000 3.401470 8.408329 0.141421 5.355371 5.278257 5.017968 1.232883 
4.657252 3.401470 0.000000 7.071775 3.300000 2.700000 2.051828 5.509083 4.561798 
9.473120 8.408329 7.071775 0.000000 8.299398 4.985980 6.708204 4.456456 8.981091 
1.449138 0.141421 3.300000 8.299398 0.000000 5.224940 5.188449 4.925444 1.349074 
6.670832 5.355371 2.700000 4.985980 5.224940 0.000000 2.641969 4.789572 6.434283 
6.491533 5.278257 2.051828 6.708204 5.188449 2.641969 0.000000 6.488451 6.335614 
5.798276 5.017968 5.509083 4.456456 4.925444 4.789572 6.488451 0.000000 5.300943 
0.616441 1.232883 4.561798 8.981091 1.349074 6.434283 6.335614 5.300943 0.000000 
0: 8 at 0.616441, 1 at 1.319091, 4 at 1.449138, 2 at 4.657252, 
1: 4 at 0.141421, 8 at 1.232883, 0 at 1.319091, 2 at 3.401470, 
2: 6 at 2.051828, 5 at 2.700000, 4 at 3.300000, 1 at 3.401470, 
3: 7 at 4.456456, 5 at 4.985980, 2 at 7.071775, 4 at 8.299398, 
4: 1 at 0.141421, 8 at 1.349074, 0 at 1.449138, 2 at 3.300000, 
5: 6 at 2.641969, 2 at 2.700000, 3 at 4.985980, 4 at 5.224940, 
6: 2 at 2.051828, 5 at 2.641969, 4 at 5.188449, 1 at 5.278257, 
7: 3 at 4.456456, 5 at 4.789572, 4 at 4.925444, 1 at 5.017968, 
8: 0 at 0.616441, 1 at 1.232883, 4 at 1.349074, 2 at 4.561798, 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-09
    • 1970-01-01
    • 2012-04-21
    • 2018-07-05
    • 2018-09-14
    • 2015-04-06
    • 2013-12-03
    相关资源
    最近更新 更多