Генерация неизменяемых циклических структур данных - PullRequest
7 голосов
/ 24 октября 2010

Предположим, у меня есть простой класс:

public class Pair {
    public readonly object first;
    public readonly object second;

    public Pair(object first, object second) {
        this.first = first;
        this.second = second;
    }
}

Невозможно сгенерировать циклический граф пар.

Как бы вы создали подобный класс, который все еще неизменен,но можно ли как-то использовать для генерации циклических графов?

Ответы [ 3 ]

3 голосов
/ 24 октября 2010

Есть миллионы способов представления графовых структур.Одним из таких способов является матрица.каждая строка и столбец индексируются вершиной, а каждая ячейка в матрице представляет направленное (возможно, взвешенное) ребро.Простой циклический граф с нулевыми значениями как без соединительного ребра и 1 с соединительным ребром будет выглядеть так:

| 0 1 |
| 1 0 |

Как и во многих неизменяемых структурах, вы создаете их путем возвращения новых структур на основена желаемое соотношение данных матриц.например, если мы хотим взять вышеприведенный граф и добавить ребро в первой вершине обратно на себя, матрица, представляющая это просто.

| 1 0 |
| 0 0 |

и объединить это с другой матрицей, мы простосложите их вместе.

| 0 1 |  +  | 1 0 |  ==  | 1 1 |
| 1 0 |     | 0 0 |      | 1 0 |

Конечно, существует множество способов представления матриц с различными компромиссами для скорости, пространства и некоторых других операций, но это другой вопрос.

0 голосов
/ 10 апреля 2011

Я бы выбрал функциональный подход, передавая продолжение в ctor. С другой стороны, вместо этого может потребоваться последовательность похожих элементов (в качестве аргумента используйте IEnumerable).

0 голосов
/ 24 октября 2010

Я не думаю, что это возможно для строго неизменяемого класса того типа, который вы предложили. Единственное, о чем я могу думать, это добавить свойство с помощью установщика, который проверяет, является ли поле пустым или нет, и позволяет установить его, если оно есть. Таким образом, вы можете оставить поле first в первом объекте null, и после создания последнего объекта в цикле установите это поле соответствующим образом, чтобы закрыть цикл. Как только оно установлено, оно больше не равно нулю, и установщик больше не позволяет его изменять. Конечно, все еще было бы возможно изменить поле с помощью внутреннего кода класса, но это было бы по существу неизменным извне.

Примерно так (C #):

public class Pair {
    private object first;
    private object second;

    public Pair(object first, object second) {
        this.first = first;
        this.second = second;
    }

    public object First {
        get { return first; }
        set 
        {
            if (first == null)
            {
                first = value;
            }
        }
    }

    // and a similar property for second
}
...