2017-09-05 6 views
1

N個の乱数を生成し、降順でバイナリファイルに書き込むプログラムを書く必要があります。メインメモリを使用するソートアルゴリズムを使用せずに実行する必要があります。乱数外部ソート

#include <iostream> 
#include <fstream> 
#include <ctime> 
#include <cstdlib> 

using namespace std; 
int main() { 
    srand(time(0)); 
    rand(); 
    int N; 
    do{ 
    cout << "Unesite N: "; 
    cin >> N; 
    } while(N<=0); 

    ofstream br("broj.dat", ios::binary | ios::trunc); 

    for(int i = 0; i<N; i++){ 
    int a = rand(); 
    br.write((char *)&a, sizeof(a)); 
    } 
    br.close(); 

    return 0; 
} 

だから、私が生成した乱数を、バイナリファイルに書きましたが、私はそれをソートする方法がわからない:これは私がこれまで行ってきたものです。

+0

メインメモリとはどういう意味ですか? –

+0

配列にその数値を挿入して、挿入ソートやバブルソートなどのアルゴリズムでソートするべきではありません。 –

+1

お探しのものは* External Merge Sort *と呼ばれており、これを達成する方法については多くの情報があります。彼らはすべて、私はあなたがやりたいとは思わないN個のファイルを作る必要がありますいくつかのサイズのバッファを使用することに注意してください。 – NathanOliver

答えて

0

私はそれをどうやって行うのか疑似コードです。

for i in 1..N: 
    write rand() to new file 
    push onto file stack (new file, size=1) 
    while 2 < len(file stack) and size of top two files the same: 
     pop top two and merge them 
     push onto file stack (merged file, size=new size) 

while 2 < len(file stack): 
    pop top two and merge them 
    push onto file stack (merged file, size=new size) 

The top of the file stack is your new sorted file. 
+0

@greybeardいいえ、ファイルが異なるサイズのときにマージが止まるので、 'O(log(n))'ファイルではありません。最初の数回の繰り返しの後に巻き上げるサイズのスタックがあります。 '1'、2、2 1、4、4 1、4 2、8、... – btilly

+0

私が '4 1'と言うとき、一番下に1要素のあるファイルがあります。もちろん、スタックサイズは 'O(log(n)) 'になります。最悪の場合、 '2^n-1'要素を格納するために' n'ファイルが必要です。 (その後、それらはすべて1つのマージされたファイルに崩壊します。)私の投稿に関しては、これは主に、上記の正確な戦略を説明する@NathanOliverにコメントを明示することを意味していました。 – btilly

+0

*最後に、NathanOliverとあなたのコメントを参照しました。地獄で曲がって外部の並べ替えをすると、数値/ランを少数の*(例えばm)個のファイルに配布し、m個の出力ファイルに配布しようとするm-wayマージを行います。マイルは様々です。 – greybeard

4

番号を線形時間でソート順に生成できます。これを行う方法を記述した論文がある:ベントレー&サックス

https://pdfs.semanticscholar.org/2dbc/4e3f10b88832fcd5fb88d34b8fb0b0102000.pdf

/** 
* Generate an sorted list of random numbers sorted from 1 to 0, given the size 
* of the list being requested. 
* 
* This is an implementation of an algorithm developed by Bentley and Sax, and 
* published in in ACM Transactions on Mathematical Software (v6, iss3, 1980) on 
* 'Generating Sorted Lists of Random Numbers'. 
*/ 
public class SortedRandomDoubleGenerator { 
    private long  valsFound; 
    private double  curMax; 
    private final long numVals; 

    /** 
    * Instantiate a generator of sorted random doubles. 
    * 
    * @param numVals the size of the list of sorted random doubles to be 
    *  generated 
    */ 
    public SortedRandomDoubleGenerator(long numVals) { 
     curMax = 1.0; 
     valsFound = 0; 
     this.numVals = numVals; 
    } 

    /** 
    * @return the next random number, in descending order. 
    */ 
    public double getNext() { 
     curMax = curMax 
       * Math.pow(Math.E, Math.log(RandomNumbers.nextDouble()) 
         /(numVals - valsFound)); 
     valsFound++; 
     return curMax; 
    } 
} 
+0

RandomNumbersは、標準のJava乱数ジェネレータ - 0〜1の間の疑似乱数を得る方法です。 – Dave

+0

クールですが、彼の任務のポイントは、ファイルをメモリに最初にロードせずにディスク上のファイルの内容をソートする方法を学ぶことです。すでにソートされた順序でファイルを書き出すと、割り当てのポイントが失われますか? –

+0

@JeremyFriesner私はこれが宿題であることに気付かなかった。それでも、これは質問された質問に答えるので、私はそれを残します。 – Dave

0

によって乱数の生成ソートリストは、標準ライブラリには、マージソートがありますが、ランダムアクセスイテレータを使用する必要があります。

#include <algorithm> 
#include <cstdio> 
#include <random> 
#include <fcntl.h> 
#include <sys/mman.h> 
#include <unistd.h> 

const size_t COUNT = 4096 * 4096; 

int main() 
{ 
    // create file (using mmap for simplicity) 
    int fd = open("out.dat", O_RDWR | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR); 
    if (fd < 0) { 
     std::perror("open failed"); 
     return 1; 
    } 
    if (ftruncate(fd, COUNT * sizeof(unsigned)) != 0) { 
     std::perror("ftruncate failed"); 
     close(fd); 
     return 1; 
    } 
    void* mm = mmap(nullptr, COUNT * sizeof(unsigned), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 
    if (mm == MAP_FAILED) { 
     std::perror("mmap failed"); 
     close(fd); 
     return 1; 
    } 
    close(fd); 

    // populate file 
    unsigned* begin = static_cast<unsigned*>(mm); 
    std::default_random_engine rng((std::random_device())()); 
    std::generate_n(begin, COUNT, rng); 
    msync(mm, COUNT * sizeof(unsigned), MS_SYNC); 
    std::puts("file written"); 

    // sort file 
    std::stable_sort(begin, begin + COUNT); 
    msync(mm, COUNT * sizeof(unsigned), MS_SYNC); 
    std::puts("file sorted"); 

    if (std::is_sorted(begin, begin + COUNT)) { 
     std::puts("it's properly sorted"); 
    } 

    // close file 
    munmap(mm, COUNT * sizeof(unsigned)); 
    return 0; 
} 

msync通話が実際に必要されていません:あなたはmmap(またはそれに相当)を使用することができます場合は、(はい、私はあなたがコマンドラインからCOUNTを取る必要があることを知っている)、ランダムアクセスイテレータを持っています。私は正直言って、これはまともなパフォーマンスを持っていることに驚いています。

+1

'私は正直に驚いています。 *厄介な問題の声明*に対処する別の方法のための功績。 (ただし、支払う顧客の要件の記述についてどう思いますか)。 – greybeard

関連する問題