인터뷰에서 내게 가장 흥미로운 코딩 과제 중 하나는 기능적 대기열을 만드는 것이 었습니다. 각 대기열에 대기 할 때마다 기존 대기열과 꼬리에 새 항목이 포함 된 새 대기열이 작성되어야합니다. 대기열에서 제외하면 새 대기열과 대기열에서 제외 된 항목이 출력 매개 변수로 반환됩니다.
이 구현에서 IEnumerator를 작성하는 것은 비파괴 적입니다. 또한 성능이 우수한 기능적 대기열을 구현하는 것이 성능이 뛰어난 기능적 스택을 구현하는 것보다 훨씬 어렵다고 가정합니다.
내 요점은 ... 자신 만의 포인터 메커니즘 (StackNode <T>)을 구현하고 열거 자에서 기능적 의미론을 사용하여 비파괴 적 스택 열거자를 만드는 것은 쉽지 않습니다.
public class Stack<T> implements IEnumerator<T>
{
private class StackNode<T>
{
private readonly T _data;
private readonly StackNode<T> _next;
public StackNode(T data, StackNode<T> next)
{
_data=data;
_next=next;
}
public <T> Data{get {return _data;}}
public StackNode<T> Next{get {return _Next;}}
}
private StackNode<T> _head;
public void Push(T item)
{
_head =new StackNode<T>(item,_head);
}
public T Pop()
{
//Add in handling for a null head (i.e. fresh stack)
var temp=_head.Data;
_head=_head.Next;
return temp;
}
///Here's the fun part
public IEnumerator<T> GetEnumerator()
{
//make a copy.
var current=_head;
while(current!=null)
{
yield return current.Data;
current=_head.Next;
}
}
}
몇 가지 참고할 사항. 명령문 current = _head 전에 푸시 또는 팝 호출. completes는 멀티 스레딩이없는 경우와는 다른 열거 형 스택을 제공합니다 (이를 방지하기 위해 ReaderWriterLock을 사용할 수 있습니다). StackNode에서 필드를 읽기 전용으로 만들었지 만 물론 T가 변경 가능한 객체이면 해당 값을 변경할 수 있습니다. StackNode를 매개 변수로 사용하는 스택 생성자를 만들고 노드에 전달 된 것으로 헤드를 설정하는 경우. 이런 식으로 구성된 두 스택은 서로 영향을 미치지 않습니다 (앞서 언급 한 변경 가능한 T 제외). 한 스택에서 원하는 것을 푸시하고 팝할 수 있으며 다른 스택은 변경되지 않습니다.
그리고 내 친구는 스택을 비파괴 적으로 열거하는 방법입니다.