0

假设我有一组 10000 个点,它们随机地相互连接。例如,让我们取 10 分。他们像图片一样连接在一起- 在此处输入图像描述

相似点的定义:

具有相同数量链接的点称为相似点。从图中我们可以看出——

节点 1 与节点 [2] 和 [10] 连接

节点 2 与节点 [1},[3],[4],[5],[6],[7],[8] 连接

节点 3 仅与节点 [2] 连接

节点 4 仅与节点 [2] 连接

节点 5 仅与节点 [2] 连接

节点 6 仅与节点 [2] 连接

节点 7 仅与节点 [2] 连接

节点 8 与节点 [2] 和 [9] 连接

节点 9 仅与节点 [8] 连接

节点 10 仅与节点 [1) 连接

所以根据定义,Node- 3,4,5,6,7,9,10 是相似的,因为它们每个只有一个链接。同样,节点 1 和 8 是相似的,因为它们每个都有两个链接。

我的问题

现在我想计算相似点的链接总和。例如-

节点 1 有 8 个类似的。

对于节点 1:

它连接到节点 2(有7 个链接)

并且还连接到节点 10(有1 个链接)

对于节点 8:

它连接到节点 2(有7 个链接)

并且还连接到节点 9(有1 个链接)

所以对于有两个链接的组,总链接数应该是= 7+1+7+1 =16。像这种方式我想计算其他类似点的总链接。

我的代码

这是我的代码。它给出了每个点的总链接的结果。

#include <cstdlib>
#include <cmath>
#include <fstream>
#include <iostream>
#include <vector>


using namespace std;

struct Node {

    vector< int > links_to;
    Node(void){};
    Node(int first_link){
        links_to.push_back(first_link);
    };
};

class Links : public vector<Node> {

public:
    void CreateLinks(int n,int m);
    void OutputNodes();

};

int RandGenerate(int max) {

    return int(drand48()*double(max));
}

void CreateRandom(int *nums,int m,int max) {

    bool clear;
    for(int i=0;i<m;i++) {

        clear=true;
        while(clear) {

            clear=false;
            nums[i]=RandGenerate(max);
            for(int j=0;j<i;j++) {

                if(nums[i]==nums[j]){
                    clear=true;break;
                }
            }
        }
    }
}

void Links::CreateLinks(int n,int m) {

    clear();
    for(int i=0;i<m;i++) {
        push_back(Node());
    }

    int edge_targets[m],nums[m];
    for(int i=0;i<m;i++) { 
        edge_targets[i]=i;
    }
    vector<int> repeated_nodes;

    int source=m;
    while(source<n) {

        push_back(Node());
        Node &node=*(end()-1);
        for(int i=0;i<m;i++) {

            node.links_to.push_back(edge_targets[i]);
            at(edge_targets[i]).links_to.push_back(source);
            repeated_nodes.push_back(edge_targets[i]);
            repeated_nodes.push_back(source);
        }

        CreateRandom(nums,m,repeated_nodes.size());
        for(int i=0;i<m;i++) {
            edge_targets[i]=repeated_nodes[nums[i]];
        }
        source++;
    }
}

void Links::OutputNodes() {

    for(int i=0;i<size();i++){
        cout<<endl;

        for(int j=0;j<at(i).links_to.size();j++){

            cout<<"Node "<<(i+1)<<" is connected with ["<<(at(i).links_to[j]+1)<<"]"<<endl;


        }

        cout<<"For Node: "<<(i+1)<<"\t"<<"Total links: "<<at(i).links_to.size()<<endl;
    }
}



int main() {



    srand48(46574621);
    Links network;

    network.CreateLinks(10,1); //(nodes,minimum value of link) 
    network.OutputNodes();

    return 0;
}

产生这样的结果-

Node 1 is connected with [2]
Node 1 is connected with [10]
For Node: 1 Total links: 2

Node 2 is connected with [1]
Node 2 is connected with [3]
Node 2 is connected with [4]
Node 2 is connected with [5]
Node 2 is connected with [6]
Node 2 is connected with [7]
Node 2 is connected with [8]
For Node: 2 Total links: 7

Node 3 is connected with [2]
For Node: 3 Total links: 1

Node 4 is connected with [2]
For Node: 4 Total links: 1 ... etc

我想添加一个函数,以便它将相似点分组并给出每个组的总链接的输出。我怎样才能做到这一点?

更新以响应 Pixelchemist 的回答

假设我将数据存储在文件名“MyLinks.txt”中,如下所示 -

1 2
1 10
2 1
2 3
2 4
2 5
2 6 
2 7
2 8...etc

并从文件中获取输入。这是代码-

