uNclear
(usa Slackware)
Enviado em 09/03/2017 - 17:11h
paulo1205 escreveu:
Você pode sim, fazer um merge de 2, e depois fazer um merge desse resultado com um terceiro, mas eu acho que não é a melhor saída.
Você pode mostrar essa parte do código, para tentarmos ajudar a ver por que motivo está parando antes do fim?
bool intercalaBloco(ifstream auxE[3], ofstream auxS[3], int passo, int saida){
//consideramos inicialmente que nao ia fazer nenhuma intercalaçao
bool intercalou = false;
Dado dados[3];
//posicao relativa de leitura em cada um dos arquivos
int pos[3] = {0, 0, 0};
//variavel para informar se os dados do arquivos sao validos (se foram lidos do arquivo de entrada e ainda nao gravados no arquivo de saida)
bool valido[3] = {false, false, false};
//em cada passo de tamanho n lemos n dados de cada arquivo e fazemos intercalaçao parcial em um novo bloco de tamanho 3*n no arquivo de saida utilizado
while( (pos[0] + pos[1] + pos[2]) < (3*passo) ){
//inicialmente verificamos se ha dados para ler
if( (pos[0] < passo) && (!valido[0]) ){
//tentamos ler do arquivo, verificando se a leitura foi valida, leitura invalida -> final do arquivo
if(auxE[0].read((char*) &dados[0], sizeof(Dado)) ){
valido[0] = true;
} else{
//para encerrer o while e nao entrar no if novamente
pos[0] = passo;
}
}
// repetimos o processo para o segundo arquivo
if( (pos[1] < passo) && (!valido[1]) ){
if(auxE[1].read((char*) &dados[1], sizeof(Dado)) ){
valido[1] = true;
} else{
//para encerrer o while e nao entrar no if novamente
pos[1] = passo;
}
}
if( (pos[2] < passo) && (!valido[2]) ){
if(auxE[2].read((char*) &dados[2], sizeof(Dado)) ){
valido[2] = true;
} else{
//para encerrer o while e nao entrar no if novamente
pos[2] = passo;
}
}
//nesse momento temos dados lidos dos 3 arquivos a nao ser que um (ou ambos) tenha chegado ao fim
//1º caso, os dois dados sao validos
if( (valido[0] && valido[1] )&& valido[2] ){
//marca que intercalou
intercalou = true;
//gravamos o menor valor no arquivo de saida
if(dados[0].chave1 <= dados[1].chave1 && (dados[0].chave1 <= dados[2].chave1)){
auxS[saida].write( (char*) &dados[0], sizeof(Dado) );
//dado utilizado nao e mais valido, avança posiçao
valido[0] = false;
pos[0]++;
}else if(dados[1].chave1 <= dados[0].chave1 && (dados[1].chave1 <= dados[2].chave1)){
auxS[saida].write( (char*) &dados[1], sizeof(Dado) );
//dado utilizado nao e mais valido, avança posiçao
valido[1] = false;
pos[1]++;
}else if(dados[2].chave1 <= dados[0].chave1 && (dados[2].chave1 <= dados[1].chave1)){
auxS[saida].write( (char*) &dados[2], sizeof(Dado) );
//dado utilizado nao e mais valido, avança posiçao
valido[2] = false;
pos[2]++;
}
/*else{
auxS[saida].write( (const char*) &dados[1], sizeof(Dado) );
//dado utilizado nao e mais valido, avança posiçao
valido[1] = false;
pos[1]++;
}*/
}
//2º caso, apenas o primeiro dado e valido
else if(valido[0]){
//marca que intercalou
intercalou = true;
auxS[saida].write( (char*) &dados[0], sizeof(Dado) );
//dado utilizado nao e mais valido, avança posiçao
valido[0] = false;
pos[0]++;
}
//3º caso, apenas o segundo dado e valido
else if(valido[1]){
//marca que intercalou
intercalou = true;
auxS[saida].write( (char*) &dados[1], sizeof(Dado) );
//dado utilizado nao e mais valido, avança posiçao
valido[1] = false;
pos[1]++;
}
else if(valido[2]){
//marca que intercalou
intercalou = true;
auxS[saida].write( (char*) &dados[2], sizeof(Dado) );
//dado utilizado nao e mais valido, avança posiçao
valido[2] = false;
pos[2]++;
}
//se chegou aqui termina o while na proxima iteraçao
else {
}
}
return intercalou;
}
void mergeexterno(ifstream &arqEntrada, ofstream &arqSaida){
ofstream arqB1 ("arqB1.dat", ios::binary);
ofstream arqB2 ("arqB2.dat", ios::binary);
ofstream arqB3("arqB3.dat", ios::binary);
if((!arqB1) && (!arqB2) && (!arqB3)){
cerr << "Arquivos auxiliares nao puderam ser abertos (arqB1.dat ou arqB2.dat )" << endl;
exit(EXIT_FAILURE);
}
Dado umDado;
//posicionando ponteiro de leitura no final do arquivo
arqEntrada.seekg(0, ios::end);
//obtendo a posicao final do arquivo
int tamanho = arqEntrada.tellg();
//dado o tamanho do arquivo, sabe-se quantos registos ha no arquivo
int numRegistros = tamanho / sizeof(Dado);
cout << numRegistros << endl;
//metade do numero de registros (arredondado pra cima)
int metade = (numRegistros / 3) + 0.5;
cout << metade << endl;
//posicionando ponteiro de leitura no inicio do arquivo
arqEntrada.seekg(0, ios::beg);
//copiando dados para 3 arquivos auxiliares
for(int i = 0; i < metade; i++){
arqEntrada.read((char*) &umDado, sizeof(Dado) );
arqB1.write((char*) &umDado, sizeof(Dado) );
}
for(int i = metade; i < metade * 2; i++){
arqEntrada.read((char*) &umDado, sizeof(Dado) );
arqB2.write((char*) &umDado, sizeof(Dado) );
}
for(int i = metade * 2; i < numRegistros; i++){
arqEntrada.read((char*) &umDado, sizeof(Dado));
arqB3.write((char*) &umDado, sizeof(Dado));
}
//finalizaçao primeira etapa
arqB1.close();
arqB2.close();
arqB3.close();
arqEntrada.close();
//arquivos auxiliares
ifstream auxEntrada[3];
ofstream auxSaida[3];
//variaveis de controle
int passo = 1;
bool ida = true;
bool ultimo[3];
//laço principal
while(passo <= numRegistros){
if(ida){
auxEntrada[0].open("arqB1.dat", ios::binary);
auxEntrada[1].open("arqB2.dat", ios::binary);
auxEntrada[2].open("arqB3.dat", ios::binary);
auxSaida[0].open("arqC1.dat", ios::binary);
auxSaida[1].open("arqC2.dat", ios::binary);
auxSaida[2].open("arqC3.dat", ios::binary);
}else{
auxEntrada[0].open("arqC1.dat", ios::binary);
auxEntrada[1].open("arqC2.dat", ios::binary);
auxEntrada[2].open("arqC3.dat", ios::binary);
auxSaida[0].open("arqB1.dat", ios::binary);
auxSaida[1].open("arqB2.dat", ios::binary);
auxSaida[2].open("arqB3.dat", ios::binary);
}
if( (!auxEntrada[0]) || (!auxEntrada[1]) || (!auxSaida[0]) || (!auxSaida[1]) || (!auxEntrada[2]) || (!auxSaida[2]) ){
cerr << "Arquivos auxiliares nao podem ser abertos (arqB1.dat ou arqB2.dat ou arqC1.dat ou arqC2.dat)" << endl;
exit(EXIT_FAILURE);
}
//enquanto nao chegar ao final dos arquivos de entrada, vai intercalando os blocos
while( (!auxEntrada[0].eof()) && (!auxEntrada[1].eof()) && (!auxEntrada[2].eof()) ){
ultimo[0] = intercalaBloco(auxEntrada, auxSaida, passo, 0);
ultimo[1] = intercalaBloco(auxEntrada, auxSaida, passo, 1);
ultimo[2] = intercalaBloco(auxEntrada, auxSaida, passo, 2);
}
//fecha arquivos para permitir troca escrita <-> leitura, na proximo interaçao
auxEntrada[0].close();
auxEntrada[1].close();
auxEntrada[2].close();
auxSaida[0].close();
auxSaida[1].close();
auxSaida[2].close();
ida = !ida;
passo *= 3;
}
//merge terminado, agora lemos do arquivo auxiliar para arquivo de saida
ifstream auxEnt;
//identifique o arquivo auxiliar com dados ordenados
if(ida){
if(ultimo[0]){
auxEnt.open("arqB1.dat", ios::binary);
}else if(ultimo[1]){
auxEnt.open("arqB2.dat", ios::binary);
}else if(ultimo[2]){
auxEnt.open("arqB3.dat", ios::binary);
}
}else{
if(ultimo[0]){
auxEnt.open("arqC1.dat", ios::binary);
}else if(ultimo[1]){
auxEnt.open("arqC2.dat", ios::binary);
}else if(ultimo[2]){
auxEnt.open("arqC3.dat", ios::binary);
}
}
if(!auxEnt){
cerr << "Arquivo auxiliar nao pode ser aberto" << endl;
exit(EXIT_FAILURE);
}
while(auxEnt.read((char*) &umDado, sizeof(Dado)) ){
arqSaida.write((const char*) &umDado, sizeof(Dado) );
}
auxEnt.close();
//apagar arquivos auxiliares
remove("arqB1.dat");
remove("arqB2.dat");
remove("arqC1.dat");
remove("arqC2.dat");
remove("arqC3.dat");
remove("arqB3.dat");
}
Obrigado mais uma vez pela ajuda o/