对大量相同长度的字符串进行排序

时间:2011-03-06 10:55:33

标签: c# algorithm sorting

我有一个很大的字符串序列。每个字符串的长度为50.每个字符串仅包含来自英语ABC的字符。排序这个序列的最佳(最快)方法是什么?

5 个答案:

答案 0 :(得分:3)

如果我必须对其进行编码,我可能会进行一次传递,将输入分成许多输出文件,具体取决于前几个字符;目标是使每个输出文件足够小以适应主存储器。然后我将按顺序打开每个文件,在内存中对其进行排序,然后将其附加到输出中。第一遍是O(n),第二遍是或多或少O(n log n),你必须每个记录做四次磁盘I / O.使用一些神秘的算法可能会做得更好,但可能不是很多,这很容易理解和编码。

如果系统限制您可以一次打开多少个文件,则可能需要拆分第一个传递。如果字符串分布不均匀,则某些中间文件可能太大。

在伪代码中:

open input file (r)
for i in ['aa', 'ab', 'ac', ..., 'zz']:
    open output file[i] (w)
for record in input file:
    write record to output file[record[0:2]]
close all files
open main output file (w)
for i in ['aa', 'ab', 'ac', ..., 'zz']:
    open input file[i] (r)
    slurp whole file into memory
    close input file
    sort data
    append whole sorted file to main output file
编辑:等等,你的意思是记录只包含字符A,B和C吗?没有其他信件?在这种情况下,您可能必须拆分一个长于2的初始子字符串。拆分前3个字符会将其分成27个文件,每个文件大小平均为370 MB。

答案 1 :(得分:2)

这样的东西?

List<string> list = new List<string>();
/* fill the list */
list.Sort();

Sort()方法具有不同的重载,允许您自定义字符串比较的执行方式。

编辑哦,“大”你的意思是500GB的字符串然后这可能不会削减它。

答案 2 :(得分:2)

您正在寻找的算法可能是合并排序

http://en.wikipedia.org/wiki/Merge_sort

和这个

http://en.wikipedia.org/wiki/External_sorting

但在您的具体情况下,请阅读:

Need a way to sort a 100 GB log file by date

它可能适合你!

答案 3 :(得分:2)

由于500 MB不是很多数据,您可以简单地将整个文件加载到内存中,对其进行排序,然后将结果写回磁盘。

我假设文件内容的布局如下:

ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWX\r\n
ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWX\r\n
    :
    :
ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWX\r\n

代码:

// Load
var data = File.ReadAllBytes("file.txt");
var itemCount = data.Length / 52;
var indexes = new int[itemCount];
for (int i = 0; i < itemCount; i++)
{
    indexes[i] = i;
}

// Sort
Array.Sort<int>(indexes, (x, y) =>
{
    for (int i = 0; i < 50; i++)
    {
        if (data[x * 52 + i] > data[y * 52 + i]) return 1;
        if (data[x * 52 + i] < data[y * 52 + i]) return -1;
    }
    return 0;
});

// Store
using (var stream = new Stream("result.txt"))
{
    for (int i = 0; i < itemCount; i++)
    {
        stream.Write(data, indexes[i] * 52, 52);
    }
}

答案 4 :(得分:0)

Quicksort(如果使用正确)可以非常有效地排序字符串。

诀窍是修改分区方法。主要思想是在每个分区步骤中,特定分区中的键具有相同的前缀。再次分区时,您不需要比较密钥的前缀。

实施例: 让我们说输入是{"hello", "world", "house", "homly" },第一个分区是关键的“世界”

你得到:{"hello", "house", "homly"}, {"world"}

如果你想重新分配第一组,你不必比较字符串的第一个字符,因为你已经知道第一个字符在所有字符串中都是相同的!

一般情况下,集合中公共前缀的长度是分区到达集合的次数。

如果您有兴趣深入了解,请阅读Fast Algorithms for sorting and searching strings