Я делаю программу, которая распечатывает все узлы в дереве Коллатца в C #.
Это занимает много памяти, и outOfMemoryExceptions стали словом дня. База программы выглядит следующим образом:
var fileStream = File.Create("collatz.txt"); //just print into a textfile for testing
var writer = new StreamWriter(fileStream);
IEnumerable<Node> nodeList = new List<Node>()
{
new Node(1, null) //rootNode
};
Task flushTask = Task.CompletedTask;
while (nodeList.Any())
{
var tempList = CalcChildren(nodeList); //Return a IEnumerable of children of all the parents in the nodeList
await flushTask;
foreach (var node in tempList)
writer.WriteLine($"{node.Value} -> {node.Parent.Value}: {node.StepsFromRoot}");
flushTask = writer.FlushAsync();
nodeList = tempList;
}
writer.Close();
static IEnumerable<Node> CalcChildren(IEnumerable<Node> parents)
{
foreach(var parent in parents)
foreach (var child in CalcChildren(parent))
yield return child;
}
static IEnumerable<Node> CalcChildren(Node parent)
{
var multiValue = parent.CalcMultiplicationValue();
if (multiValue.HasValue)
{
var child = new Node(multiValue.Value, parent);
parent.MultiplicationChild = child;
yield return child;
}
var divValue = parent.CalcDivisionValue();
if (divValue.HasValue && divValue.Value!=1)
{
var child = new Node(divValue.Value, parent);
parent.DivisionChild = child;
yield return child;
}
}
Я думаю, что здесь кроется проблема, но ради полноты, класс Node:
public class Node
{
public Node(int value, Node parent)
{
Value = value;
Parent = parent;
if (parent != null)
StepsFromRoot = parent.StepsFromRoot+1;
else
StepsFromRoot = 0;
}
public int Value { get; }
public Node Parent { get; set; }
public Node DivisionChild { get; set; }
public Node MultiplicationChild { get; set; }
public int StepsFromRoot { get; set; }
public int? CalcMultiplicationValue()
{
if(Value<=int.MaxValue/2)
return 2 * Value;
return null;
}
public int? CalcDivisionValue()
{
double newValue = (Value - 1) / 3.0;
if (newValue % 2 == 1 && newValue >= 1)
return (int)newValue;
return null;
}
}
Я стараюсь изо всех сил отбросить как можно больше памяти, но, похоже, это не работает. На 105-й итерации эта программа занимает 4 ГБ памяти! Сначала я подумал, что это потому, что буфер моего писателя занимал всю память. Теперь я думаю, что это потому, что сборка узлов не очищается сборщиком мусора.
Я пытался сделать его более минимальным. Но я не уверен, что удалить, сохраняя его полным. Заранее спасибо!