## 趣味编程：函数式链表的快速排序（参考答案）

2009-09-02 10:58  Jeffrey Zhao  阅读(5006)  评论(20编辑  收藏  举报

ImmutableList结构的定义如下：

public abstract class ImmutableList<T> : IEnumerable<T>
{
public abstract T Head { get; }

public abstract ImmutableList<T> Tail { get; }

public abstract bool IsEmpty { get; }

#region IEnumerable<T> Members

public IEnumerator<T> GetEnumerator()
{
var current = this;
while (!current.IsEmpty)
{
current = current.Tail;
}
}

#endregion

#region IEnumerable Members

IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}

#endregion
}


public abstract class ImmutableList<T> : IEnumerable<T>
{
public static readonly ImmutableList<T> Empty = new EmptyImmutableList<T>();

...
}

internal sealed class EmptyImmutableList<T> : ImmutableList<T>
{
public EmptyImmutableList() { }

{
get
{
throw new InvalidOperationException("an empty list has no head.");
}
}

public override ImmutableList<T> Tail
{
get
{
throw new InvalidOperationException("an empty list has no tail.");
}
}

public override bool IsEmpty { get { return true; } }
}

internal class NonEmptyImmutableList<T> : ImmutableList<T>
{
{
this.m_tail = tail;
}

private ImmutableList<T> m_tail;
public override ImmutableList<T> Tail { get { return this.m_tail; } }

public override bool IsEmpty { get { return false; } }
}

public abstract class ImmutableList<T> : IEnumerable<T>
{
public static readonly ImmutableList<T> Empty = new EmptyImmutableList<T>();

public static ImmutableList<T> Create(T element)
{
return new NonEmptyImmutableList<T>(element, Empty);
}
}


public static ImmutableList<T> operator +(ImmutableList<T> headList, ImmutableList<T> tailList)
{
if (tailList == null) throw new ArgumentNullException("tailList");

...
}


1 -> 2 -> 3
↖ list1
4 -> 5 -> 6
↖ list2

1 -> 2 -> 3
↖ list1
1 -> 2 -> 3 -> 4 -> 5 -> 6
↖ result      ↖ list2

public abstract class ImmutableList<T> : IEnumerable<T>
{
...

public static ImmutableList<T> Create(params T[] elements)
{
if (elements == null) throw new ArgumentNullException("elements");

return Create(elements, Empty);
}

public static ImmutableList<T> Create(IEnumerable<T> elements)
{
if (elements == null) throw new ArgumentNullException("elements");

return Create(elements, Empty);
}

private static ImmutableList<T> Create(IEnumerable<T> elements, ImmutableList<T> tail)
{
}

public static ImmutableList<T> operator +(ImmutableList<T> headList, ImmutableList<T> tailList)
{
...

}

...
}

internal class NonEmptyImmutableList<T> : ImmutableList<T>
{
public static ImmutableList<T> FromEnumerable(IEnumerable<T> elements, ImmutableList<T> tail)
{
NonEmptyImmutableList<T> result = null, last = null;

foreach (var item in elements)
{
var newNode = new NonEmptyImmutableList<T>(item, Empty);
if (last == null)
{
result = last = newNode;
}
else
{
last.m_tail = newNode;
last = newNode;
}
}

if (last != null)
{
last.m_tail = tail;
}

return result ?? tail;
}

...
}


ImmutableList的连接操作实现完成后，我们便可以为其添加一些额外的辅助方法了。如Filter：

public static class ImmutableListExtensions
{
public static ImmutableList<T> Filter<T>(this ImmutableList<T> source, Func<T, bool> predicate)
{
if (source == null) throw new ArgumentNullException("source");
if (predicate == null) throw new ArgumentNullException("predicate");

if (source.IsEmpty) return source;
return ImmutableList<T>.Create(source.Where(predicate));
}

...
}


public static class ImmutableListExtensions
{
...

public static ImmutableList<T> QuickSort<T>(this ImmutableList<T> list, Func<T, T, int> compare)
{
if (list == null) throw new ArgumentNullException("list");
if (compare == null) throw new ArgumentNullException("compare");

return list.IsEmpty ? list :
list.Tail.Filter(e => compare(e, list.Head) < 0).QuickSort(compare) +
list.Tail.Filter(e => compare(e, list.Head) >= 0).QuickSort(compare);
}
}


qsort [] = []
qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++ qsort (filter (>= x) xs)

var random = new Random();
var source = new List<int>();
for (int i = 0; i < 10; i++) source.Add(random.Next());

var sourceList = ImmutableList<int>.Create(source);
var sortedList = sourceList.QuickSort((x, y) => x - y);

foreach (var i in sourceList) Console.WriteLine(i);
Console.WriteLine();
foreach (var i in sortedList) Console.WriteLine(i);


• ImmutableList的快速排序已经完成了，那么您是否可以尝试着进行归并排序（Merge Sort）？
• 能否模拟ImmutableList构造一个ImmutableStack？我不是指“封装ImmutableList”，而是直接编写一个ImmutableStack，需要实现Pop，Push和Peek三种操作。