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

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]);
}
...全文
129 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



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

内容概要:SSD2828QN4是一款MIPI主桥接芯片,用于连接应用处理器与传统并行LCD接口及支持MIPI从属接口的LCD驱动器。该芯片支持最高每通道1Gbps的串行链路速度,最多可配置4个数据通道,显著减少了信号数量。它支持多种接口模式,包括RGB+SPI组合接口,适用于驱动智能或非智能显示面板,并能通过命令模式和视频模式传输数据。芯片内置时钟和复位模块、外部接口、协议控制单元(PCU)、包处理单元(PPU)、错误校正码/循环冗余校验(ECC/CRC)模块、长包和命令缓冲区、D-PHY控制器、模拟收发器以及内部锁相环(PLL),确保了高效的数据传输和系统稳定性。此外,文档详细描述了芯片的引脚分配、寄存器设置、操作模式、电源序列、时序特性等关键参数,为开发者提供了全面的技术指导。 适合人群:具备一定硬件设计基础,从事嵌入式系统开发、显示技术研究的研发人员。 使用场景及目标:①实现应用处理器与MIPI兼容显示屏之间的高速数据传输;②优化显示系统的功耗表现,减少电磁干扰(EMI);③通过灵活配置不同接口模式来适应各种显示设备的需求。 阅读建议:此文档面向具有一定电子工程背景的专业人士,建议读者结合实际项目需求深入理解各章节内容,特别是关于寄存器配置、时序要求等方面的具体说明。对于初次接触此类技术的开发者而言,建议先熟悉基本概念再逐步掌握高级功能的应用方法。

65,210

社区成员

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

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