Создание списков из словаря

1

У меня есть словарь, который для каждого ключа перечисляет его зависимости:

parent[2] = 1 (2 depends on 1)
parent[3] = 1 (3 depends on 1)
parent[4] = {2,3} (4 depends on 2, or 4 depends on 3)

Я хочу создать списки из этого словаря:

[4,2,1]
[4,3,1]

У меня есть подозрение, что я должен использовать рекурсивный алгоритм. Любые намеки?

EDIT: это то, что я до сих пор:

Как я называю рекурсивную функцию:

var result = new List<List<Node<TData, TId>>>();
GetResult(parent, target, result);
return result;

И сама рекурсивная функция:

private static List<Node<TData, TId>> GetResult<TData, TId>(Dictionary<Node<TData, TId>, List<Node<TData, TId>>> parent, Node<TData, TId> index,
    List<List<Node<TData, TId>>> finalList)
    where TData : IIdentifiable<TId>
    where TId : IComparable
{
    var newResult = new List<Node<TData, TId>> { index };

    if (parent.ContainsKey(index))
    {
        if (parent[index].Count == 1)
        {
            return new List<Node<TData, TId>> { index, parent[index].First()};
        }

        foreach (var child in parent[index])
        {
            var temp = newResult.Union(GetResult(parent, child, finalList)).ToList();
            finalList.Add(temp);
        }
    }

    return newResult;
}
  • 0
    Да, это должна быть рекурсия. С какой проблемой вы столкнулись?
  • 0
    Вы почти ищете топологический алгоритм сортировки . Почти , потому что ваш список означает OR вместо AND. Есть ли вероятность того, что А зависит от В и С ?
Показать ещё 1 комментарий
Теги:
algorithm
graph

2 ответа

1
Лучший ответ

Вы можете попробовать адаптировать для своих нужд следующий код:

public static List<List<int>> FindParents(Dictionary<int, List<int>> parents, int index)
{
    List<int> prefix = new List<int>();
    List<List<int>> results = new List<List<int>>();
    FindParentsInternal(parents, index, prefix, results);
    return results;
}

private static void FindParentsInternal(Dictionary<int, List<int>> parents, int index,
    List<int> prefix, List<List<int>> results)
{
    var newPrefix = new List<int>(prefix) { index };
    if (!parents.ContainsKey(index))
    {
        results.Add(newPrefix);
        return;
    }
    parents[index].ForEach(i => FindParentsInternal(parents, i, newPrefix, results));
}

Применение:

Dictionary<int, List<int>> parents = new Dictionary<int, List<int>>
    {
        { 2, new List<int> { 1 } },
        { 3, new List<int> { 1 } },
        { 4, new List<int> { 2, 3 } }
    };

var t = FindParents(parents, 4);
  • 0
    Я попробую это, спасибо!
  • 0
    Каков результат вашей попытки? Мне любопытно.
Показать ещё 3 комментария
0

Вы можете выиграть, сохранив словарь результатов - таким образом вам не нужно будет пересматривать их.

Dictionary<Int, Set<Int>> results;

Set<Int> getResult(int index) {
  Set<Int> dictResult = results.get(index);
  if(dictResult != null) {
    // result has already been computed
    return dictResult;
  } else {
    // compute result, store in dictResult
    Set<Int> newResult = // compute dependency set
    dictResult.put(index, newResult);
    return newResult;
  }
}

Что касается части //compute dependency list, вы можете сделать что-то вроде следующего:

Set<Int> newResult = new Set(index);
if(dict.containsKey(index)) {
  List<Int> dependencies = dict.get(index);
  foreach(int subIndex in dependencies) {
    newResult = newResult.union(getResult(subIndex));
  }
}

Ваш базовый регистр - это когда индекс не находится в dict (т. dict.containsKey возвращает false), например 1 для данных, которые вы предоставили.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню