合并2个排序时间序列算法

时间:2012-05-03 14:12:53

标签: c# algorithm sorting collections merge

我有两个包含Bar对象的时间序列,每个Bar对象包含一个long类型的成员变量,每个时间序列都存储在它自己的BlockingCollection中。时间序列按长值的升序排序。

我喜欢设计一个合并算法,它允许我带走包含相对于另一个BlockingCollection中相同比较元素的最低值的长成员变量的Bar。

例如,如果BlockingCollection1中第一个Bar(bar1)中包含的long值低于BlockingCollection2中第一个Bar(bar2)中包含的long值,则BlockingCollection1和Add()中的Take()为MasterBlockingCollection,基本上以Bar对象的合并流结束,并按每个Bar的长成员变量的值排序。

我希望稍后扩展到n BlockingCollections,而不仅仅是2.我使用包含长值的数组来使映射更容易,但我认为在处理与此特定目标算法有关的指针时,数组更加方便。

我想知道是否有人能指出我的Linq实现,并评论这种方法的计算成本如何。我在问,因为吞吐量非常重要,因为有数亿个Bar对象流经集合。如果有人比使用Linq更聪明,那将非常受欢迎。我前段时间在DrDobbs遇到了一些想法重新合并算法,但找不到文章了。如果现在不明显,我的目标是C#(。Net4.0)

非常感谢

编辑:我忘了提到合并过程应该与将新项目添加到blockingcollections(在不同任务上运行)的工作人员同时发生

1 个答案:

答案 0 :(得分:1)

这是Merge的一个实现。它应该在O(cN)时间运行,其中c是集合的数量。这是你在找什么?

    public static BlockingCollection<Bar> Merge(IEnumerable<BlockingCollection<Bar>> collections)
    {
        BlockingCollection<Bar> masterCollection = new BlockingCollection<Bar>();
        LinkedList<BarWrapper> orderedLows = new LinkedList<BarWrapper>();

        foreach (var c in collections)
            OrderedInsert(new BarWrapper { Value = c.Take(), Source = c }, orderedLows);

        while (orderedLows.Any())
        {
            BarWrapper currentLow = orderedLows.First.Value;
            orderedLows.RemoveFirst();

            BlockingCollection<Bar> collection = currentLow.Source;

            if (collection.Any())
                OrderedInsert(new BarWrapper { Value = collection.Take(), Source = collection }, orderedLows);

            masterCollection.Add(currentLow.Value);
        }
        return masterCollection;
    }

    private static void OrderedInsert(BarWrapper bar, LinkedList<BarWrapper> orderedLows)
    {
        if (!orderedLows.Any())
        {
            orderedLows.AddFirst(bar);
            return;
        }

        var iterator = orderedLows.First;
        while (iterator != null && iterator.Value.Value.LongValue < bar.Value.LongValue)
            iterator = iterator.Next;

        if (iterator == null)
            orderedLows.AddLast(bar);
        else
            orderedLows.AddBefore(iterator, bar);
    }

    class BarWrapper
    {
        public Bar Value { get; set; }
        public BlockingCollection<Bar> Source { get; set; }
    }

    class Bar
    {
        public Bar(long l)
        {
            this.LongValue = l;
        }
        public long LongValue { get; set; }
    }