Language agnostic C#数据结构算法

Language agnostic C#数据结构算法,language-agnostic,data-structures,sorting,Language Agnostic,Data Structures,Sorting,我最近采访了一家顶级软件公司。面试官只问了我一个问题,那就是 问:我有一台内存为512MB/1GB的机器,我必须对4GB大小的文件(XML或任何文件)进行排序。我将如何进行?数据结构是什么?我将使用哪种排序算法?如何使用 你认为这是可以实现的吗?如果是的话,你能解释一下吗 提前谢谢 在Guido van Rossum上有一篇不错的帖子,里面有一些建议。注意代码是用Python编写的。请使用 以下是伪代码: function sortFile(file) if fileTooBigForM

我最近采访了一家顶级软件公司。面试官只问了我一个问题,那就是

问:我有一台内存为512MB/1GB的机器,我必须对4GB大小的文件(XML或任何文件)进行排序。我将如何进行?数据结构是什么?我将使用哪种排序算法?如何使用

你认为这是可以实现的吗?如果是的话,你能解释一下吗


提前谢谢

在Guido van Rossum上有一篇不错的帖子,里面有一些建议。注意代码是用Python编写的。

请使用

以下是伪代码:

function sortFile(file)
    if fileTooBigForMemory(file)
       pair<firstHalfOfFile, secondHalfOfFile> = breakIntoTwoHalves()
       sortFile(firstHalfOfFile)
       sortFile(secondHalfOfFile)
    else
       sortCharactersInFile(file)
    endif

    MergeTwoHalvesInOrder(firstHalfOfFile, secondHalfOfFile)
end

将文件拆分为适合内存的块。 使用快速排序对每个块进行排序,并将其保存到单独的文件中。
然后合并结果文件,您就可以得到结果。

面试官可能想要的答案可能是您如何有效地对超出系统内存的数据集进行排序。以下部分摘自:

内存使用模式和索引 排序

当数组的大小为 排序接近或超过 可用主内存,以便 (速度慢得多)磁盘或交换空间必须 如果使用,内存使用模式 一种排序算法的实现 很重要,一个可能 当 易于在RAM中安装的阵列可能会 不切实际的在这个场景中 比较的总数变为 (相对)不太重要,以及 内存分区的次数 必须复制或交换到或从 磁盘可以控制性能 算法的特征。因此 通行证的数量和 比较的本地化可以是 比原始数量更重要的是 比较,因为 附近的元素彼此相连 以系统总线速度(或者,使用缓存, 即使在CPU速度下),与 磁盘速度,实际上是 瞬间的

例如,流行的递归 快速排序算法提供了相当好的性能 合理的性能和足够的 RAM,但由于递归方式 它复制阵列的一部分 当 数组不适合RAM,因为它 可能会导致一些慢拷贝或 在磁盘之间移动操作。在里面 在这种情况下,可能会出现另一种算法 即使需要更多,也最好选择 总体比较

解决这个问题的一种方法, 当记录比较复杂时,这种方法很有效 (例如在关系数据库中)是 按相对较小的键排序 字段,用于在 数组,然后对索引进行排序,而不是 而不是整个阵列。(A)分类 然后,可以修改整个阵列的版本 一次通过产生,阅读 从指数来看,但通常情况下甚至是这样 不必要的,如已分类的 索引是足够的。)因为索引 比整个阵列小得多, 它可以很容易地放在内存中 整个阵列不会,有效地 消除了磁盘交换问题。 这个过程有时被称为 “标记排序”。[5]

另一种克服困难的技巧 内存大小的问题是将两个 以一种需要 优势在于每一种力量都能发挥作用 提高整体绩效。对于 实例中,该数组可能是 细分为大小相同的块 将很容易安装在RAM中(例如,几个 千个元素),块被排序 使用有效的算法(例如 快速排序或堆集),以及 结果按照mergesort合并。这 它的效率比仅仅做一件事要低 一开始是合并排序,但它 需要更少的物理RAM(需要 实用)而不是一个完整的快速排序 整个阵列

技术也可以结合起来。对于 对非常大的数据集进行排序 大大超过系统内存,甚至 索引可能需要使用 算法或算法组合 设计用于合理地执行 虚拟内存,即减少 所需的交换量


只需模拟一个虚拟内存,重载数组索引操作符,[]


找到一个快速排序实现,它在C++或C语言中对数组排序。重载索引器运算符[],它将从文件中读取并保存到文件中。这样,您就可以插入现有的排序算法,只需更改这些[]

上的幕后操作,下面是一个在C上模拟虚拟内存的示例#

资料来源:

//indexer.cs
//参数:indexer.txt
使用制度;
使用System.IO;
//类以提供对大型文件的访问
//就像是一个字节数组。
公共类FileByteArray
{
Stream;//保存基础流
//用于访问该文件。
//创建封装特定文件的新FileByteArray。
公共文件字节数组(字符串文件名)
{
stream=新文件流(文件名,FileMode.Open);
}
//关闭流。这应该是最后一件事了
//当你完成的时候。
公众假期结束()
{
stream.Close();
流=空;
}
//索引器提供对文件的读/写访问。
公共字节此[long index]//long是64位整数
{
//在偏移量索引处读取一个字节并返回它。
得到
{
字节[]缓冲区=新字节[1];
Seek(索引,SeekOrigin.Begin);
读取(缓冲区,0,1);
返回缓冲区[0];
}
//在偏移量索引处写入一个字节并返回它。
设置
{
字节[]缓冲区=新字节[1]{value};
Seek(索引,SeekOrigin.Begin);
流写入(缓冲区,0,1);
}
}
//获取文件的总长度。
公共长线
{
得到
{
返回stream.Seek(0,SeekOrigin.End);
}
}
}
//演示FileByteArray类。
//反转文件中的字节。
公共类反向
{
公众的
class File {
    private char[] characters;
    //methods to access and mutate 'characters'
}
// indexer.cs
// arguments: indexer.txt
using System;
using System.IO;

// Class to provide access to a large file
// as if it were a byte array.
public class FileByteArray
{
    Stream stream;      // Holds the underlying stream
                        // used to access the file.
// Create a new FileByteArray encapsulating a particular file.
    public FileByteArray(string fileName)
    {
        stream = new FileStream(fileName, FileMode.Open);
    }

    // Close the stream. This should be the last thing done
    // when you are finished.
    public void Close()
    {
        stream.Close();
        stream = null;
    }

    // Indexer to provide read/write access to the file.
    public byte this[long index]   // long is a 64-bit integer
    {
        // Read one byte at offset index and return it.
        get 
        {
            byte[] buffer = new byte[1];
            stream.Seek(index, SeekOrigin.Begin);
            stream.Read(buffer, 0, 1);
            return buffer[0];
        }
        // Write one byte at offset index and return it.
        set 
        {
            byte[] buffer = new byte[1] {value};
            stream.Seek(index, SeekOrigin.Begin);
            stream.Write(buffer, 0, 1);
        }
    }

    // Get the total length of the file.
    public long Length 
    {
        get 
        {
            return stream.Seek(0, SeekOrigin.End);
        }
    }
}

// Demonstrate the FileByteArray class.
// Reverses the bytes in a file.
public class Reverse 
{
    public static void Main(String[] args) 
    {
        // Check for arguments.
        if (args.Length == 0)
        {
            Console.WriteLine("indexer <filename>");
            return;
        }

        FileByteArray file = new FileByteArray(args[0]);
        long len = file.Length;

        // Swap bytes in the file to reverse it.
        for (long i = 0; i < len / 2; ++i) 
        {
            byte t;

            // Note that indexing the "file" variable invokes the
            // indexer on the FileByteStream class, which reads
            // and writes the bytes in the file.
            t = file[i];
            file[i] = file[len - i - 1];
            file[len - i - 1] = t;
        }

        file.Close();
    } 
}