用于将一组随机整数从输入文件分发到N个输出(桶)文件的算法

时间:2017-03-09 13:11:53

标签: java algorithm sorting

我正在尝试改进我的算法,该算法将输入数据从单个输入文件分发到N个输出文件。输入数据按以下方式分发:

例如,如果输入文件包含值5 2 4 6 3 1 0 8 5 9并且我有N = 4个输出文件,则值的分布如下:

  • file_0:2 1 0
  • file_1:5 4 3 5
  • file_2:6 8
  • file_3:9

所以每个值都应该"映射"到[0,N-1]范围内的适当文件。稍后将对每个文件进行排序,您可以看到它们的串联将生成输入值的排序顺序。

所有输出文件路径都存储在名为bucket_files的File数组中,我在这里要做的是使用某种散列函数H(input_value)将input_value映射到[0,N]范围内的数组索引-1]。

到目前为止我所拥有的是

private static void distributeData(int N, File main_string_file) {
    int min = 1;
    int max = 9;
    long left_interval_border;
    long right_interval_border;

    int input_buff_size = 8;
    File bucket_files[] = new File[N];
    int input_buffer[] = new int[input_buff_size / 2];
    BufferedWriter bucket_file_writers[] = new BufferedWriter[N];
    BufferedReader main_file_reader = new BufferedReader(new FileReader(main_string_file));

    left_interval_border = min;
    long range = (int) Math.ceil(max / N);
    right_interval_border = range;

    for (int i = 0; i < N; i++) {
        bucket_files[i] = new File("/path/to/files/file_" + i + ".txt");
        bucket_file_writers[i] = new BufferedWriter(new FileWriter(bucket_files[i], true));
    }

    try {
        while (main_file_reader.ready()) {
            for (int i = 0; i < input_buffer.length; i++) {
                input_buffer[i] = Integer.parseInt(main_file_reader.readLine());
            }

            for (int i = 1; i <= N; i++) {
                for (int j = 0; j < input_buffer.length; j++) {
                    if (input_buffer[j] >= left_interval_border && input_buffer[j] <= right_interval_border) {
                        bucket_file_writers[i - 1].write(Integer.toString(input_buffer[j]));
                        bucket_file_writers[i - 1].write(System.getProperty("line.separator"));
                    }
                }

                left_interval_border = right_interval_border + 1;
                right_interval_border = left_interval_border + range;
            }

            left_interval_border = min;
            right_interval_border = range;
        }
    }

    catch (EOFException eofe) {
        System.out.println("Reached end of file!");
    }
}

这种方法是我提出的第一种方法,它非常慢并且如果输入文件会更大并且任何一种更好的解决方案都是非常受欢迎的话将无法正常工作:)这个双循环是一个瓶子脖子,我想改变成更好更快的东西。

谢谢!

注释

  • 所有文件都是.txt文件,每个值都用新行分隔
  • N至少为2且达到合理数量,让我们说200 max
  • main_string_file会更大,并且包含0到Integer.MAX_VALUE-1
  • 范围内的随机值
  • min和max预先设置(0和Integer.MAX_VALUE-1),这意味着文件中没有特殊的min和max特殊搜索

2 个答案:

答案 0 :(得分:1)

您可以使用println并计算要写入的文件。

{{1}}

答案 1 :(得分:1)

根据你说你想要分解桶的方式,你的桶大小由range/(numBuckets-1)计算。除了范围均匀分配桶数的情况。所以你拥有的是:

int bucketSize;
if (range % bucketSize == 0)
    bucketSize = range / numBuckets;
else
    bucketSize = range / (numBuckets-1);

一旦你知道了桶的数量和项目的范围,那就是一次性计算。

然后,您可以使用简单的除法计算每个项目的存储桶。如果项目为i,则:

int bucket = i/bucketSize;