int main (void)
{
ifstream inputFile("MyLinks.txt");
double Temp[2];
Links links_object;
while (true) {
  for (unsigned i = 0; i < 2; i++){
  inputFile>>Temp[i];
}
  for (size_t i(0u); i<10; ++i)
  {
    links_object.add(Node());
  }

  links_object.link_nodes(Temp[0], Temp[1]);
  /*
  links_object.link_nodes(0u, 9u);
  links_object.link_nodes(1u, 2u);
  links_object.link_nodes(1u, 3u);
  links_object.link_nodes(1u, 4u);
  links_object.link_nodes(1u, 5u);
  links_object.link_nodes(1u, 6u);
  links_object.link_nodes(1u, 7u);
  links_object.link_nodes(7u, 8u);
  */
}

  std::vector<size_t> linksum;
  for (auto const & node : links_object.nodes())
  {
    size_t const linksum_index(node.links().size()-1u);
    if (linksum.size() < node.links().size()) 
    {
      size_t const nls(node.links().size());
      for (size_t i(linksum.size()); i<nls; ++i) 
      {
        linksum.push_back(0u);
      }
    }
    for (auto linked : node.links())
    {
      linksum[linksum_index] += linked->links().size();
    }
  }

  for (size_t i(0u); i<linksum.size(); ++i)
  {
    std::cout << "Sum of secondary links with " << i+1;
    std::cout << "-link nodes is: " << linksum[i] << std::endl;
  }
}

更新了我的代码,将“连接”的结果存储在文本文件中并尝试从中获取值。但现在它给了我分段错误。我该如何解决?

4

4 回答 4

0

您可以遍历属于“对”的节点并将它们放入列表中。如果您尝试添加的元素已经在列表中,请不要添加它。(例如 if 语句检查)然后在检查所有元素后检查列表大小,这应该是您的链接。

如果这不是您要问的,请纠正我。

我确信有更好的方法来做到这一点。我相信它的复杂性是 O(n^2) 时间。

于 2013-09-05T17:42:08.177 回答
0

我会使用std::vector<size_t>向量的索引是相应节点类型的链接数。

您遍历所有节点并将与std::vector<size_t>该节点的链接数相对应的 -entry 与链接到当前节点的所有节点的链接数相加。

这段代码:

#include <vector>
#include <stdexcept>

class Node 
{
  std::vector< Node const * > m_links;
public:
  Node(void) { }
  void link_to (Node const &n) 
  { 
    m_links.push_back(&n); 
  }
  std::vector< Node const * > const & links (void) const 
  { 
    return m_links; 
  }
};

class Links
{
  std::vector<Node> m_nodes;
public:
  void add (Node const &node) { m_nodes.push_back(node); }
  void link_nodes (size_t node_a, size_t node_b)
  {
    size_t ns(m_nodes.size());
    if (node_a >= ns || node_b >= ns) 
    {
      throw std::logic_error("Requested invalid link.");
    }
    m_nodes[node_a].link_to(m_nodes[node_b]);
    m_nodes[node_b].link_to(m_nodes[node_a]);
  }
  std::vector<Node> const & nodes (void) const 
  { 
    return m_nodes; 
  }
};

int main (void)
{
  Links links_object;
  for (size_t i(0u); i<10; ++i)
  {
    links_object.add(Node());
  }

  links_object.link_nodes(0u, 1u);
  links_object.link_nodes(0u, 9u);
  links_object.link_nodes(1u, 2u);
  links_object.link_nodes(1u, 3u);
  links_object.link_nodes(1u, 4u);
  links_object.link_nodes(1u, 5u);
  links_object.link_nodes(1u, 6u);
  links_object.link_nodes(1u, 7u);
  links_object.link_nodes(7u, 8u);

  std::vector<size_t> linksum;
  for (auto const & node : links_object.nodes())
  {
    size_t const linksum_index(node.links().size()-1u);
    if (linksum.size() < node.links().size()) 
    {
      size_t const nls(node.links().size());
      for (size_t i(linksum.size()); i<nls; ++i) 
      {
        linksum.push_back(0u);
      }
    }
    for (auto linked : node.links())
    {
      linksum[linksum_index] += linked->links().size();
    }
  }

  for (size_t i(0u); i<linksum.size(); ++i)
  {
    std::cout << "Sum of secondary links with " << i+1;
    std::cout << "-link nodes is: " << linksum[i] << std::endl;
  }
}

印刷:

具有 1 个链路节点的二级链路总和为:39
具有 2 个链路节点的辅助链路总和为:16
具有 3 链路节点的二级链路总和为:0
具有 4 链路节点的二级链路总和为:0
具有 5 个链路节点的二级链路总和为:0
具有 6 个链路节点的二级链路总和为:0
具有 7 个链路节点的二级链路总和为:9

你应该明白了。

于 2013-09-05T18:03:05.357 回答
0

我会使用地图。链接数将是键,其值将是一个向量,其中包含具有该链接数的节点的 ID。

typedef std::map<size_t,std::vector<size_t> SimilarNodeMap;

SimilarNodeMap myMap;

... // fill up the map

for (SimilarNodeMap::iterator it=mymap.begin(); it!=mymap.end(); ++it)
{
  std::cout << "Nodes with " it->first << " links: ";

  for ( size_t i = 0; i < second->size(); ++i )
  {
     std::cout << second->at(i) << std::endl;
  }
}
于 2013-09-05T17:41:23.313 回答
0

您可能会遍历所有节点并计数。伪代码:

std::map<std::size_t, std::size_t> counter;
for each node
    ++counter[node.links().size]
于 2013-09-05T20:14:05.307 回答