免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2766 | 回复: 6
打印 上一主题 下一主题

[算法] 排序问题,大家帮帮忙! [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-01-09 16:47 |只看该作者 |倒序浏览
5可用积分
有一文件,文件中内容如下:
[04001 0216][001505-758][9988*00010 柜员登陆系统      ][                       ]
[04001 0216][001505-894][9988*00010 柜员登陆系统      ][交易成功           0000]
[04001 0216][001509-345][9675*00000 开工回显状态      ][                       ]
[04001 0216][001509-377][9675*00000 开工回显状态      ][交易成功           0000]
[04001 0216][001514-347][5502 00012 柜员开工          ][                       ]
[04001 0216][001510-146][5501 00011 网点开工          ][                       ]
[04001 0216][001510-207][5501 00011 网点开工          ][交易成功           0000]
[04001 0216][001514-391][5502 00012 柜员开工          ][交易成功           0000]
这样的记录大概有12500条,第三个[]中记录相同的代表同一条记录,但是汉字前面是00000的记录要删除。第二个[]记录的为时间(H:M:S-MS)。
要求有一程序对同一条记录所耗费的时间进行排序。大家给点思路!十分感谢

[ 本帖最后由 cooper84 于 2009-1-10 11:19 编辑 ]

最佳答案

查看完整内容

那很好说。在我4楼的半伪代码中,在while循环的一开始,判断一下是否跳过(剔出)就行,后面的逻辑完全不影响。然后,补充说明一下原理吧。map,用来将你的数据按照你所说的“第三个[]中记录相同的代表同一条记录”“对同一条记录所耗费的时间进行排序”进行分类。每个类别有一个set。然后,因为在很多STL的实现中,map和set内部使用的是RB-Tree,而RB_tree是一个有序结构。因此,当我们往set中添加数据后,set内部的RB-tree会使 ...

论坛徽章:
0
2 [报告]
发表于 2009-01-09 16:47 |只看该作者
原帖由 cooper84 于 2009-1-10 11:16 发表
谢谢大家 我忘记写另外一个条件了,第三个[]中带00000的不用排序,要删除掉,我举例子中的3-4行记录就要删除



那很好说。在我4楼的半伪代码中,在while循环的一开始,判断一下是否跳过(剔出)就行,后面的逻辑完全不影响。

//-- C++ code


struct RecordItem
{
    TimeType     time;     //-- 你的时间纪录  (方便排序比较的类型,比如将时间转换为毫秒数,然后用uint64_t什么的存一下)


    std::string  strTime;  //-- 你时间的原始记录


    std::string  desc;     //-- 你的第三个[]的内容


    void*        other;

    //-- member function


    RecordItem() {}
    RecordItem(std::string & strOrgTime, std::string & orgDesc):  strTime(strOrgTime), desc(orgDesc)
    {
        InitTimeTypeDataByString(strOrgTime); //-- 初始化你的 time成员


    }
    
    bool operator == ( const RecordItem & r ) {return time == r.time; }
    bool operator != ( const RecordItem & r ) {return time != r.time; }
&nbsp;&nbsp;&nbsp;&nbsp;bool operator <= ( const RecordItem & r ) {return time <= r.time; }
&nbsp;&nbsp;&nbsp;&nbsp;bool operator >= ( const RecordItem & r ) {return time >= r.time; }
&nbsp;&nbsp;&nbsp;&nbsp;bool operator < ( const RecordItem & r ) {return time < r.time; }
&nbsp;&nbsp;&nbsp;&nbsp;bool operator > ( const RecordItem & r ) {return time > r.time; }
};
void Sort(record_list)
{
&nbsp;&nbsp;&nbsp;&nbsp;std::set<RecordItem>        *foundSet;
&nbsp;&nbsp;&nbsp;&nbsp;std::map<std::string, std::set<RecordItem> >  allItem;
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;RecordItem item;
&nbsp;&nbsp;&nbsp;&nbsp;while(item = record_list.getAnItem())    //-- 假设返回NULL表示结束

&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(item.desc.find("00000")    //-- find只是举例,直接这样用应该不够严密。

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue;     //-- 如果遇到你刚才说的条件,那就跳过,直接剔出该条数据。


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foundSet = allItem.find(item.desc);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(foundSet != allItem.end())
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foundSet->escond.insert(item);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::set<RecordItem>        itemSet;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;itemSet.insert(item);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;allItem.insert(std::pair<std::string, std::set<RecordItem> >(item.desc, itemSet));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
}


然后,补充说明一下原理吧。
map,用来将你的数据按照你所说的“第三个[]中记录相同的代表同一条记录”“对同一条记录所耗费的时间进行排序”进行分类。每个类别有一个set。
然后,因为在很多STL的实现中,map和set内部使用的是RB-Tree,而RB_tree是一个有序结构。因此,当我们往set中添加数据后,set内部的RB-tree会使用set实例化的第二个模版参数(在这里我用的是默认参数)less()函数对象,来调用相关的关系操作运算进行操作。而这个操作的副产品就是,当我们从begin()到end()遍历时,就相当于对set内部的rb-tree进行中序遍历,从而导致最终的输出为排序后的有序输出(less()函数对象的话,是从小到大)。这就是为什么在RecordItem中重载了关系运算符的原因了。

而且因为你是要依据时间排序,所以在RecordItem重载关系运算符时,只以time成员为判断依据。同时这也是为什么我在伪代码中建议将时间转换成毫秒数然后存放到64位无符号整型中的原因了,便于比较 + 代码量少。

其实大致代码如上,除了转换函数和剔出判断外,基本上主干代码就如上所示(当然,辅助代码我就不管了,毕竟是示意伪码)。如果需要从大到小排列,反序遍历,或者使用grater()函数对象就行。如果需要其它稀奇古怪的排序方式,写一个函数对象显示地作为set实例化的第二个模版参数,然后适当改一下RecordItem的关系重载实现就行。

论坛徽章:
0
3 [报告]
发表于 2009-01-09 17:02 |只看该作者
大家帮帮忙啊!高手给个思路就行

论坛徽章:
0
4 [报告]
发表于 2009-01-09 17:18 |只看该作者
先按第二个快速排序,再按第三个把相同的调整到一起

论坛徽章:
0
5 [报告]
发表于 2009-01-09 18:04 |只看该作者
原帖由 cooper84 于 2009-1-9 16:47 发表
有一文件,文件中内容如下:
[04001 0216][001505-758][9988*00010 柜员登陆系统      ][                       ]
[04001 0216][001505-894][9988*00010 柜员登陆系统      ][交易成功           0000]
[04 ...



思路伪码:
//-- C++ code

struct RecordItem
{
&nbsp;&nbsp;&nbsp;&nbsp;TimeType     time;     //-- 你的时间纪录  (方便排序比较的类型,比如将时间转换为毫秒数,然后用uint64_t什么的存一下)

&nbsp;&nbsp;&nbsp;&nbsp;std::string  strTime;  //-- 你时间的原始记录

&nbsp;&nbsp;&nbsp;&nbsp;std::string  desc;     //-- 你的第三个[]的内容

&nbsp;&nbsp;&nbsp;&nbsp;void*        other;

&nbsp;&nbsp;&nbsp;&nbsp;//-- member function

&nbsp;&nbsp;&nbsp;&nbsp;RecordItem() {}
&nbsp;&nbsp;&nbsp;&nbsp;RecordItem(std::string & strOrgTime, std::string & orgDesc):  strTime(strOrgTime), desc(orgDesc)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InitTimeTypeDataByString(strOrgTime); //-- 初始化你的 time成员

&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;bool operator == ( const RecordItem & r ) {return time == r.time; }
&nbsp;&nbsp;&nbsp;&nbsp;bool operator != ( const RecordItem & r ) {return time != r.time; }
&nbsp;&nbsp;&nbsp;&nbsp;bool operator <= ( const RecordItem & r ) {return time <= r.time; }
&nbsp;&nbsp;&nbsp;&nbsp;bool operator >= ( const RecordItem & r ) {return time >= r.time; }
&nbsp;&nbsp;&nbsp;&nbsp;bool operator < ( const RecordItem & r ) {return time < r.time; }
&nbsp;&nbsp;&nbsp;&nbsp;bool operator > ( const RecordItem & r ) {return time > r.time; }
};
void Sort(record_list)
{
&nbsp;&nbsp;&nbsp;&nbsp;std::set<RecordItem>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*foundSet;
&nbsp;&nbsp;&nbsp;&nbsp;std::map<std::string, std::set<RecordItem> >  allItem;
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;RecordItem item;
&nbsp;&nbsp;&nbsp;&nbsp;while(item = record_list.getAnItem())
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foundSet = allItem.find(item.desc);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(foundSet != allItem.end())
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foundSet->escond.insert(item);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::set<RecordItem>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;itemSet;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;itemSet.insert(item);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;allItem.insert(std::pair<std::string, std::set<RecordItem> >(item.desc, itemSet));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
}


这个时候,你所有记录全在allItem里面按你第三个[]分类。每个分类里,你从set<RecordItem>::begin() 到 set<RecordItem>::end()遍历,遍历的结果就是按时间排序的结果。

[ 本帖最后由 swxlion 于 2009-1-9 18:15 编辑 ]

论坛徽章:
0
6 [报告]
发表于 2009-01-10 11:16 |只看该作者
谢谢大家 我忘记写另外一个条件了,第三个[]中带00000的不用排序,要删除掉,我举例子中的3-4行记录就要删除

论坛徽章:
0
7 [报告]
发表于 2009-01-10 15:37 |只看该作者

补充一下6楼

如果set内部的实现不是用的有序结构的话,那就不行了。但至少目前我遇到的set的内部实现都是有序结构。

如果万一遇到的set内部刚好不是有序结构,那上面的算法其实还是不用变,直接将set对象用AVL Tree或RB-Tree代替就行。
如果没找到合适的AVL Tree或RB-Tree,又不想写,或怕性能有问题的话,可以考虑使用我签名项目中的GDST子项目里的对应结构。

但如果需要纯C实现的话,相信按上面的思路,很好解决。

[ 本帖最后由 swxlion 于 2009-1-10 15:40 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP