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