这个排序程序要如何提高效率?

kingstarer 2009-05-25 07:10:16
我写了一个程序,作用是将文件按行排序

里面已经尽我可能提高效率了,但是发现还是比不上别人写的排序程序(外排)

理论上说外排应该会比内排慢一些才对,但是我又实在想不出要怎么提速了

不知各位有何高见

我写的代码:

#pragma warning (disable:4996)
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include <stdlib.h>
#include <assert.h>
using namespace std;

#define LINE_LENGTH 1000

//获得文件行数和字节数
bool GetFileCountSize(const char *filepath, size_t &fcount, size_t &fsize)
{
FILE *fp = fopen(filepath, "r");

if (fp == NULL)
{
return false;
}

char buffer[LINE_LENGTH];
fcount = 0;

while (fgets(buffer, LINE_LENGTH, fp))
{
fcount++;
}

fsize = ftell(fp);

return true;
}

//比较大小,排序时用
int CompareLine(const void *pleft, const void *pritht)
{
return strcmp((*(char **)pleft), (*(char **)pritht));
}

int test_sort(char *in_filepath, char *out_filepath)
{
size_t fcount = 0, fsize = 0, cursize = 0;
GetFileCountSize(in_filepath, fcount, fsize);

//读取源文件内存并保存到内存中
FILE *fp = fopen(in_filepath, "r");

if (fp == NULL)
{
cerr << "can't open file " << in_filepath << endl;
return 1;
}

//预分配内存
char *FileStrings = new char[fsize + fcount];
char ** FileLines = new char *[fcount];
if (FileLines == NULL || FileLines == NULL)
{
cerr << "get memory error!" << endl;
}

FileLines[0] = FileStrings;
fgets(FileLines[0], LINE_LENGTH, fp);

for (size_t i = 1, j = 0; i < fcount; i++, j++)
{
FileLines[i] = FileLines[j] + strlen(FileLines[j]) + 1;

fgets(FileLines[i], LINE_LENGTH, fp);
}

//排序
qsort(FileLines, fcount, sizeof(FileLines[0]), CompareLine);
//sort(FileLines, FileLines + fcount, CompareLine);
fclose(fp);

//将排序结果写到目标文件
fp = fopen(out_filepath, "w");

if (fp == NULL)
{
cerr << "can't open file " << out_filepath << endl;
return 1;
}

for (size_t i = 0; i < fcount; i++)
{
fputs(FileLines[i], fp);
}

fclose(fp);

//释放内存
delete FileStrings;
delete FileLines;

return 0;
}

int main(int argc, char *argv[])
{
return test_sort(argv[1], argv[2]);
}
...全文
130 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
kingstarer 2009-05-31
  • 打赏
  • 举报
回复
今天终于找到时间测试了一下:
$time testcmp memcmp tmp.txt > memcmp.res

real 0m0.08s
user 0m0.06s
sys 0m0.01s
$time testcmp strcmp tmp.txt > strcmp.res

real 0m0.03s
user 0m0.03s
sys 0m0.00s

从测试结果表明 memcmp代替strcmp 比 直接strcmp 慢 一倍多(1w行数据)
估计是不同机器库函数实现不同的问题,看来提升速度不能从此处下手

测试代码如下:


int main(int argc, char *argv[])
{
//char *strings[] = {"asf3223", "aesf534", "ase54", "3asef", "qe32", "adsgh", "asdaf34", "q23r34w", "saf", "2231e", "1231"};

size_t fcount = 0;
size_t fsize = 0;
char *FileStrings;
char ** strings;

//读源文件
if (!LoadFile(argv[2], fcount, fsize, FileStrings, strings)) return 1;


if (argv[1] == string("memcmp"))
{
for (int i = 0; i < fcount; i++)
{
for (int j = 0; j < fcount - i - 1; j++)
{
if (memcmp(strings[j], strings[j + 1], strlen(strings[j])) < 0)
{
char *tmp = strings[j];
strings[j] = strings[j + 1];
strings[j + 1] = tmp;
}
}
}
}
else
{
for (int i = 0; i < fcount; i++)
{
for (int j = 0; j < fcount - i - 1; j++)
{
if (strcmp(strings[j], strings[j + 1]) < 0)
{
char *tmp = strings[j];
strings[j] = strings[j + 1];
strings[j + 1] = tmp;
}
}
}
}

for (size_t i = 0; i < fcount; i++)
{
cout << strings[i] << endl;
}
return 0;
}

kingstarer 2009-05-25
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 hikaliv 的回复:]
引用 7 楼 kingstarer 的回复:
哈 不知不觉升四角了 值得庆贺^_^


散分吧……散1000,我去接五百。
[/Quote]

你说的对,确实想散分庆祝 :)

http://topic.csdn.net/u/20090525/22/499c7a07-32c4-40cb-b613-fe4a0b31129c.html
kingstarer 2009-05-25
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 hikaliv 的回复:]
引用 4 楼 kingstarer 的回复:
ls是建议用memcmp替换strcmp?

不知道这样效率能提升多少,我明天试试

不过比较郁闷的是这样又要开多500w个int保存字符串的大小


保存字符串的大小?这是什么意思……

你传进去strlen()就完了……
[/Quote]

因为觉得如果每次CompareLine调用时都算一次strlen可能会比直接strcmp慢

strlen遍历一次,memcmp遍历一次
而strcmp只遍历一次
光宇广贞 2009-05-25
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 kingstarer 的回复:]
哈 不知不觉升四角了 值得庆贺^_^
[/Quote]

散分吧……散1000,我去接五百。
kingstarer 2009-05-25
  • 打赏
  • 举报
回复
哈 不知不觉升四角了 值得庆贺^_^
光宇广贞 2009-05-25
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 kingstarer 的回复:]
ls是建议用memcmp替换strcmp?

不知道这样效率能提升多少,我明天试试

不过比较郁闷的是这样又要开多500w个int保存字符串的大小
[/Quote]

保存字符串的大小?这是什么意思……

你传进去strlen()就完了……
光宇广贞 2009-05-25
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 kingstarer 的回复:]
ls是建议用memcmp替换strcmp?

不知道这样效率能提升多少,我明天试试

不过比较郁闷的是这样又要开多500w个int保存字符串的大小
[/Quote]

一次比较过程,提升得很多。
kingstarer 2009-05-25
  • 打赏
  • 举报
回复
ls是建议用memcmp替换strcmp?

不知道这样效率能提升多少,我明天试试

不过比较郁闷的是这样又要开多500w个int保存字符串的大小
光宇广贞 2009-05-25
  • 打赏
  • 举报
回复
http://blog.csdn.net/jcwKyl/archive/2008/03/25/2217428.aspx

看看memcmp
kingstarer 2009-05-25
  • 打赏
  • 举报
回复
按行排序的意思如下:
假设a文件内存为
e
a
bb
c
dd

将a按行排序后则变成
a
bb
c
dd
e

行与行比较用strcmp
kingstarer 2009-05-25
  • 打赏
  • 举报
回复
排序500w行的文件花时间对比如下:
我的内排程序:


real 0m39.09s
user 0m22.17s
sys 0m2.80s



别人写的外排程序:


real 0m38.33s
user 0m22.74s
sys 0m5.84s



真想不通为何内排居然比外排不慢

65,211

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