如何在二维数组中找到N个最小值(c ++)

时间:2015-11-15 12:34:54

标签: c++ arrays algorithm graph-algorithm

您好我正在研究计算溶剂中氢键配置稳定性的程序。 问题是我现在选择用两个分子之间的距离制作二维阵列i&学家 如何在给定i的数组中找到N(给定)最小值,而不会在排序时丢失索引。 在标准库中是否有这样的东西,我首先想到使用std :: min但是没有用。

编辑: 其中MAXBONDS是上面提到的N. 该课程是

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)最小值。

EDIT2: 这实际上是图算法问题 dist [] []表示分子i和j之间的距离。我需要(如在TSP问题中)所有分子之间的整体最短路径(我需要知道哪个分子与哪个分子相连)。并且每个分子都应该与其他分子具有MAXBONDS连接(它们实际上也存在于最大距离内,但我已经考虑了dist阵列中的那个)所以我的贪婪方法是将所有可能的j的N(MAXBONDS)最短距离用于a鉴于我形成阵列dist。

1 个答案:

答案 0 :(得分:0)

我给出了一个算法,根据距离矩阵找出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;
    }
};

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

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,