简体   繁体   English

关于将项目添加到自定义数据类型列表的问题

[英]Question about adding items to a list of a custom datatype

I have a simple node class.我有一个简单的节点 class。 Now I want to add all the adjacent neighbors to every node in a list I have, but for some reason it just adds the first adjacent node of the neighborhood.现在我想将所有相邻的邻居添加到我拥有的列表中的每个节点,但由于某种原因,它只是添加了邻域的第一个相邻节点。 In the below code "edges" is a datatree( basically a dictionary-> int,List) where every consists of to integers representing a node.在下面的代码中,“edges”是一个数据树(基本上是一个字典-> int,List),其中每个都由表示一个节点的整数组成。 Maybe someone could explain me why It just adds one value to the list of every node, I would be really grateful!也许有人可以解释我为什么它只是为每个节点的列表添加一个值,我将非常感激!

The node class节点 class

public class Node
{
  //Properties
  public int name;
  public List<Node> AdjN;
  
  // constructor that takes the current node and initializes the adjList
  public Node(int _node)
  {
    name = _node;
    AdjN = new List<Node>();
  }
}

The main code:主要代码:

   var nodes = new List<Node>();   
    for (int i = 0; i < edges.BranchCount; i++) // edges is a datatree which is basically a dictionary (int,List<int>
    {
      Node n1 = new Node(edges.Branch(i)[0]);// this int is the first node of the current edge
      Node n2 = new Node(edges.Branch(i)[1]);/ this int is the second node of the current edge
      
      nodes.Add(n1);
      nodes.Add(n2);
      n1.AdjN.Add(n2); 
      n2.AdjN.Add(n1);     
    }
 
    
    var neighbors = new List<int>();
    for (int i = 0; i < nodes[0].AdjN.Count; i++)
      neighbors.Add(nodes[0].AdjN[i].name);

Thanks everybody for looking at this!谢谢大家看这个!

Try following:尝试以下操作:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Dictionary<int, List<int>> edges = new Dictionary<int,List<int>>() {
                { 0, new List<int>(){100,200}},
                { 1, new List<int>(){300,400}},
                { 2, new List<int>(){500,600}},
                { 3, new List<int>(){700,800}}
            };

            var nodes = new List<Node>();   
            for (int i = 0; i < edges.Count; i++) // edges is a datatree which is basically a dictionary (int,List<int>
            {
              Node n1 = new Node(edges[i][0]);// this int is the first node of the current edge
              Node n2 = new Node(edges[i][1]);// this int is the second node of the current edge
      
              nodes.Add(n1);
              nodes.Add(n2);
              n1.AdjN.Add(n2); 
              n2.AdjN.Add(n1);     
            }
 
    
            var neighbors = new List<int>();
            for (int i = 0; i < nodes[0].AdjN.Count; i++)
              neighbors.Add(nodes[0].AdjN[i].name);
  
        }
    }
    public class Node
    {
        //Properties
        public int name;
        public List<Node> AdjN;

        // constructor that takes the current node and initializes the adjList
        public Node(int _node)
        {
            name = _node;
            AdjN = new List<Node>();
        }
    }
}

The problem with your current implementation is that a node will appear in your list multiple times if it is connected to multiple edges, each time with one neighbor.您当前实现的问题是,如果一个节点连接到多个边,则该节点将多次出现在您的列表中,每次都有一个邻居。 It should instead appear in your list only once, with one neighbor per edge.相反,它应该只出现在您的列表中一次,每条边有一个邻居。 Here's an example graph:这是一个示例图:

B -- A -- C

Currently, you process it as follows:目前,您按如下方式处理它:

  1. Add nodes B & A to the list, each listing the other as a neighbor:将节点 B 和 A 添加到列表中,每个节点都将另一个节点列为邻居:
    • B, neighbors: A B、邻居:A
    • A, neighbors: B A、邻居:B
  2. Add nodes A (again) & C to the list, each listing the other as a neighbor.将节点 A(再次)和 C 添加到列表中,每个都将另一个列为邻居。
    • B, neighbors: A B、邻居:A
    • A, neighbors: B A、邻居:B
    • A, neighbors: C A、邻居:C
    • C, neighbors: A C,邻居:A

Node A appears twice in your list, once listing B as a neighbor and once listing C.节点 A 在您的列表中出现两次,一次将 B 列为邻居,一次将 C 列为。 The second loop iteration ought to notice that A is already in the list, and add C as another neighbor.第二次循环迭代应该注意到 A 已经在列表中,并添加 C 作为另一个邻居。

But the only way to see whether A is already in your List is to traverse the entire thing, which is not efficient when the number of nodes is large.但是查看A是否已经在你的List中的唯一方法是遍历整个东西,当节点数量很大时效率不高。

Try changing your nodes variable from a List<Node> data structure to a Dictionary<int,Node> , where the key is the node identifier and the value is the complete node.尝试将nodes变量从List<Node>数据结构更改为Dictionary<int,Node> ,其中键是节点标识符,值是完整节点。 On each iteration through the loop, you can check for the existence of n1 and n2 in your dictionary in O(1) time, and add them to the dictionary only if they aren't yet present.在循环的每次迭代中,您可以在 O(1) 时间内检查字典中是否存在n1n2 ,并且仅当它们不存在时才将它们添加到字典中。

Don't forget that if you find the node identifier in your Dictionary , you need to update the neighbor list for the object in your dictionary, not the object you created and just happens to have the same identifier.不要忘记,如果您在Dictionary中找到节点标识符,则需要更新字典中 object 的邻居列表,而不是您创建的 object 的邻居列表,并且恰好具有相同的标识符。

The algorithm should look something like this:该算法应如下所示:

For each edge
    For j = 0 to 1
        id[j] = node[j] attached to the edge
        if id[j] is in the dictionary
            set n[j] = value from dictionary
        else
            set n[j] = new Node(id[j])
            add n[j] to the dictionary

    add n[1] as neighbor to n[0]
    add n[0] as neighbor to n[1]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM