在不使用数组的情况下对二进制文件中的数据进行排序

Sorting data in binary file without using arrays

本文关键字:数据 排序 二进制文件 情况下 数组      更新时间:2023-10-16

你好,我有一个作业,我应该生成随机数。然后将它们写入二进制文件。之后,我应该读取数据将其打印到屏幕上。最后,我必须对数据和输出进行排序。我必须在不使用数组的情况下执行此操作。我能够完成前两个部分。但是,我无法正确完成最后一部分,所以我去了谷歌和YouTube寻找有关如何做到这一点的插图,但我不走运。我真的很想知道我做错了什么,谢谢。

我想我应该使用递归 fseek 和强制转换来避免使用数组;但是,我不知道如何使用它们。

这是我的代码以及输出:

#include <iostream>
#include <fstream>
#include <iomanip>
#include <stdlib.h> 
using namespace std;
//Function prototypes
void Write_File(int num);
void Read_File(int num);
void Compare(int num);
//**********************
int main()
{
    int num = 0;
    cout << "Enter a positive number to generate random numbers ";
    cin >> num;
    Write_File(num);
    Read_File(num);
    Compare(num);

    return 0;
}
//***************
// Functions Definitions
void Write_File(int num)
{
    ofstream fout("sortfile.dat", ios::out | ios::binary | ios::beg);
    int number = 0;
    if (fout.is_open())
    {
        for (int x = 0; x < num; x++)
        {
            number = rand();
            fout << number << endl;
        }
        fout.close();
    }
    else
    {
        cout << "Error, File not opened" << endl;
    }
}
void Read_File(int num)
{
    ifstream fin("sortfile.dat", ios::in | ios::binary | ios::beg);
    int number = 0;
    cout << endl << "randomly generated numbers befor sortingn";
    if (fin.is_open())//check first if open already
    {
        for (int i = 0; i < num; i++)
        {
            fin >> number;
            cout << number << endl;
        }

            fin.close();
        }
        else
            cout << "File not opened in read phase." << endl;
}

void Compare(int num) 
{
    int number = 0;
    int temp = 0;
    int hold = 0;
    ifstream fin("sortfile.dat", ios::in | ios::binary | ios::beg);
    if (fin.is_open())//check first if open already
    {
        for (int i = 0; i < num; i++)
        {
            fin >> number;
            fin >> temp;
            if (number > temp)
            {

                hold = temp;
                temp = number;
                number = hold;
            }
            else
            {
                ofstream fout("sortfile.dat", ios::out | ios::binary | ios::beg);
                fout << number;
                fout << temp;
            }
            ofstream fout("sortfile.dat", ios::out | ios::binary | ios::beg);
            fout << number;
            fout << temp;
        }
        cout << endl << "Nums after sortn";
        for (int i = 0; i < num; i++)
        {
            fin >> number;
            cout << number << endl;
        }
        fin.close();
    }
    else
        cout << "File not opened in read phase." << endl;
}

输出:

Enter a positive number to generate random numbers 4
randomly generated numbers befor sorting
41
18467
6334
26500
Nums after sort
6334
6334
6334
6334
Press any key to continue . . .

好的,这里有几点问题。 首先,您将无法仅通过交换相邻元素来进行一次性排序。 那将是一个O(n(排序,如果你设法实现它,你将立即成为一个计算机科学名人。 你的教授说你不能使用数组? 如果"数组"是指任何类型的内存缓冲区,那只是愚蠢的。如果你想要一个不使用数组的排序,从字面上看,只需使用 std::map。 从文件中读取数字时,将数字插入到地图中。 然后,使用迭代器按排序顺序检索数字,并在执行此操作时打印出它们。

其次,您正在使用文件 io 做一些可能不是您想要的事情。 在从文件中读取数字对然后可能交换它们的循环中,控制流允许将数字对写入文件两次,如果它们按排序顺序排列。 此外,您可以在每个循环迭代中构造一个或两个 ofstream 对象。 每个新的输出流都从文件的开头开始,因此您重复写入文件的开头。 在打印出"排序"内容之前,您也不会将输入流查找到文件开头。它打印出相同数字 4 次的原因是它已到达文件的末尾,并且没有为"数字"分配任何新值。

我的建议是真正避免尝试同时读取和写入文件。 读取数字(不是数组,请注意;)(,对它们进行排序,然后输出它们。(从赋值规范来看,您似乎不必再次将它们写入文件,但我不确定(。

据我所知,请继续重新创建输出流,这意味着您继续写入文件的开头。

在您的比较函数中:

for (int i = 0; i < num; i++)
{
      ...
     // for every iteration you create an output stream at the beginning of the file
      ofstream fout("sortfile.dat", ios::out | ios::binary | ios::beg);
      fout << number;
      fout << temp;
}

嗯,要对一堆元素进行排序,无论您使用哪种算法,都会有一段时间您至少必须将一个元素(或其索引(存储在其存储中的指定位置 =>普通程序员使用数组(或数组或索引(所称呼的。

您的要求可以通过两种方式理解:

  • 您不能使用数组,但可以使用其他C++容器。好吧,取一个向量(填充后像数组一样使用(,或者按照@c_dubs的建议使用地图。也许吧,但是如果我要求不使用数组并且不明确允许C++容器,我不会对该解决方案感到满意
  • 您根本无法在内存存储中使用。您必须直接对磁盘上的文件(或文件的副本(进行排序。如果您遵循该路径,只需使用 fseek 在文件上移动指针,您就可以直接在磁盘上定义的位置读取和写入元素。这足以使用任何类型的算法。

当心:我的建议是对该分配使用直接磁盘排序,但在现实世界中永远不要这样做!无论如何,在对大量元素进行排序时,将初始数据分成足够小的束以在内存中处理,对它们进行排序并将它们存储回磁盘,然后合并这些排序的文件,这很有用。这是对无法加载到内存中的数据进行排序的唯一万无一失的方法。

我的猜测是,您可以使用变量来保存文件中的数字,并使用多个文件来保存临时数据(或您随机访问的单个文件,就好像它是 4 个文件一样(。您可以使用 4 个文件实现自下而上的 2 路合并排序。它类似于 wiki 文章中提到的 4 磁带驱动器排序。

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