我今天正在练习我的编码排序并解决"从链接列表中删除某个值的所有元素"今天的问题。我提出的解决方案是
public void RemoveAll ( T val )
{
if(_root == null)
return;
if(_root.Value == val)
{
_root = _root.Next;
RemoveAll(val);
}
Node last = _root,
cur = _root.Next;
while(cur != null)
{
if(cur.Value == val)
last.Next = cur.Next;
else
last = cur;
cur = cur.Next;
}
}
以及我的问题:
当cur.Value == val
我正在执行更改
A -> B -> C
到
A -> C
编译器或运行时环境是否会看到B
不再使用并将其丢弃?或者我应该明确地这样做吗?
我还有第二个问题,即调用堆栈是否会出现递归void
方法。正如您在此处看到的,该方法可能会调用自身。但由于它是一种不返回值的方法,运行时环境是否只能擦除最后一次调用的数据?它没有理由留在内存中(对吧?)。
答案 0 :(得分:1)
编译器或运行时环境是否会看到B已不再使用并将其丢弃?或者我应该明确地这样做吗?
GC,当它运行时,将意识到没有对该对象的活动引用并清理它(假设没有其他人拥有对该对象的引用)。您无法在.NET中手动清理单个对象。在.NET中,内存由垃圾收集器根据需要进行管理和清理。
我还有第二个问题,即调用堆栈是否会破坏递归void方法。正如您在此处看到的,该方法可能会调用自身。但由于它是一种不返回值的方法,运行时环境是否只能擦除有关上次调用的数据?它没有理由留在内存中(对吧?)。
您正在描述tail recursion. C#编译器不会生成尾递归调用。如果你的递归太深,那么你可能会遇到StackOverflowException
。[/ p>
该限制不是CLR限制 - .NET Framework确实支持尾调用。它是C#编译器,不会发出尾部IL操作码。当手动生成IL或使用F#时,您可以在.NET Framework中使用Tail Recursion,它会在适当的时候生成尾调用。
有关详细信息,请参阅https://stackoverflow.com/a/15865150/1163867。
PS。我认为您的代码有错误。看起来你应该在递归调用RemoveAll
后提前返回:
if(_root.Value == val)
{
_root = _root.Next;
RemoveAll(val);
return;
}