2013-03-25 2 views
2

외부 정렬을 구현하려고하는 Im.C의 파일에서 N 개의 정수를 한 번에 읽는 중

처음에는 파일에서 N 정수 (고정 메모리에 따라 고정)를 읽어야합니다. 따라서 quicksort를 적용한 다음 병합 프로세스를 계속 진행할 수 있습니다.

나는이 두 가지 방법을 생각할 수 있습니다

  1. 는 N 정수에게 파일을 하나씩 읽고으로 정렬 한 후 배열에 넣어.
  2. 대량의 데이터를 큰 문자 배열로 읽어 들인 다음 sscanf를 사용하여 정수를 읽습니다.

첫번째 방법은 명확하게 느리고 두번째 방법은 추가 메모리를 많이 사용하고 (하지만 우리는 제한된 메인 메모리가)

이 더 좋은 방법이 있나요를?

+0

대소 문자가 +1 –

+0

비교 및 ​​스와핑에 비해 액세스 시간이 훨씬 더 깁니다. 파일에 수백만 개의 정수가 있으므로 한 번에 하나씩 액세스가 느려집니다. – Roronoa

+0

정수가 파일에 쓰여 있습니까 이진 형식이나 ASCII 문자열로? 당신은'sscanf()'를 아마 ASCII라고 언급합니다. ASCII 인 경우 라인 당 하나의 숫자입니까? 정수는 모두 같은 크기 (같은 자리수)입니까? 그렇지 않다면 한 번에 하나씩 읽는 것이 가장 현명합니다. ''은 최악의 비효율 문제를 피하기 위해 I/O를 버퍼링합니다. 아마도 충분히 빠를 것입니다. –

답변

3

당신의 OS보다 더 똑똑해 지려고하지 마십시오. 아마도 영리한 메모리 관리 기능을 지원할 것입니다. 그것은 당신의 삶과 코드를 더 빠르게 만들어 줄 것입니다.

POSIX 호환 운영 체제를 사용한다고 가정하면 mmap(2)을 사용할 수 있습니다.

  1. 지도의 mmap와 메모리에 파일
  2. 정렬이
  3. 동기화 할

OS가 방에 꽉 때 데이터를 교환 처리하고 당신이 필요로 할 때 그것을 교환 할 것이다이 방법 그것.

+0

그러나 이것은 표준 POSIX 함수입니다. – jbr

+0

행복한 지금 teppic? – jbr

+0

@teppic : 현재 99.99999 % 이상의 확실성을 지닌 프로그램은 mmap을 지원하는 OS에서 실행되거나'CreateFileMapping (...); MapViewOfFile (...)'. – datenwolf

0

읽을 때와 같은 시간에 정렬하는 것이 가장 좋습니다. 정렬 대신 데이터를 연결된 목록에 저장하는 것이 더 효율적입니다.

fscanf()을 사용하면 정수에서 정수를 읽을 수 있습니다. 그리고 파일에서 정수를 읽는 순간 정렬을 시도하십시오. 나는 파일에서 정수를 읽을 때 배열을 올바른 위치에 놓으면 읽는 것을 마칠 때 배열을 정렬 할 수 있습니다.

다음 예는 정수로 파일 정수를 읽은 다음 읽기와 동시에 sort를 삽입합니다. 정수는

기능이 소요 .... 배열로가 아니라 하나에 의해 파일 하나에서의 int를 읽고 정렬 및 이동에 병합 계속 아래와 같은 기능을 사용할 수 있습니다

void sort_insert(int x, int *array, int len) 
{ 
    int i=0, j; 
    for(i=0; i<(len-1); i++) 
    { 
     if (x > array[i]) 
      continue; 
     for (j=(len-1); j>i; j--) 
      array[j] = array[j-1]; 
     break; 
    } 
    array[i] = x; 
} 

void main() { 
    int x, i; 
    int len = 0; 
    int array[50]; 
    FILE *fp = fopen("myfile.txt", "r"); 

    while (len<50 && fscanf(fp, " %d",&x)>0) 
    { 
     len++; 
     sort_insert(x, array, len); 
    } 
    for (i=0; i<len; i++) 
    { 
     printf("array[%d] = %d\n", i, array[i]); 
    } 

} 
1

연결리스트에 저장됩니다 filename과 integer count를 인수로 취하고 파일에서 int를 반환합니다.

int read_int (const char *file_name, int count) 
{ 
    int err = -1; 
    int num = 0; 

    int fd = open(filename, O_RDONLY); 
    if(fd < 0) 
    { 
    printf("error opening file\n"); 
    return (fd); 
    } 

    err = pread(fd, &num, sizeof(int), count*sizeof(int)); 
    if(err < 0) 
    { 
    printf("End of file reached\n"); 
    return (err); 
    } 

    close(fd); 
    return (num); 
} 
+0

응답 해 주셔서 감사합니다.하지만 방금 N을 읽는 것 사이에 성능 차이가 있는지 알고 싶습니다. 한 번에 하나씩 읽기 – Roronoa

+0

@PranayVarma ... 분명히 한 번에 N 정수를 읽는 것과 1을 1을 읽는 것 사이의 성능 차이가 있습니다 ... 한 번에 N 개의 정수를 읽는 것과 비교하여 1을 읽는 것이 더 느립니다. .. 그러나 동시에 N 정수를 읽는 것은 1을 1 씩 읽는 것보다 전체 파일을 읽는 데 훨씬 더 많은 메모리가 필요합니다. 또는 두 가지 경우의 해결 방법으로 두 경우의 상품을 결합 할 수 있습니다. 당신이 읽을 수 있다고 말합니다. 고정 크기 버퍼 (64K/256k/512K 등) 및 다음 이동 정렬 ... 수행하고 같은 EOF 도달 할 때까지 반복 ....... 나는 또한 그쪽으로 데이터를 저장하기 위해 B + 트리를 사용하는 것이 좋습니다 정렬 방법이 빠릅니다. –

1

stdio 이후 파일 작업은 정말 파일이 큰되지 특히, 첫 번째 옵션에 대해 걱정할 필요가 없습니다, 버퍼링됩니다. 파일을 직접 조작하지 않고 메모리에 파일을 표현한 것을 기억하십시오.

예를 들어 한 번에 하나의 숫자를 스캔하면 시스템에서 파일의 훨씬 큰 부분을 읽습니다 (내 시스템에서는 4096 바이트, 파일이 짧으면 전체 파일에서 읽음).

관련 문제