生成嵌套在字典中的2D数字数组

时间:2018-09-20 21:53:05

标签: c# arrays dictionary tree nested

我有一本字典,其中包含一些数字键。每个键都有一组值,这些值包含特定键内“嵌套”的数字(此数据已从数据库中提取)。

一些例子:

  • 825内部有838个,在838内是2941,在2941内是556。因此有4个嵌套级别。

  • 825中有27个,这只是一个嵌套级别。

  • 23嵌套在838个内部(2个嵌套级别),但23个嵌套的内部有66个,因此3个嵌套级别。

示例结构:

dictionary {
    825 : [838, 27],
    838 : [2941, 23],
    2941 : [556, 612],
    23 : [66]
}

我已经编写了一些代码,可以将数字嵌套在其他数字中,因为其中一项要求是获取嵌套的深度。

// example: call function with key: 825
public int getDepth(int number, Dictionary<int, List<int>> nestedNumbers, int depth)
{
    // 825 is in nestedNumbers
    if (nestedNumbers.Keys.Contains(number))
    {
        // foreach number in 825 [838, 27]
        foreach (var currentNumber in nestedNumbers[number])
        {
            // depth is now level 2
            depth++;
            // call the function again but with 838, which will now get nested groups in 838 [2941, 23]
            return getDepth(currentNumber, nestedNumbers, depth);
        }
    }
    return depth;
}

我需要制作一个包含所有嵌套级别的列表(或数组列表)列表,如下所示:

lvl1  lvl2  lvl3  lvl4
[[825, 838, 2941, 556],
[825, 27],   
[825, 838, 23, 66],
[825, 838, 2941, 612]]  <-- e.g. 612 is in 2941, 2941 is in 838, 838 is in 825

但是我不确定如何根据已经编写的功能进行操作。有谁知道我如何实现这一目标?

1 个答案:

答案 0 :(得分:0)

这是一个tree traversal问题。在tree术语中,我们希望从树的根部到叶子或没有子节点的所有路径。这是您的树的可视化图像:

       825
      /   \
     838   27
    /  \
  2941  23 
  /  \   \
556  612  66

可以使用stackqueue数据结构(递归基于堆栈)来执行遍历。在本示例中,我选择使用队列。

遍历部分包括使当前节点的子节点入队,并使用字典来跟踪每个子节点的父节点,然后逐个对子节点进行出队并重复此过程,直到到达叶节点为止。一旦发现了这样的节点,就可以通过返回树直到到达根,然后将该路径添加到结果列表中来构建返回根的路径。

using System;
using System.Collections.Generic;

class MainClass {
    public static void Main(string[] args) {
        Dictionary<int, List<int>> tree = new Dictionary<int, List<int>>()
        {
            {825, new List<int> {838, 27}},
            {838, new List<int> {2941, 23}},
            {2941, new List<int> {556, 612}},
            {23, new List<int> {66}},
        };

        foreach (var row in FindPathsToLeaves(825, tree))
        {
            foreach (var cell in row) 
            {
                Console.Write(cell + " ");
            }

            Console.WriteLine();
        }
    }

    static List<List<int>> FindPathsToLeaves(int root, Dictionary<int, List<int>> tree)
    {
        List<List<int>> paths = new List<List<int>>();
        Dictionary<int, int> parent = new Dictionary<int, int>();
        parent[root] = -1;
        Queue<int> q = new Queue<int>();
        q.Enqueue(root);

        while (q.Count > 0) 
        {
            int current = q.Dequeue();

            if (tree.ContainsKey(current))
            {
                foreach (int n in tree[current])
                {
                    parent[n] = current;
                    q.Enqueue(n);
                }
            } 
            else
            {
                List<int> path = new List<int>();

                while (parent.ContainsKey(current))
                {
                    path.Insert(0, current);
                    current = parent[current];
                }

                paths.Add(path);
            }
        }

        return paths;
    }
}

输出:

825 27 
825 838 2941 556 
825 838 2941 612 
825 838 23 66 

这里是repl的测试对象。<​​/ p>