首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 .NET Java 游戏 视频 人才 外包 培训 数据库 书店 程序员
中国软件网
欢迎您:游客 | 登录 注册 帮助
  • 有10亿个浮点数,从中找出1万个最大的数。 [已结帖,结帖人:kesaihao862]
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • kesaihao862
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 结帖率:
    发表于:2008-02-28 14:43:57 楼主
    请问:1.有10亿个浮点数,从中找出1万个最大的数。写一个高性能的算法

    能说出算法和数据结构就可以了
    10  修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • dubiousway
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-28 14:52:251楼 得分:0
    10亿个浮点数? 内存操作不行吧。
    文件操作,我想到的算法就是归并排序了。

    我也关注,等高人。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • BluntBlade
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-28 14:53:062楼 得分:0
    最小二叉堆?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • BluntBlade
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-28 15:15:553楼 得分:0
    给一个基于最小二叉堆的方案:
    第一阶段,向最小二叉堆中插入前一万个浮点数;
    第二阶段,从第一万零一个浮点数开始,将之与最小二叉堆顶部的最小值比较。如果小于这个最小值,把最小值弹出并将新值插入到二叉堆中。重复此过程直到遍历完成。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • BluntBlade
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-28 15:16:474楼 得分:0
    最小二叉堆可以用一维线性数组实现,最后输出时还可以自动排序。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • BluntBlade
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-28 15:17:205楼 得分:0
    “如果小于这个最小值,” -》 “如果大于这个最小值,”
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • hxxwcc
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-28 15:29:376楼 得分:0
    3楼方案应该算是变相的堆排序,因为每次替换过数字后,堆需要进行一次调整,时间复杂度应是O(nlogn)数量级
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • BluntBlade
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-28 15:36:457楼 得分:0
    就是堆排序,还变相……
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • oo
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-28 15:42:378楼 得分:10
    可以用分段的方法,在数据结构版看mathe给的(可能题目不太一样),大致是这样的:

    开一个100万的数组,
    1,读入100万的数据
    2,找到最大的1万个数据,有线性算法的
    3,现在数组里只有1万个数据了,取最小的那个数据 TempMin
    4,再从源数据中读数据,只保存比TempMin大的数据,其他数据丢弃
    5,当数据达到100万或数据读完时,用第二步的方法找到最大的1万个,如果还有数据转3,如数据读完则结束
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • hxxwcc
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-28 16:05:509楼 得分:0
    非典型性堆排序(好吧,我好像创造名词了^.^)

    参照3楼.我想了个思路:
    1.一个数组,大小10000,指针指向头尾部,称min和max
    2.排序下(算法自选吧)
    3.比min指针小的数字,忽略;大于max的,max指针移到min指针位置,min右移一步.介于两者之间的,max指针不动,min右移.
    4.当min指针到达数组最右端(无论max指针是否是在这里),排序一下子,两指针回到原来位置
    5.重复2-4步骤,直至完成

    对于排序的时候,时间复杂度不可避免(但规模是10000的)
    3,4插入时,插入的时间复杂度是o(1)吧,而且能处理的数据应远大于10000个

    因此,这样应该比所选用的排序的算法更快


    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • hxxwcc
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-28 16:07:0110楼 得分:0
    2之前加一步,即填充进去10000个数字

    1.一个数组,大小10000,指针指向头尾部,称min和max
    2.填充进去10000个数字
    3.排序下(算法自选吧)
    4.比min指针小的数字,忽略;大于max的,max指针移到min指针位置,min右移一步.介于两者之间的,max指针不动,min右移.
    5.当min指针到达数组最右端(无论max指针是否是在这里),排序一下子,两指针回到原来位置
    6.重复3-5步骤,直至完成
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • sheenl
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-28 16:59:5311楼 得分:0
    要不这样, 分成1百个组, 每组1000万个数, 全部排序, 取前1万个数, 合成1百万个数, 再排一次序, 取前一万个。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • redleaves
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-28 17:06:0812楼 得分:0
    取1万个数快排.
    剩下的数中取一个与之前数据中最小的比较.如果大于,做排入排序.直到取完剩余的数.
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • oo
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-28 17:09:3813楼 得分:0
    4.比min指针小的数字,忽略;大于max的,max指针移到min指针位置,min右移一步.介于两者之间的,max指针不动,min右移.
    ========================================
    如果新加的比min右移后的小呢?光min右移不能保证min指向的是10000个中最小的,必须把新加入的数插入到数组中才能保证min指向的是最小的
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • oo
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-28 17:12:1314楼 得分:0
    要不这样,  分成1百个组,  每组1000万个数,  全部排序,  取前1万个数,  合成1百万个数,  再排一次序,  取前一万个。
    ============================================================================
    如果排序就是nlogm的算法了(n=10万 m= 每组的个数)

    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • hxxwcc
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-28 17:17:4015楼 得分:0
    to 13楼:
    你忽略了我的排序步骤,这是保证继续进行的关键

    当排序完成时,min在最左端,max在最右端,此时指针所指位置是符合指针名字所代表的含义的.

    当无法继续替换时,我便重新进行排序.
    C/C++ code
    100 105 110 200 min max ------------------ insert 99,omited ------------------ insert 106 106 105 110 200 min max (min指针,即105之前已经为混乱区域,不能在这里插入,必须在min指针之后插入) --------------- insert 201 106 201 110 200 max min -------------- insert 5,omited ----------------- insert 112 106 201 112 200 max min (到达尾部,排序) ------------------ 106 112 200 201 min max --------------
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • hxxwcc
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-28 17:19:4316楼 得分:0
    哦,我发现到我的错误了,让我再想下看能否避免
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • oo
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-28 17:21:2417楼 得分:0
    insert  201
    106 201 110 200
        max min
    --------------
    insert 109如何处理?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • annvily
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-28 17:23:5418楼 得分:0
    不需要排序
    1.选第i(i从1开始,)个数与后面的数对比,
      大于它的写入a[10000][0]
      把他们的位次写入a[10000][1]
    2.如果a[10000][0]未写满,i++,记录开始为空的标识位j
      继续1,把大于第i个数的数写入j及以后的位置,如果还未写满,继续2
    3.如果a[10000][0]写满且超出,i= a[j][1],继续2
    4.刚好写满,结束
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • annvily
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-28 17:28:1619楼 得分:0
    补充:
    第3步:先跟a[j+1][0]...a[9999][1]比,再从a[9999][1]+1位开始比
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • redleaves
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-28 17:40:2720楼 得分:0
    简单测试了一下,10亿个数不到300s可以搞定.
    公司的破AMD 3000+
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • p0303230
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-28 17:42:5121楼 得分:0
    100000 0000
    把数据分成10万个每组,刚好1万组
    求每组的最大值max[],
    然后在1万个最大值中求最小值min,剔除比它小的数

    递归ing

    嘻嘻
    可以
    但效率就不好说了
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • yu_xm
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-28 17:48:4722楼 得分:0
    希尔排序
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • fflyn
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-28 19:19:0023楼 得分:0
    最小堆 + 线形
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • visame
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-28 19:19:2424楼 得分:0
    应该用到外排序的相关算法。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • CAYU
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-28 20:49:2825楼 得分:0
    内存中创建一个10000的数组,然后读取数据,如果大于内存中数组最小的数,就替换这个最小的数,读玩内存中的数组就是你要求的。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • hfgongheguo
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-28 21:00:2226楼 得分:0
    为什么我想到的是用链表结构

    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • kesaihao862
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-28 21:28:0727楼 得分:0
    我想问下oo,你的第2步的线性算法指的是什么?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • kesaihao862
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-28 21:30:2828楼 得分:0
    就是线性算法的具体实现,谢谢
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • buzhihuigai
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-28 21:52:0729楼 得分:0
    使用链表

    维护一个小到大排序的链表。每读一个就按大小插入到链表中相应位置。达到10000个后,每插入一个,就删除链表的第一个,小于第一个节点的数据忽略。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • michney
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-28 21:52:0830楼 得分:0
    不会,关注。。。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • annvily
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-28 21:57:5931楼 得分:0
    没有人支持我,5555
    不需要排序
    比如:
    N个数取一个最大的
    把最大的冒泡到最后就好了
    不需要浪费排序的时间空间
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • visame
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-29 00:43:4032楼 得分:0
    3楼的方法不错。
    如果要对10亿个数全部排序,就要用到初始顺序+归并顺序。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • ghao0
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-29 09:07:4633楼 得分:0
    有值的,更好的在哪?
    -------------------------
    redleaves
    取1万个数快排.
    剩下的数中取一个与之前数据中最小的比较.如果大于,做排入排序.直到取完剩余的数.
    简单测试了一下,10亿个数不到300s可以搞定.
    公司的破AMD  3000+
    -----------------------
    取1万个数快排.
    剩下的数中取一个与之前数据中最小的比较.如果大于,做冒泡插入.直到取完剩余的数.

    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • ghao0
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-29 09:19:5934楼 得分:0
    -----------------------
    取1万个数快排. 
    剩下的数中取一个与之前数据中最小的比较.如果大于,做冒泡插入.直到取完剩余的数.
    --------
    1万个数的存放,如果你用.net或delphi的话建议用arraylist存放
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zbjg
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-29 09:21:5435楼 得分:0

    1. 创建长度一万的二叉树。
    2. 遍历剩余的浮点数,若大于最小值则插入二叉树并删除最小的节点,否则略过。

    这基本上是一个较优的算法,复杂度为: 千万级(一万的排序) + 140亿(插入二叉树)
    从上面的粗略计算可以知道,二叉树的插入是最耗时的,因此如果能提前确定一个尽可能大初始数组则可能大大减少比较次数。
    所以有必要对原始数据进行一些预算:
    1. 将所有数据进行分组
    2. 计算各组平均值
    3. 对平均值排序
    3. 以最大的做为初始数组,建立有序二叉树
    4. 以平均值从大到小的顺序往初始二叉树中插入
    这样就有可能避免很大比例的比较运算,当然对是否值得进行预算,以及预算到什么程度还需要根据原始数据的情况而定。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • superdullwolf
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 3

    发表于:2008-02-29 09:29:4336楼 得分:0
    有10亿个浮点数,从中找出1万个最大的数。

    二叉树,循环把10亿个浮点数往树里塞,二叉树只允许有1万个元素,小的塞不进去,大的塞进去把小的挤掉。

    复杂度小于O(n*logn)
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • superdullwolf
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 3

    发表于:2008-02-29 09:31:4137楼 得分:0
    思路和zbjg 一致。

    复杂度小于O(n*logm)
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • redleaves
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-29 09:36:0538楼 得分:0
    又改进了一下前面的算法.
    1.建立A,B两个排序表.
    2.取1万个数快排.放到A表中.并记下最小值min,及min所在的表t=A
    3.取一个数f与min比较,小于则重复3.直到取完转7
    4.将t中的min删除.并将f插入到A,B两个表中,大小较小的一个里.
    5.比较A,B表中的最小值,并记下最小值min,及min所在的表t=?
    6.转到3.
    7.将A,B表做归并.

    这种算法我验证了以下,处理1.1316亿个数据只要23秒.而用我之前说的那个算法则要28秒.
    其中,仅仅是读文件就用了18秒.可见,数据处理的速度提高了1倍.
    而且这个算法为了简单只用了A,B两个表,实际上可以推广到N个表,理论上,在N=sqrt(num),num为要取的数据个数时,性能会达到最优.说性能可以至少再提高一倍.
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • redleaves
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-29 10:12:4039楼 得分:0
    晕了....
    改用icl 10.1编译一下,只用18.8秒就可以搞定,读文件要17.8秒.
    改用gcc 4.2.3编译一下,只用17.6秒就可以搞定,读文件要16.8秒.
    也就是说处理10亿个数据只要10秒不到.还有170~180秒在读文件...
    看来还是换编译器来得更值一点儿啊~^_^
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • pzhuyy
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-29 10:13:1840楼 得分:0
    关注。。。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • hxxwcc
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-29 10:20:0441楼 得分:0
    39楼你的1亿多双精度数字文件大小是多大?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • wjlsmail
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-29 10:39:4542楼 得分:0
    Support Layer 8:

    可以用分段的方法,在数据结构版看mathe给的(可能题目不太一样),大致是这样的:

    开一个100万的数组,
    1,读入100万的数据
    2,找到最大的1万个数据,有线性算法的
    3,现在数组里只有1万个数据了,取最小的那个数据  TempMin
    4,再从源数据中读数据,只保存比TempMin大的数据,其他数据丢弃
    5,当数据达到100万或数据读完时,用第二步的方法找到最大的1万个,如果还有数据转3,如数据读完则结束


    If change the base array to 10w or 2w, better?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • r_swordsman
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-29 10:53:3343楼 得分:0
    又改进了一下前面的算法.
    1.建立A,B两个排序表.
    2.取1万个数快排.放到A表中.并记下最小值min,及min所在的表t=A
    3.取一个数f与min比较,小于则重复3.直到取完转7
    4.将t中的min删除.并将f插入到A,B两个表中,大小较小的一个里.
    5.比较A,B表中的最小值,并记下最小值min,及min所在的表t=?
    6.转到3.
    7.将A,B表做归并.

    这种算法我验证了以下,处理1.1316亿个数据只要23秒.而用我之前说的那个算法则要28秒.
    其中,仅仅是读文件就用了18秒.可见,数据处理的速度提高了1倍.
    而且这个算法为了简单只用了A,B两个表,实际上可以推广到N个表,理论上,在N=sqrt(num),num为要取的数据个数时,性能会达到最优.说性能可以至少再提高一倍.

    ------------------------------------------

    redleaves  把源码贴来我运行一下
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • hxxwcc
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-29 11:19:3344楼 得分:0
    恩,顶一下43楼,请redleaves贴一下

    我这里空跑1000W(文件读至double变量)的数字是要10秒..可能慢了一点..
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • YanDong_8212
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 3

    发表于:2008-02-29 11:25:2645楼 得分:0
    B+树
    首先构造B+树,然后从最大叶结点向左遍历一万次.
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • tncqsy
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-29 11:30:2146楼 得分:0
    感觉 hxxwcc 的排序很好,只是进来的数字需要和min后面的比较,如果大于min小于min后面的,则替换min的值就行,min的位置不用移动
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • redleaves
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-29 11:33:3447楼 得分:0
    TO hxxwcc,我用的是单精度的浮点数.文件是一个400多MB的二进制文件.

    另外,我又改了几行不相关的代码.VC8编译出的程序运行结果和ICL差不多了...呵呵.有时候编译器也不太可靠.

    我的代码如下:
    C/C++ code
    #include <stdio.h> #include <set> #include <time.h> int main( int argc, char *argv[] ) { std::set<float> A,B; std::set<float> *t; size_t count = 0; clock_t c = clock(); FILE *fp = fopen( argv[1], "r+b" ); // 取1w个数并排序 while( !feof(fp) && A.size()<10000 ) { float f; fread( &f, sizeof(f), 1, fp ); count++; A.insert( f ); } float min = *A.begin(); t = &A; // 取剩下的数进行插入 while( !feof(fp) ) { float f; count++; fread( &f, sizeof(f), 1, fp ); if ( f > min ) { if ( A.find( f ) != A.end() || B.find( f ) != B.end() ) { continue; } t->erase( t->begin() ); if ( B.size() < A.size() ) { B.insert( f ); } else { A.insert( f ); } if ( *A.begin() > *B.begin() ) { t = &B; min = *B.begin(); } else { t = &A; min = *A.begin(); } } } { // 合并两个表 std::set<float>::iterator iter = B.begin(); while( iter != B.end() ) { A.insert( *iter ); iter++; } } c = clock() - c; fclose( fp ); std::set<float>::iterator iter = A.begin(); while( iter != A.end() ) { printf( "%e\n", *iter ); iter++; } printf( "count:%d\ntime:%dms\n", A.size(), c ); return 0; }

    说明一下,为了方便,我用set容器来保存排序结果.所以第一步没用快排.
    而且关于float的比较,我没有做特殊处理.
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • tenderghost
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-29 11:35:1348楼 得分:0
    不会,关注学习一下。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • w_anthony
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-29 12:39:5649楼 得分:0
    个人认为,最小的算法复杂度应该是O(n*logm),毕竟以下两点难以避免:
    1、10000个最大的数之间需要排序,不可避免的是O(log(m))。
    有人说我不需要排序,那么请问当原先最小的数被挤掉后,你怎么找到第二小的数呢?
    有人说我可以保存大小顺序的序号,这样就可以很快的找到第二小的数,那么当新数挤掉旧数时,你的序号更新的复杂度又是多少?
    如果这个步骤无法避免,干脆直接用std::set好了。

    2、10亿个数必须遍历一遍,不可避免的是O(n)。

    那算法复杂度就是O(n*logm)了,除非不是基于以上两点方法的。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • rediscovery
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-29 12:44:0050楼 得分:0
    呵呵,我看这个问题大家都有很多想法,但谁的算法最优?大家能否评价的出来,这样讨论下来没有结果的哦,我想应该是谁的比较次数最少,还有就是数据移动最少的最优吧。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • tonyswe
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-29 13:50:2051楼 得分:0
    事后统计分析
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • jezhee
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-29 14:04:1352楼 得分:0
    正在看数据结构与算法分析(C++版), 这个问题在一开始就提出来了,不过解答在很后面,还没看到,不过它事先给出了最优解的时间复杂度是线性的 O(N)。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • laznhr
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-29 14:17:4253楼 得分:0
    为什么看了这么多。越看越乱了。。这里边不是有几个问题的吗?
    第一:这数组要不要经过排序,如果要排序,怎 样排法最好。这里又有几个小问题:
        1,如果不用分组的话排序那最快排序法就是最好的算法。
        2,如果要分组的话,比如1万一组,就要分10万组,每一次都要排一次序。然后就是要解决这10万组中如何找出最大的一万条数。
    第二:如果不用排序,那就是要找出最大的一万个值,是在10亿中调用查最大值一万次。

    现在最不明的就是一:假如内存是无限大时,到底是为10亿条记录排序快?还是查一万次最大值快呢?这是最关键。
                    二:内存有限时,分组排序到底肯定是不完美的顺序表,那我们如何有好的算法从中找到最大的一万个值呢?
                      我觉得这个分组后找一万个最大值是很难的。
    -------------------------------------------------------------------
    还有一点。。10亿这么大的数据,结果是很随机性的,一个数值在头和在尾可以使结果差N多个时间。所以如果大家使用的数据库不一样时,等程序运行后是没有可比性的。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • hxxwcc
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-29 15:25:1554楼 得分:0
    我把我改过后的那个算法贴一下,并说明一下效率.参照我在9和10楼,以及16楼的发言

    1.一个数组,用于读取文件,每次读进去10000个数字
    1.一个链表,大小10000,指针指向头尾部,称min和max(事实是指向尾部前一个位置)
    2.数组的数字读进链表,并且排序一下
    3.数组读文件,10000个
    4.10000个数字插入到list中.其中,1)比min指针小的数字,忽略;2)大于max的,max指针移到min指针位置,min右移一步.3)介于两者之间的,max指针不动,从min指针出发,寻找此数字应该插入的位置,插入.然后min指针右移,原来指的位置失效.4)当min指针到达链表尾部(max指针不可能在这里如果min能够到达),min回到初始位置
    5.重复3-4直至完成i

    分析效率:
    明显算法的效率是在第4步上来决定.
    (1).4中,(不管4)步) 1),2)步是O(1),3)ASL=5000
    (2).3)出现的多少影响了算法的整体效率.事实上,当赛选进行到一定时间后,绝大部分的数字应该是走的1)情况,所以规模越大,算法应该越快
    (3)此算法和KMP一样是"不回头的"算法
    (4)与3楼的算法进行比较.我这里有优势的是4中的2)情况,此点比他的算法优秀;但是3)情况效率不如他
    (5)3)应该可以改进

    实际结果:
    规模 创建文件 空跑文件 所用时间 实际时间(单位均为秒)
    1e7  30(大概) 10      20        10
    5e7  118      54      62        8

    也就是说,5千万的规模甚至比1千万用时间小...
    和前面分析吻合(不是必然)
    我是通过 <ctime>里面的函数来计算时间的,秒级别

    下面贴的代码不能直接运行,因为用到了一些未贴出来的东东
    大家看一下就算了哈^.^

    C/C++ code
    void top10000(void) { FileRelated f; Counter<int> lengthForReadFile; vector<double> vectorForRead(VECTOR_SIZE); list<double> listForInsert(VECTOR_SIZE); /*used for create-file mode f.CreateFile(); */ /*used for only-read-file mode for(Counter<int> read;read.NotArrived(f.LENGTH);read.Count(VECTOR_SIZE)) f.ReadFile(vectorForRead.begin(),VECTOR_SIZE); return; */ f.ReadFile(vectorForRead.begin(),VECTOR_SIZE); lengthForReadFile.Count(VECTOR_SIZE); //1stStep: copy(vectorForRead.begin(),vectorForRead.end(),listForInsert.begin()); //2ndStep: sort(vectorForRead.begin(),vectorForRead.end()); list<double>::iterator minPtr=listForInsert.begin(); list<double>::iterator maxPtr=listForInsert.end(); --maxPtr; while(lengthForReadFile.NotArrived(f.LENGTH)) { //3rdStep: f.ReadFile(vectorForRead.begin(),VECTOR_SIZE); lengthForReadFile.Count(VECTOR_SIZE); //4thStep: for(vector<double>::iterator iter=vectorForRead.begin(); iter!=vectorForRead.end(); ++iter) { if(minPtr==listForInsert.end()) minPtr=listForInsert.begin(); else if(*iter>=*maxPtr) { maxPtr=minPtr++; *maxPtr=*iter; } else if(*iter>*minPtr) { list<double>::iterator replacePtr= find_if(listForInsert.begin(),listForInsert.end(), bind2nd(greater<double>(),*iter)); listForInsert.insert(replacePtr,*iter);//before replacePtr listForInsert.erase(minPtr++); } } } //nthStep: copy(listForInsert.begin(),listForInsert.end(),ostream_iterator<double>(cout," ")); }
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • SoftBomb
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-29 15:29:3255楼 得分:0
    快速选择
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • hxxwcc
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-29 16:02:3956楼 得分:0
    [CODE=C/C++]
    规模  创建文件  空跑文件  所用时间  实际时间(单位均为秒)
    1e7    30(大概)  10            20        10
    5e7    118        54            62        8
    1e8    164(iso:app)55,51(空跑了2次)62      7-11
    [/CDOE]

    我等会在1e8的规模上更换一下所采用的文件,看看是否还能到达这个速度
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • liangbch
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-29 16:18:3557楼 得分:0
    n= 10亿
    m= 1万

    1.开2个数组,数组A,和数组B
    2.前1万个读入数组A,快排 ,复杂度m*log(m), 并找出最小的数min

    3.检查其余的数,如果小于min,放入数组B,如果数组B满 或者 所有的数取完 转4
    4.对数组B快排, 复杂度m*log(m)
    5.对数组A和数组B,进行归并排序,最大的m个数仍留在数组A,置数组B为空,复杂度m
    6.转步骤3


    1.最坏情况,n的数中,数组分布为从小到大方式,越往后越大。则数组B被填满的次数为n/m,因此4步骤和5 需要作n/m次,
      每次需要 m*log(m)+m次操作,忽略第二项。 总的复杂为 n/m*m*log(m)=n*log(m)

    2.一般情况,越到后来,数据被放入数组B的几率越小,因此数组B被填满的次数远小于n/m,故总的复杂度远小于n*log(m)

    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • dreamsdark
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-29 16:36:0258楼 得分:0
    这不是群硕的笔试题吗?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • hxxwcc
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-29 16:40:5759楼 得分:0
    C/C++ code
    规模 创建文件 空跑文件 所用时间 实际时间(单位均为秒) 1e7 30(大概) 10 20 10 5e7 118 54 62 8 1e8 164(iso:app)55,51(空跑了2次)62 7-11 1e8(another file)251 104 118 14



    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • sknice
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-29 17:44:0860楼 得分:0
    厉害,多是牛人
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zhongweiwen
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-02-29 19:52:2261楼 得分:0
    钟伟文先生『转标题』:核心生存力让企业活得更加稳健

      作者:邓正红

      来源:博锐管理在线

    在这样一个高度不确性的时代,竞争程度的日趋激烈以及技术飞速进步给企业生存带来的新挑战,也加重了企业未来生存的难度。而随着买方话语权力的越来越强大,客户的权力被提升到至高无上的地位,企业的生存方式也由此而发生变化,客户越来越要求量身定制的产品和服务,响应客户需求及市场变化的能力变得比企业规模更为重要。

    那么,企业应该选择什么样的生存方式,才能应对高风险的市场环境变化?企业生存管理专家、企业未来生存管理理论创始人邓正红认为,核心生存力就是企业所独有的生存方式,这种生存方式超越核心竞争力,而且贯穿企业生命全过程,是支撑企业一辈子永恒的生存力量。核心生存力的培育和形成,遵循邓正红企业未来生存管理理论的“两合原理”。企业按照未来生存规律,将环境的变化与企业不变的追求融合为一体,同时将核心理念生发的软实力和核心能力构筑的硬实力紧紧捏合在一块,便形成了企业牢不可破的核心生存力。

    三星以往靠模仿别人制造廉价产品,跟在索尼后面亦步亦趋。但是,近几年来,三星依托发展自我技术和品牌而迅速崛起,一跃成为全球最大的内存芯片、纯平显示器和彩色电视制造商之一。现在,三星更是超过西门子成为全球第三大手机制造商,仅次于诺基亚和摩托罗拉。

    回顾三星的发展历史,三星集团的崛起强大与三星的将战略重点放在核心生存力的培育上有重大关系。李健熙在1993年所提出的“新经营运动”对于当时的三星意义深远。“新经营运动” 的核心是强调三星要从以数量为主的经营模式转到以质量为主的经营模式,在追求质量的基础上确保企业的核心生存力,这样企业才能长足发展。邓正红企业未来生存管理理论认为,企业软实力包括企业文化、经营模式、社会责任和企业品牌等四大内容,而经营模式是企业软实力向核心生存力转化的最关键项目。这里要注意的是,三星的经营模式变革实际上就是适应市场环境变化对企业软实力的硬化,这个思路与核心生存力的发展轨迹不谋而合。

    李健熙的“新经营运动”理念使得当时韩国企业界从一致认可的“量经营”思想,开始向“质经营”思想转变。韩国爆发金融危机后,“新经营”思想成为三星抢先一步完成调整的原动力。李健熙在“新经营运动”的基础上,按照变与不变相统一的企业未来生存规律,提出了三星集团生存方式的战略转型,使三星能够对市场变化作为出迅捷的反应。

    在新的经营战略指导下,三星立志成为21世纪名副其实的世界超一流企业,将电子、金融及服务业确定为其核心业务,成长为引导信息时代的“数字企业”,经营核心转向以自有品牌、数字技术为中心。为达成此目标,三星在生存方式调整与未来生存战略上采取以下两项措施:一是将企业生存视点转入最有可持续增长潜力的行业;二是按照核心生存力的要求确立以电子产品和电信产品为主打业务的核心资源战略。

    在新经济浪潮席卷全球时,三星集团的领导人以对高新技术的高度敏感,看中了一个最有可持续增长潜力的行业——生物工程。三星在大力发展电子信息化产业的同时,加大资源投入,努力拓展在生物工程方面的进展。同时,三星集团也从韩国政府处获得了从财政到金融、从知识产权转让到人力资源培训、从信息供应到出口便利等种种国家层面的支持,这也极大地增强了三星集团的综合生存能力,并使生物工程产业成为三星全球销售业务中的一个新亮点。

    三星曾经也“贪大求全”,涉足过汽车、建筑、化工等传统领域,不仅使大量资金进入无效运营状态,而且无法走出产品在狭窄的国内市场上低价销售而几乎不赢利的局面。痛定思痛之后,三星集团果断地调整了自己的主打业务,完成了由传统的重工业向新型工业的产业结构转轨。三星放弃了汽车业务,因为这一产品在韩国已经严重过剩;建筑业务也主动萎缩,因为韩国在世界杯之后实在没有什么新的大规模建设机会了;而对重化工业三星也开始出让部分股权,以换取宝贵的流动资金。在放弃重工业的同时,三星确立了以电子产品和电信产品为主打业务的战略,并且每周都有新产品问世。正是由于成功的战略转型,使三星集团从此在全球的电子领域中确立了自己的领导地位,在500强中排名也不断趋前。

    企业生存管理专家、企业未来生存管理理论创始人邓正红认为,企业内外环境都存在着潜在的变化规律,如果企业能够敏锐地捕捉到这种变化之势,并能乘势而上有所作为,就能主宰企业未来生存命运。但是,潜在的变化之势往往不易被察觉,它是一种细微的慢性的有规律的事态发展,如果企业不能及时发现,错过了驾驭这种势头的良机,很可能给企业造成巨大的损失,甚至灭顶之灾。

    现在,我们正经历一个多变的社会,体制的变革把我们从一条风平浪静的计划经济的小溪推向了充满惊涛骇浪的汪洋。这种变化是彻底的、革命性的,又是客观的,必然的。这种变化给企业经营带来了极大的风险压力,也给企业发展带来了难得的机遇,关键是我们如何正确看待。我们一经体会到来自各方面的压力,就预示事物的变化已经开始,就要求立刻采取行之有效的措施予以应对。

    从三星集团十年来的发展史中,我们可以看出,李健熙早就意识到外部市场环境正在发生着剧烈的变化,而这种变化对企业生存发展的影响将是巨大的,所以他所提出的“三星危机论”以及由此核心生存力战略,让三星在这个充满不确性的时代中,发展的步履显得更加稳健有力。钟伟文先生
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • luckysnake
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-01 00:45:1962楼 得分:0
    都是高人啊,刚入行,呵呵,学习一下
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • tang_cheng
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-01 03:11:2263楼 得分:0
    可以建立一个总长度1万的数组,然后建立一个变量记录当前使用的数组长度。当读取一个数据时候,就把这个数和数组中最后一个数比较,如果小于这个数的话,就忽略掉。如果大于这个数,则用二分法找到这个数在数组中的相应位置后,将数据插入,如果数组长度已经达到1万,则将最后一个数据删除。这个过程如果是用C语言实现的话只要采用内存移位方式(memmove),速度非常快。这种方式只要一次性扫描数据,时间复杂度为O(n),对于查找由于采用二分法查询,时间复杂度为O(log n)。不过其整体时间复杂度由数据的分布情况决定,如果大数据比较靠前的话,那查找和移位的次数会比较少,否则就会比较多。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • tang_cheng
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-01 03:33:1964楼 得分:0
    具体算法代码为(仅参考,未调试):

    int   fund_func(   const   void   *elem1,   const   void   *elem2   )
    {
            float   key   =   *(float*)elem1;
            float   start   =   *(float*)elem2;
            float   end       =   *(float*)(elem2   +   1);
            if(key   <   start)return   -1;
            if(key   >   end)return   1;
            return   0;
    }

    void   main()
    {
            int   len   =   0;
            float   arr[10000];

            for(i   =   0;   i   <   1000000000;   i   ++)
          {
                    //   读取数据
                    float   f   =   read_value(i);

                    //   如果读取的数据比当前列表中最小的数据小则忽略
                    if(len   >   0   &&   arr[len   -   1]   > =   f)
                            continue;

                    //   如果列表中无数据则直接插入
                    if(len   ==   0)
                            arr[len   ++]   =   f;

                    //   如果列表中只有一个数据则直接插入或直接交换
                    else   if(len   ==   1)
                    {
                            if(arr[0]   >   f)
                                  arr[len   ++]   =   f;
                            else
                            {
                                  arr[len   ++]   =   arr[0];
                                  arr[0]   =   f;
                            }
                    }

                    //   如果列表中超过两个数据则搜索插入
                    else
                    {
                            //   二分法搜索到相关的插入位置
                            float*   pos   =   (float*)bsearch(&f,   arr,   len   -   1,   sizeof   arr[0],   find_func);
                            int   i_pos     =   pos   -   arr;
                           
                            //   将插入位置后的数据移位(如果长度为10000则移位的数据个数少一,以便移出最后一个数据)
                            memmove(pos,   pos   +   1,   sizeof(float)   *   (len   -   i_pos)   -   (len   ==   10000));
                    }
            }
    }
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • tang_cheng
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-01 03:38:0065楼 得分:0
    代码纠错:

    //  如果列表中超过两个数据则搜索插入
    else
    {
        //  二分法搜索到相关的插入位置
        float* pos = (float*)bsearch(&f, arr,len - 1,sizeof arr[0], find_func);
        int i_pos = pos - arr;
                         
        //  将插入位置后的数据移位(如果长度为10000则移位的数据个数少一,以便移出最后一个数据)
        memmove(pos, pos + 1, sizeof(float) * (len - i_pos) - (len == 10000));
       
      // 保存当前数据
      *pos = f;

      // 累加计数器
      len += (len < 10000);
    }
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • flyingscv
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-01 06:14:2166楼 得分:0
    用最小堆,只需要建堆过程,复杂度为o(n)
    且堆大小 <=10000,,应该是非常好的算法了
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • guoqiangone
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-01 08:04:2367楼 得分:0
    oo,学习
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • axolo
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-01 08:48:5268楼 得分:0
    CSDN牛人
    学习
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • hxxwcc
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-01 08:51:4469楼 得分:0
    改正点小BUG,和改进一下54楼我的算法:
    max指针不用回到min的位置,也不用检查min是否到达尾部,直接在尾部插入,在头部消除就是了
    C/C++ code
    // // File: top10000.cc // Created by: cc <tireless-heart@163.com> // Created on: Fri Feb 29 12:26:53 2008 // #include "top10000.h" #include <iostream> #include "FileRelated.h" #include <vector> #include <list> #include <iterator> #include <algorithm> #include "Counter.h" using namespace std; const static int VECTOR_SIZE=10000; void top10000(void) { FileRelated f; Counter<int> lengthForReadFile; vector<double> vectorForRead(VECTOR_SIZE); list<double> listForInsert(VECTOR_SIZE); //1stStep: f.ReadFile(vectorForRead.begin(),VECTOR_SIZE); lengthForReadFile.Count(VECTOR_SIZE); copy(vectorFor.begin(),vectorForRead.end(),listForInsert.begin()); //2ndStep: sort(vectorForInsert.begin(),vectorForInsert.end()); list<double>::iterator minPtr=listForInsert.begin(); list<double>::iterator maxPtr=listForInsert.end(); --maxPtr; while(lengthForReadFile.NotArrived(f.LENGTH)) { //3rdStep: f.ReadFile(vectorForRead.begin(),VECTOR_SIZE); lengthForReadFile.Count(VECTOR_SIZE); //4thStep: for(vector<double>::iterator iter=vectorForRead.begin(); iter!=vectorForRead.end(); ++iter) { if(*iter>=*maxPtr) { listForInsert.insert(listForInsert.end(),*iter); ++maxPtr; listForInsert.erase(minPtr++); } else if(*iter>*minPtr)//*minPtr<*iter<*maxPtr { list<double>::iterator replacePtr= find_if(listForInsert.begin(),listForInsert.end(), bind2nd(greater_equal<double>(),*iter)); listForInsert.insert(replacePtr,*iter);//before replacePtr listForInsert.erase(minPtr++); } } } //5thStep: copy(listForInsert.begin(),listForInsert.end(),ostream_iterator<double>(cout," ")); }
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • hxxwcc
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-01 08:59:2270楼 得分:0
    我晕,还是有BUG,69L代码作废,CSDN不能修改太不爽了:
    C/C++ code
    // // File: top10000.cc // Created by: cc <tireless-heart@163.com> // Created on: Fri Feb 29 12:26:53 2008 // #include <iostream> #include <vector> #include <list> #include <iterator> #include "top10000.h" #include "Counter.h" #include "FileRelated.h" using namespace std; const static int VECTOR_SIZE=10000; void top10000(void) { FileRelated f; Counter<int> lengthForReadFile; vector<double> vectorForRead(VECTOR_SIZE); list<double> listForInsert(VECTOR_SIZE); //1stStep: f.ReadFile(vectorForRead.begin(),VECTOR_SIZE); lengthForReadFile.Count(VECTOR_SIZE); sort(vectorForRead.begin(),vectorForRead.end()); copy(vectorForRead.begin(),vectorForRead.end(),listForInsert.begin()); //2ndStep: list<double>::iterator minPtr=listForInsert.begin(); list<double>::iterator maxPtr=listForInsert.end(); --maxPtr;// while(lengthForReadFile.NotArrived(f.LENGTH)) { //3rdStep: f.ReadFile(vectorForRead.begin(),VECTOR_SIZE); lengthForReadFile.Count(VECTOR_SIZE); //4thStep: for(vector<double>::iterator iter=vectorForRead.begin(); iter!=vectorForRead.end(); ++iter) { if(*iter>=*maxPtr) { listForInsert.insert(listForInsert.end(),*iter); ++maxPtr; listForInsert.erase(minPtr++); } else if(*iter>*minPtr)//*minPtr<*iter<*maxPtr { list<double>::iterator replacePtr= find_if(listForInsert.begin(),listForInsert.end(), bind2nd(greater_equal<double>(),*iter)); listForInsert.insert(replacePtr,*iter);//before replacePtr listForInsert.erase(minPtr++); } } } //5thStep: copy(listForInsert.begin(),listForInsert.end(),ostream_iterator<double>(cout," ")); }
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • leer168
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-01 10:01:0271楼 得分:0
    都是大虾啊,菜鸟给你们敬礼了
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • liberd
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-01 12:02:3772楼 得分:0
    我学的是Java,Java里有个快速排序,先进行全部排序,然后再取相应的项!
    算法我现在写不出来!我回学校查查再写出来!
    你可以给我发个人信息!我再上网时写给你!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • dzq138
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-01 13:47:0873楼 得分:0
    ..
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • bwangel
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-01 14:11:0774楼 得分:0
    这个,好象不存在计算次数小于10亿次的算法吧?

    也许我孤陋寡闻,但即使你比较了9,999,999,999个数,也难保那最后一个数不是最大的。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zhiang75
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-01 15:20:4975楼 得分:0
    ..使用基数排序,无论是在内存,还是在文件中我就不考虑了,各位都是C++高手C#的代码应该很容易看懂..
    http://blog.csdn.net/zhiang75/archive/2007/11/07/1872006.aspx
    此算法的复杂度为O(n)
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • tongmux55
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-01 15:58:4776楼 得分:0
    一、首先建立1w个10w容量的数组,将它们进行排序;
    二、清除每个数组中较小的9万个浮点数(减小下一步比较数的数量);
    三、比较这一万个数组的最大值得到极大值(如数组A中的最大值)放到一个数组(B)中,并将数组(A)的最大值清除;
    四、重复三的动作,直到数组B中的count为1万;
    五、比较结束;
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • tinystone
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-01 16:00:3677楼 得分:0
      18楼:一百万个数,一定是外部排序了,这样一遍遍地读,速度会不会太慢....
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • tongmux55
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-01 16:03:2578楼 得分:0
    上说有点错误,二、清除每个数组中较小的9万个浮点数(减小下一步比较数的数量);
    第二步是为了减小内存的占用率
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • w_anthony
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-01 16:15:1479楼 得分:0
    基数排序在这里的效率体现不出来,原因如下:
    1、假设n个数,划分为m列,每列k个位置(虽然是要找10000个数,但划分还是包含所有情况)。
    2、由于不可能给每列都分配好足够的空间来直接定位位置,所以在每列中找位置还是需要查找算法,查找复杂度为O(log(k))。
    3、那么一次插入的复杂度为O(m*log(k))。
    4、有n个数需要执行n次,那么复杂度就是O(n*m*log(k)。
    这里n为10亿,m可以选8,k相应选16,而n在各种算法中不可避免,所以比较一下m*log(k)就差不多了,这种选择下,m*log(k)=32,而实际上由于不太可能每次都要查找log(k)次,应该是远小于32,但要大于8。

    而堆排序这类的n*log(m),m为10000,log2(10000)约为13,到后期还可能不需要执行插入,效率可能还要比基数排序好。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • w_anthony
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-01 16:18:2080楼 得分:0
    76楼要用多少内存阿?即便是有清除操作,这么大的内存清除也是很费时间的啊。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zhiang75
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-01 17:32:4581楼 得分:0
    To w_anthony :
    由于不可能给每列都分配好足够的空间来直接定位位置,所以在每列中找位置还是需要查找算法,查找复杂度为O(log(k))。
    这个我不赞同,用基数为什么还要查找?为什么不可以直接定位?
    C# code
    public class FloatRadixSortItem : RadixSortItem ...{ float value; public float Value ...{ get ...{ return value; } } public FloatRadixSortItem(float Value) ...{ value = Value; if (value < 0) ...{ IsNegative = true; } else ...{ IsNegative = false; } Data = new byte[4]; byte[] temp = BitConverter.GetBytes(value); uint bi3 = temp[3]; bi3 <<= 8; bi3 += temp[2]; bi3 <<= 8; bi3 += temp[1]; bi3 <<= 8; bi3 += temp[0]; if (value < 0) ...{ bi3 = ~bi3; } uint bi1 = bi3 & 0x7F800000; Data[3] = (byte)(bi1 >> 23); bi1 = bi3 & 0x7FFFFF; Data[0] = (byte)(bi1 & 0xFF); bi1 >>= 8; Data[1] = (byte)(bi1 & 0xFF); bi1 >>= 8; Data[2] = (byte)(bi1 & 0xFF); DataLen = 4; } public override string ToString() ...{ return value.ToString() + " " + Data[0].ToString("X2") +" " + Data[1].ToString("X2") +" " + Data[2].ToString("X2") +" " + Data[3].ToString("X2"); }

    这里很清楚的写明了如何将一个float 转换为byte数组
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zhiang75
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-01 17:37:4682楼 得分:0
    To w_anthony :
    假设n个数,划分为m列,每列k个位置

    作为基数排序我承认n,m,但是K我不认同,这个k应该是一个插入弹出为O(1)的链表实现.
    因此基数排序的时间复杂性应该是O(n*m)
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • w_anthony
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-01 19:04:4783楼 得分:0
    To zhiang75:
    如果要直接定位,那就必须要预先把16个位置都分配好,那么就需要16的8次方个位置进行预先分配,以目前的计算机配置,内存不够用……
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • sknice
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-01 19:08:1884楼 得分:0
    帮顶
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • w_anthony
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-01 19:21:0585楼 得分:0
    补充,如果是在需要的时候再一次性分配16个位置,似乎可以达到O(1)的算法复杂度,但是由于内存原因,从里面删除节点的时候,就要把相关内存也释放掉,这样就要扫描一遍同列的其他位置是否为空来决定本身是否可以删除,删除的代价会相应变大。不过到后期基本上很难插进来,所以删除操作也不会太多,这样一来算法复杂度就不好计算了,或许和堆排序不相伯仲。不过堆排序最差也是13,而且内存占用率低,要是真正测试起来,我个人认为可能还是堆要快一点。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • JackLucifer
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-01 20:32:4486楼 得分:0
    再次发现,原来自己什么都不会。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • JYeung
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-01 21:27:1687楼 得分:0
    用PIORITY QUEUE,时间为 N LOG M, N = 10亿, M = 10000
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zhiang75
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-01 21:37:2388楼 得分:0
    To:w_anthony
    可以和你探讨这个问题,我感觉非常荣幸.
    首先基数排序考虑问题的方式,和一般方式不太一样,
    假定我们讨论的是float格式,这种数据是存储在32位的存储空间中的.
    按浮点格式标准
    31位是符号位,1表示该数为负,0反之。
    30-23位,一共8位是指数位。
    22-0位,一共23位是尾数位。
    不考虑符号位,可以将其拆分为4个Byte,其中指数1Byte,尾数用其余3Byte.
    需要认可的的是指数越大数值越大,指数一样,尾数越大数值越大.
    因此先准备256个桶历遍所有数据,将指数为1的仍到一号桶中,将指数为2的仍到二号桶中...指数为n的仍到n号桶中..
    桶的结构为二进制文件.
    同时准备256个计数器,一号桶扔入一个数一号计数器就加一...n号桶中扔入一个数n号计数器就加一.
    统计256个计数器的数据,使用降序统计满足这个条件,就是(255计数器+254计数器+253计数器+n计数器)>=1W
    你需要1W的数据就在这些桶中,剩下如何做,是继续基数排序,还是快排,还是堆排,随你了..总之这样过滤完的数据量将很小,内存完全可以应付了.

    我越来越感觉这是这个问题的标准答案.

    它考了浮点的格式,以及基数,或者是桶排序的综合运用


    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zhiang75
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-01 21:50:4089楼 得分:0
    To:w_anthony
    预先把16个位置都分配
    这16是从哪里来的啊?可以帮我解释一下吗?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zhiang75
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-01 21:58:2590楼 得分:0
    我认为这个问题可以盖棺定论了.^_^....自以为很NB....
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • 39457760
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-01 22:08:0091楼 得分:0
    发段代码,比较次数是2*n
    思路同8楼的差不多

    VC6编译的,P4机器上运行30秒左右
    C/C++ code
    #include <vector> #include <iostream> #include <fstream> #include <iomanip> #include <algorithm> #include <functional> #include <cmath> #include <windows.h> using namespace std; size_t M = 10000; size_t N = 2; size_t DATA_LENGTH=5*100*100*M; size_t INNER_DATA_LENGTH=N*M; bool read_data(ifstream& ifile, double* data,size_t length) { ifile.read((char*)data,length); return true; } bool read_data(double* data,size_t length) { static int j=0; if(j++)return true; for(size_t i=0; i<length; i++) { data[i] = rand(); } return true; } bool createdata(ofstream& out) { if(!out.is_open()) return false; double* data = new double[N*M]; for(size_t i=0; i<DATA_LENGTH/INNER_DATA_LENGTH;i++) { for(size_t i=0; i<INNER_DATA_LENGTH; i++) { data[i] = sin(rand())*rand(); } out.write((char*)data,INNER_DATA_LENGTH*sizeof(double)); } delete[] data; return true; } void solver(ifstream& ifile) { if(!ifile.is_open()) { cerr<<"无法打开文件"<<endl; return; } //记录从数据文件读入的数据 double* data=new double[N*M]; //每次从data中取出M个最大的数放入这个数组中[M+index,M+index+M), double* better_data=new double[N*M]; int index = 0; if(better_data==NULL||data==NULL) { cerr<<"内存不足"<<endl; delete[] data;delete[] better_data; return; } for(int i=0; i<DATA_LENGTH/INNER_DATA_LENGTH;i++) { while(index<INNER_DATA_LENGTH) { read_data(ifile,data,INNER_DATA_LENGTH); //read_data(data,INNER_DATA_LENGTH); nth_element(data,better_data+M,data+INNER_DATA_LENGTH,greater<double>()); copy(data,data+M,better_data+index); index+=M; } nth_element(better_data,better_data+M,better_data+INNER_DATA_LENGTH,greater<double>()); index=M; } delete[] better_data; delete[] data; } int main(int argc, char* argv[]) { const char* fname="test.dat"; //生成测试数据 ofstream ofile(fname,ios::binary|ios::out); createdata(ofile); ofile.close(); //求解问题 ifstream ifile("test.dat",ios::binary|ios::in); ifile.seekg(0,ios_base::beg); DWORD start = GetTickCount(); solver(ifile); DWORD end = GetTickCount(); cout<<end-start<<endl; return 0; }
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • 39457760
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-01 22:10:5192楼 得分:0
    上面的代码以及结果是针对5亿规模的数据的(硬盘空间不够)

    修改 DATA_LENGTH=10*100*100*M;就可以计算10亿的数据了
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zzzkkk666
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-01 22:52:4893楼 得分:0
    据说用外部排序法和归并排序法,我还没有实践过
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zhiang75
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-01 23:24:2094楼 得分:0
    To:39457760
    ...不会吧4G的文件啊,我顺序读一遍都要2分多钟阿..
    5亿规模的数据就算是2G..2G/30S=68M/S 不考录计算就是磁盘带宽至少就是68M/S啊...这样的硬盘,不用阵列根本就不可以阿,莫非是在超级计算机上跑得?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • cqinthehouse
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-02 03:19:4795楼 得分:0
    不知道行不行
    比较数的位数
    这个应该很好写~
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • hxxwcc
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-02 10:31:0896楼 得分:0
    小总结一下:
    1)时间复杂度应该 <=O(NlogM),>=O(N)(无论何种算法)
    2)内存不够用,越大越排得快(空间换速度)
    3)外部排序不可取,读写文件浪费时间(为主要瓶颈)
    4)float可以优化
    5)所有算法是不能回头的(不能第2遍读文件)

    ps:我觉得最优秀的算法是近似线性的。。。
    再PS:现在提出的好几个算法已经可以在10分20分钟内完成筛选了(主要读文件慢噢),差不多可以了。。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • sjjf
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-02 11:54:4297楼 得分:0
    主啊,如果可能,我祈求平衡二叉树的出现。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • sjjf
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-02 11:56:2898楼 得分:0
    主啊,如果有可能,我想祈求 Fibonacci 他老人家出来查找一下.
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zhiang75
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-02 14:01:4099楼 得分:0
    俺今天写了一下代码,10亿个数在俺的本本上用了180秒的时间...是用C#写的,C++应该更快,不过不会有质的飞跃了,不敢独享,原代码附上.
    C# code
    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.IO; namespace WindowsApplication14 { public partial class Form1 : Form { public Form1() { InitializeComponent(); for (int a = 0; a < 65536; a++) { container[a] = new List<float>(); } } /// <summary> /// 内存容器 /// </summary> List<float>[] container = new List<float>[65536]; /// <summary> /// 可以使用的内存容器最小索引 /// </summary> uint containerIndex = 0; /// <summary> /// 构造数据文件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button1_Click(object sender, EventArgs e) { FileStream data=File.Create("d:\\data.float", 1024 * 1024 * 10); DateTime bt1 = DateTime.Now; Random random=new Random(); for (int a = 0; a < 1000000000; a++) { double temp = random.NextDouble(); int bi1 = random.Next(10000000); temp = temp * bi1; float rand = (float)temp; byte[] array = BitConverter.GetBytes(rand); data.Write(array,0,4); } data.Close(); DateTime bt2 = DateTime.Now; this.Text=(bt2-bt1).ToString(); } int addCount = 0; /// <summary> /// 将数据加入到容器 /// </summary> /// <param name="value"></param> /// <param name="dataFrame"></param> void AddContainer(float value, uint dataFrame) { addCount++; uint index = dataFrame & 0x7FFF8000;//01111111 11111111 10000000 00000000 index >>= 15; //以上获得8位指数和8位头尾数组成的索引 if (index >= containerIndex) { container[(int)index].Add(value); } //每当添加的数据大于1000w时进行整理 if (addCount > 10000000) { //计数器清零 addCount = 0; //容器中数据量的合计 int sumContainerCount = 0; for (int a = 65535; a >= 0; a--) { sumContainerCount += container[a].Count; if (sumContainerCount >= 10000) { //移动可以使用的容器索引,小于此索引的容器不可以使用 containerIndex = (uint)a; break; } } //清理不可以使用的容器,释放内存 for (int a = 0; a < containerIndex; a++) { container[a].Clear(); } } } /// <summary> /// 合并数据整理输出 /// </summary> /// <returns></returns> List<float> Retuen() { List<float> R = new List<float>(); for (int a = 65535; a >= containerIndex; a--) { R.AddRange(container[a]); } //调用.Net内置排序器,其实就是快排 R.Sort(); //将顺序反转 R.Reverse(); //返回10000个最大的数 return R.GetRange(0, 10000); } /// <summary> /// 计算获得1W个最大数 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button2_Click(object sender, EventArgs e) { FileStream data = File.OpenRead("d:\\data.float"); DateTime bt1 = DateTime.Now; byte[] array = new byte[4]; while (data.Read(array, 0, 4) > 0) { //转换为一个整数结构 uint bi1 = BitConverter.ToUInt32(array,0); //还原为浮点数 float bf1 = BitConverter.ToSingle(array, 0); AddContainer(bf1, bi1); } data.Close(); Retuen(); DateTime bt2 = DateTime.Now; this.Text = (bt2 - bt1).ToString(); } } }

    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • chowming
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-02 14:55:58100楼 得分:0
    我有一种线形的算法,大家请指教:
    1.快速选择第10000大的数时间O(N),记为K;
    2.浏览整个数组,如果a[i]>K,记录输出,否则抛弃,时间为O(N).
    总时间为O(N).
    但是前提就是要内存能放下整个数组。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • chowming
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-02 14:59:25101楼 得分:0
    上面的有歧义
    我有一种线形的算法,大家请指教:
    1.快速选择第10000大的记为K,时间为O(N),该算法和快排差不多;
    2.浏览整个数组,如果a[i]> K,记录输出,否则继续,该阶段的时间为O(N).
    所以总时间为O(N).
    但是前提就是要内存能放下整个数组。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • Ninstein
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-02 16:45:38102楼 得分:0
    TO F101
    比较可笑,你已经知道了第1W大的数了(其实你应该说是第 10亿-1万 大),不就找到了结果,这个过程时间复杂度在O(N)?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zhang88187
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-02 18:01:26103楼 得分:0
    构造两个有一万个浮点数元素的数组A1[],A2[];

    1,A1[]读入10000个数,快速排序;
    2,A2[]读入10000个数,快速排序;
    3,取A2[]中最大的数,二叉查找到它在A1[]中的位置,记录其下标index1;
    4,取A1[]中最小的数,二叉查找到它在A2[]中的位置,记录其下标index2;
    5,将A2[]中下标index2到9999的数复制到A1[]中下标0到index1的位置;
    6,回到步骤2直至取数完毕.

    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • chowming
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-02 19:46:12104楼 得分:0

    TO F102

    是一样的道理哈,快速选择,时间为O(N),算法导论上有的,你可以查阅
    题目也没有说要把这一万个数排序,即使要排序也可以将从上面算法得到的10000个数用快排,时间也比1亿个数进行排序好多了,总的时间也应该是O(N)+Mlog(M),M也就10000,N为一亿,不知道你明白没有?
    总而言之就是先找到一个分界点(如你所说的1亿-10000),然后将大于这个界的10000个数输出,如果要对这10000个数排序的话那不是减少了很多时间么?
    PS:该观点纯属我个人的观点,正如上面所说,1亿个数很大,内存可能装不下
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • 39457760
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-02 23:10:09105楼 得分:0
    引用 94 楼 zhiang75 的回复:
    To:39457760
    ...不会吧4G的文件啊,我顺序读一遍都要2分多钟阿..
    5亿规模的数据就算是2G..2G/30S=68M/S 不考录计算就是磁盘带宽至少就是68M/S啊...这样的硬盘,不用阵列根本就不可以阿,莫非是在超级计算机上跑得?

    读文件的代码写错了,应该是ifile.read((char*)data,length*8);       
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • little06
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-03 01:00:37106楼 得分:0
    根据计算10000 / 1000000000 =0.00001 就是要求的数据是原数据的10万分之一
    所以
    这里应该用多线程,把原数据分割,进行数据的初次排序
    比如分割成10000个数组
    然后把排序后的最大位进行比对,就可以筛选出一部分
    不够一万 再比对数据中的第二位 或者中间的那位进行比对 就可以用了

    这样用的好处是 可以多部机或者多线程进行大规模的运算

    应该最优二叉树 加 冒泡排序的方式来做的


    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • little06
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-03-03 01:04:54107楼 得分:0
    如果把问题改成10亿的浮点数里找一个最大的数字 我想算法就变得唯一了
    所以现在的问题的解决方案是
    现在的算法关键是如果进行10000个数字里快速的比对和排序 才是关键
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天