大规模数据排序,对一亿个int型整数排序,大规模数字在有限内存上排序,外部排序

文章详细阐述了如何通过划分、内存排序、归并步骤对一亿整数进行排序,以及提供了C++代码实现
摘要由CSDN通过智能技术生成

对一亿个整数排序的解决方案

概述

外部排序是一种用于处理大型数据集合的排序算法,由于内存限制,无法将整个数据集放入内存中进行排序。因此,外部排序使用磁盘或其他外部存储介质来存储和处理数据

问题

当需要对大规模数据进行排序时,传统的排序算法(如快速排序、归并排序等)往往无法直接应用,因为它们要求所有数据同时存在于内存中。这种情况下,需要采用外部排序算法来解决这一问题。

思路

外部排序通常涉及以下几个步骤:

划分阶段: 数据被分割成适当大小的块,每个块可以容纳在内存中进行排序。
排序阶段: 每个块在内存中进行排序,常用的排序算法如快速排序、堆排序等。
归并阶段: 将所有的块归并到一个文件中。
具体解决方案
  1. 切分大文件至多个小文件
  2. 对每个小文件进行单独排序
  3. 维护一个优先队列,优先队列的大小为文件数目。
  4. 将每个小文件的第一个数字和该数字的来源放入优先队列中。
  5. 将优先队列中的堆顶弹出,堆顶数字即当前最小值,再从数字来源中读入一个新的数字进入优先队列。
  6. 关闭文件,删除临时文件
代码实现
#include <algorithm>
#include <fstream>
#include <iostream>
#include <iterator>
#include <queue>
#include <random>
#include <sstream>
#include <string>
#include <vector>

void generateRandomNumbers(const std::string &filename, int count)
{
  std::ofstream file(filename);

  if (!file.is_open()) {
    std::cerr << "Unable to open file: " << filename << std::endl;
    return;
  }

  std::random_device rd;
  std::mt19937 generator(rd());
  std::uniform_int_distribution<int> distribution(1, count);

  for (int i = 0; i < count; ++i) {
    file << distribution(generator) << std::endl;
  }

  file.close();
}

void splitFile(const std::string &inputFile, const std::string &outputFilePrefix, int chunkSize, int &fileIndex)
{
  std::ifstream input(inputFile);
  std::vector<int> numbers;
  numbers.reserve(chunkSize);

  std::string line;
  while (std::getline(input, line)) {
    std::istringstream iss(line);
    std::copy(std::istream_iterator<int>(iss), std::istream_iterator<int>(), std::back_inserter(numbers));

    if (numbers.size() >= chunkSize) {
      std::sort(numbers.begin(), numbers.end());
      std::ofstream output(outputFilePrefix + std::to_string(fileIndex++) + ".tmp");
      std::copy(numbers.begin(), numbers.end(), std::ostream_iterator<int>(output, " "));
      output << "\n";
      numbers.clear();
    }
  }

  if (!numbers.empty()) {
    std::sort(numbers.begin(), numbers.end());
    std::ofstream output(outputFilePrefix + std::to_string(fileIndex++) + ".tmp");
    std::copy(numbers.begin(), numbers.end(), std::ostream_iterator<int>(output, " "));
    output << "\n";
  }
}

void mergeFiles(const std::string &outputFile, const std::string &inputFilePrefix, int fileCount)
{
  std::vector<std::ifstream> inputs(fileCount);
  std::vector<int> numbers(fileCount);
  std::vector<bool> activeInputs(fileCount, true);

  for (int i = 0; i < fileCount; i++) {
    inputs[i].open(inputFilePrefix + std::to_string(i) + ".tmp");
    inputs[i] >> numbers[i];
  }

  std::ofstream output(outputFile);

  struct Compare {
    bool operator()(const std::pair<int, int> &a, const std::pair<int, int> &b)
    {
      return a.first > b.first;
    }
  };

  std::priority_queue<std::pair<int, int>, std::vector<std::pair<int, int>>, Compare> pq;

  for (int i = 0; i < fileCount; i++) {
    if (activeInputs[i]) {
      pq.emplace(numbers[i], i);
      if (!(inputs[i] >> numbers[i])) {
        activeInputs[i] = false;
      }
    }
  }

  while (!pq.empty()) {
    int minValue = pq.top().first;
    int minIndex = pq.top().second;
    pq.pop();

    output << minValue << "\n";

    if (activeInputs[minIndex]) {
      pq.emplace(numbers[minIndex], minIndex);
      if (!(inputs[minIndex] >> numbers[minIndex])) {
        activeInputs[minIndex] = false;
      }
    }
  }

  for (int i = 0; i < fileCount; i++) {
    inputs[i].close();
  }
}

void deleteTempFiles(const std::string &inputFilePrefix, int fileCount)
{
  for (int i = 0; i < fileCount; i++) {
    std::string fileName = inputFilePrefix + std::to_string(i) + ".tmp";
    std::remove(fileName.c_str());
  }
}

int main()
{
  const std::string filename = "numbers.txt";
  const int count = 100000000;
  const std::string inputFile = "numbers.txt";
  const std::string outputFile = "sorted_numbers.txt";
  const std::string tempFilePrefix = "temp_";
  const int chunkSize = 10000;
  int fileIndex = 0;

  generateRandomNumbers(filename, count);
  splitFile(inputFile, tempFilePrefix, chunkSize, fileIndex);
  mergeFiles(outputFile, tempFilePrefix, fileIndex);
  deleteTempFiles(tempFilePrefix, fileIndex);

  return 0;
}

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值