如何对包裹的数字序列进行排序

时间:2013-06-12 08:51:57

标签: c# algorithm sorting sequence

我有一系列对象,每个对象的序列号从0到ushort.MaxValue(0-65535)。我的序列中最多有大约10 000个项目,因此不应该有任何重复项,并且这些项目主要是根据它们的加载方式进行排序。我只需要按顺序访问数据,我不需要它们在列表中,如果这可以帮助。它也是经常做的事情,所以它不能有太高的Big-O。

对此列表进行排序的最佳方法是什么?

示例序列可以是( 在此示例中, 假设序列号是单个字节并且包装在255处):

240 241 242 243 244 250 251 245 246 248 247 249 252 253 0 1 2 254 255 3 4 5 6

然后

正确的顺序
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 0 1 2 3 4 5 6 

我有一些不同的方法,包括制作一个ushort.MaxValue数组,只是增加位置,但这似乎是一种非常低效的方式,当我收到的数据有一个跳跃序列时我遇到了一些问题。但是,它的性能是O(1)..

另一种方法是正常订购商品,然后找到拆分(6-240),并将第一个商品移到最后。但我不确定这是不是一个好主意。

我的第三个想法是循环序列,直到找到错误的序列号,向前看直到找到正确的序列号,并将其移动到正确的位置。但是,如果早期的序列号错误,这可能会非常慢。

2 个答案:

答案 0 :(得分:1)

这是你在找什么?

var groups = ints.GroupBy(x => x < 255 / 2)
     .OrderByDescending(list => list.ElementAt(0))
     .Select(x => x.OrderBy(u => u))
     .SelectMany(i => i).ToList(); 

示例 在:

int[] ints = new int[] { 88, 89, 90, 91, 92, 0, 1, 2, 3, 92, 93, 94, 95, 96, 97, 4, 5, 6, 7, 8, 99, 100, 9, 10, 11, 12, 13 };

输出:

88 89 90 91 92 92 93 94 95 96 97 99 100 0 1 2 3 4 5 6 7 8 9 10 11 12 13

答案 1 :(得分:1)

我意识到这是一个老问题字节,我也需要这样做,并希望得到答案......

SortedSet<FileData>与自定义比较器一起使用;

其中FileData包含有关您正在使用的文件的信息 e.g。

struct FileData
{
    public ushort SequenceNumber;
    ...
}

internal class Sequencer : IComparer<FileData>
{
    public int Compare(FileData x, FileData y)
    {
        ushort comparer = (ushort)(x.SequenceNumber - y.SequenceNumber);
        if (comparer == 0) return 0;
        if (comparer < ushort.MaxValue / 2) return 1;
        return -1;
    }
}

当您从磁盘读取文件信息时,请将它们添加到SortedSet

当您从SortedSet中读出它们时,它们现在的顺序正确

请注意SortedSet内部使用红黑色,这样可以在性能和内存之间取得很好的平衡

插入是O(log n)
遍历是O(n)