2010-03-03 82 views
2

我试图在非常大的数据集上实现I/O密集型快速排序(C++ qsort)。为了提高速度,我希望一次将大块数据读入缓冲区,然后使用qsort在缓冲区内对其进行排序。 (我目前正在处理文本文件,但很快就会转向二进制文件。)但是,我的数据由可变长度的记录组成,并且qsort需要被告知记录的长度以便进行排序。有什么办法来标准化这个吗?我能想到的唯一事情是相当复杂的:我的程序正在从缓冲区中读取数据,直到它遇到一个换行字符('ascii'中的'10'),将每个字符转移到另一个数组中。当它找到一个换行符(输入文件中的分隔符)时,它会填充该记录的缓冲区中剩余的空格数(记录大小设置为30),并使用空字符。这样,我最终将得到一个充满固定大小记录的缓冲区来提供qsort。从缓冲区读取可变长度记录 - 奇怪的内存问题

我知道我的方法有几个问题,一个是它只是笨拙的,另一个是记录尺寸可能大于30,但通常要少得多。有没有更好的方法来做到这一点?

此外,我目前的代码甚至不工作。当我调试它时,它似乎将字符从一个缓冲区转移到另一个缓冲区,但是当我尝试打印出缓冲区时,它只包含第一条记录。

这里是我的代码:

FILE *fp; 
unsigned char *buff; 
unsigned char *realbuff; 
FILE *inputFiles[NUM_INPUT_FILES]; 
buff = (unsigned char *) malloc(2048); 
realbuff = (unsigned char *) malloc(NUM_RECORDS * RECORD_SIZE); 

fp = fopen("postings0.txt", "r"); 
if(fp) 
{ 
    fread(buff, 1, 2048, fp); 


    /*for(int i=0; i <30; i++) 
    cout << buff[i] <<endl;*/ 

    int y=0; 
    int recordcounter = 0; 

    //cout << buff; 
    for(int i=0;i <100; i++) 
    { 
     if(buff[i] != char(10)) 
     { 
      realbuff[y] = buff[i]; 
      y++; 
      recordcounter++; 
     }   
     else 
     { 
      if(recordcounter < RECORD_SIZE) 
       for(int j=recordcounter; j < RECORD_SIZE;j++) 
       { 
        realbuff[y] = char(0); 
        y++; 
       } 
      recordcounter = 0; 
     } 
    } 

    cout << realbuff <<endl; 
    cout << buff; 
} 
else 
    cout << "sorry"; 

非常感谢你, BSG

+1

如果您希望人们帮助您,请多加小心,让您的代码可读。 – 2010-03-03 06:21:32

+1

'qsort'在哪里? (顺便说一句,因为你已经在使用C++为什么不使用'std :: sort'?) – kennytm 2010-03-03 06:35:38

+0

因为“y”永远不会被重置,所以你可能会写出“realbuff”的限制。 – YeenFei 2010-03-03 06:57:06

回答

1

的快速排序功能只能在固定长度的记录(像你说的)。为了排序可变长度的记录,你需要一个指向它们的指针数组,然后对qsort指针数组进行排序。这可能也更有效率,因为指针比大块数据更快地移动。

std :: sort也是一样,因为它是类型安全的,所以建议这样做。只要确保提供一个比较谓词(小于函数),以指针作为参数作为第三个参数。

+0

感谢您的建议。我创建了一个指针数组,并将它们指向每条记录的开头,但是由于它们是一个字符数组,每个指针都指向从指向的位置开始的整个数组。所以当它排序时,我想打印出数组,它会打印整个数组几次。我怎样才能使每个指针指向只有一个记录?同样,每一个都指向记录的开始,但它认为缓冲区的其余部分也是它所指向的字符串的一部分。谢谢,bsg。 – bsg 2010-03-04 03:26:35