算法优化问题,请大家帮忙(急啊)

xjpeng 2003-08-21 04:56:49
我写的一个程序中有一段代码是对一个N*N的矩阵做比较排序,N一般都是在10000左右,我现在的程序运行的太慢,大家能否帮忙优化一下。
算法过程(简单描述,略去了矩阵重排):
1、设矩阵每一行都是一个点
2、用一个公式计算每两个点之间的一个关系d,称为距离吧
3、找到距离最小的两个点,合并成一行,形成一个新的点
4、再次重复步骤2,直到整个矩阵只剩一行,即一个点。
希望我的描述比较清楚了,不知大家是否看明白。
我现在是用的最简单两层循环硬比得到最小的d,这样做计算时间太久了,简单的估算一下,得到第一个最小的d需要计算5000万次(N=10000)……这整个过程需要几个小时,不知道大家是否有能提供比较好的实现算法,不胜感激。
我等级比较低,只能放100分,不够的话我另外开帖再放。
...全文
49 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
jornet 2003-08-27
  • 打赏
  • 举报
回复
这要具体看下你的所谓的d是怎么求出来的
demiurge 2003-08-27
  • 打赏
  • 举报
回复
既然是排序,
为什么要合并成一个点?
只要能判断数据的大小,
就可以用经典的排序算法来做,
只是比较函数要自己定义而已
qingren 2003-08-25
  • 打赏
  • 举报
回复
把比较算法优化一下
用2分法,快速排序法等
Robert1978 2003-08-25
  • 打赏
  • 举报
回复
我个人觉得,得出第一个点的计算时间无法节省。

但可以将后面的计算简化。

因为当计算第2个点时,只需要重新计算该新行和其他没删除的行之间的距离。

如果是我的话我会建立一个距离的二维数组,以及一个长N的一维标志向量,

标志某行是否被删除,——可以省略重排距阵。

每循环一次,删除某一行,更改某一行,重新计算一部分的距离(大约为N)。

(写的不太明确,楼主有兴趣的话,可以发消息给我,我会近一步解释。)


紫郢剑侠 2003-08-23
  • 打赏
  • 举报
回复
帮你up
beachday 2003-08-22
  • 打赏
  • 举报
回复
如果是这样的话好像不太容易达到要求啊。

姑且就把每两行数据之间的关系叫做“权”吧,如果要找出10000行数据之间中某两行的最小权,我们知道10000个元素中任挑两个元素的组合共有C(10000,2)=10000×9999÷2=5千万种,也就是说如果要找到这个最小权,肯定先得算出这所有的权组合,而这个算法显然是O(n平方)的。而且,这个算法显然不能用贪心法来求解,所以每次在内部比最小权都要花O(n的平方),加上最外面的那重循环,整个算法的时间复杂度是O(n的立方)。

能不能有方法不计算权呢?我不太明白楼主的“对一个N*N的矩阵做比较排序”是什么意思,是按照里面元素的大小比较么?是不是输入的是一个N*N的无序矩阵,输出的是一个N*N的有序矩阵?如果里面的元素可以直接相比那还用计算权么?如果可以直接比较元素的大小的话,那还不如把n×n的矩阵等同一个大数组直接复杂排序并插入新矩阵呢……

如果一定要比较权的话,那只好采取“用空间换时间”的办法了。因为每回比较最小权的时候都要对每两行之间进行计算,这样不免会有很多次的重复计算。为了消除这些冗余,可以考虑在内存里做个映射表,每次直接去表里面找最小值,而不用重新计算权值。

第一次放到映射表里面的数据显然是5000万个,对这5000万做个复杂排序(假设从大到小),使它成为一个有序表。这样表末最后一个元素就是最小权。根据这个最小权找到相关的两行,将其合并成新行,同时这相关的两行的关联权值就可以从表里面全部删去了。新行和剩下的9998行之间计算出9998个新权值,将这些新权值插入表中,再找最小值,再删相关行的权,再添相关权…… 这样你每次只需要计算新的权值就够了,之前的所有权都是经过排序的,这样插入也很快,于是就避免了每次生成新行的时候还要进行以前的两两之间的d的计算。

当然为了进一步减少插入新权的时间开销,可以把这个映射表组织成二叉树的结构来代替链表,这样每插一个新权由原来的O(n)次比较可减少到O(log n)次。再进一步,如果觉得每次删除相关权时这棵二叉树都会进行大的结构变动,为了节省这一部分的时间可以考虑不删权节点:每个节点设一个附加布尔变量flag,为false时表示这个权已经被“删去”,下次比较大小时就可以不比了。否则为true时还将继续比较。这样的整个算法最耗时的一步应该就是那个第一次的所有权值排序,是O(n平方 * log(n 平方))=2*O(n平方 * log n),也就是说时间复杂度只有O(n平方 * log n),比原来的O(n立方)要省出好多时间了。当然,占用的内存开销会大一些,为了省时间也只有那么做了。

一点浅见,纸上谈兵而已,不知道思路能不能对你有所启发。


xjpeng 2003-08-22
  • 打赏
  • 举报
回复
我顶
xjpeng 2003-08-21
  • 打赏
  • 举报
回复
非常感谢大家的支持
to howbigsea(大海)
1、其实不叫距离,我只是想简单描述,至于怎么计算出来是有一个具体的固定公式计算的,就是两行数据经过计算得到一个d
2、每行数据都是一个数组,有N个数据,合并是这样的:假设I行和J行的d最小,则新行K的数据由I和J组成,K1=(I1+J1)/2,K2=(I2+J2)/2...这样I和J不再参加下一次循环,由K代替

现在我觉得主要是第一次计算出两两之间的d就比较费时,能不能优化第一次计算次数?
thrillers 2003-08-21
  • 打赏
  • 举报
回复
帮你up
howbigsea 2003-08-21
  • 打赏
  • 举报
回复
不好意思,错了
应该是:
N*(N-1)/2+(N-1)*(N-1)=10000*9999/2+9999*9999
=9999*(5000+9999)=149975001
howbigsea 2003-08-21
  • 打赏
  • 举报
回复

不明白处:
1:主要两个点之间的关系d如何计算?
是否是两个向量之间的距离
2:距离最小的两个点如何合并成一行

可能的优化:
N个点(N行),两两之间的距离计算需要计算N*N次
然后合并两个点,变成一行,然后只需要,让新的点(行)与其它N-1个点计算距离
其它的相互距离不用重新计算
两两合并一次,点数减少一个,从N到1,因此,需要合并N-1次
这样优化以后,可能计算相互距离的次数为:
N*N+(N-1)*(N-1)
如果N=1万
则N*N+(N-1)*(N-1)=10000*10000+9999*9999=(约等于)2*10000*10000次
listshyp 2003-08-21
  • 打赏
  • 举报
回复
不太明白,关注!

另外在构造一个N×N的一维数组,进行插入排序不行吗?

见笑了:)

590

社区成员

发帖
与我相关
我的任务
社区描述
提出问题
其他 技术论坛(原bbs)
社区管理员
  • community_281
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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