排序,不过比较复杂,求助。(300分)

X

xingxin00

Unregistered / Unconfirmed
GUEST, unregistred user!
看了半天design1的帖子,不明白,想运行一下也运行不了,郁闷啊。
 
D

design1

Unregistered / Unconfirmed
GUEST, unregistred user!
xingxin00,上面后面一个拷贝下来保存为一个ModelObject.pas文件就可以了,前面一段是试用代码,你建个窗体加个按钮把那段代码拷贝进去就可以了(记得USES ModelObject),这里没有上传文件的功能啊,不然我把工程传上来!有EMAIL留个我发给你
luoyanqing119 呵呵,不好意思,由于这是我正在写的一个开源框架里的代码(详细情况可以到我博客里去看看,欢迎大家提意见啊),所以写的比较通用,具体排序算法部分如果对快速排序比较了解的话,会很容易看懂,就是多重排序那里需要下点工夫去看,^_^
kia2004 呵呵,多交流呀
上面 "XSORT"是我建立的一个五个值为整数的一个对象,相关加了LIST的是
XSORT的一个列表,由于忙着帮你把结果搞出来,所以"XSORT"是随便起的一个名字,呵呵,楼主提到一张表,这就是一张表名吧
有什么问题多交流!
 
D

design1

Unregistered / Unconfirmed
GUEST, unregistred user!
如果只是想要结果的话,直接使用就OK了,比较稳定的,如果只是对算法本身感兴趣,就看看Sortsby函数极其相关部分
 
L

lynch2611

Unregistered / Unconfirmed
GUEST, unregistred user!
我问个情况,你这些数据在什么地方的?
数据库里面,还是什么表格里?
 
L

LeeChange

Unregistered / Unconfirmed
GUEST, unregistred user!
to creation:
虽然现在来的少,但只要是数据结构版里的帖子,还是能出手时就出手哎。[:D]
 
L

liugaohui

Unregistered / Unconfirmed
GUEST, unregistred user!
两大高手进入此帖,楼主运气真好,应该抽奖去
 
X

xingxin00

Unregistered / Unconfirmed
GUEST, unregistred user!
我的Email: sfrew-123@163.com
 
Z

zhuzhi129

Unregistered / Unconfirmed
GUEST, unregistred user!
看似简单,其实很复杂,我也做了1个小时了,得不到结果,靠
 
K

kia2004

Unregistered / Unconfirmed
GUEST, unregistred user!
design1,今天忙了一天,没看你的代码,晚上一定好好学习下,不过今天有个思路,就是把3、5列的数取-,然后就可以将求小值转化为大值,进行排序备用,五维数组的后两维用作标志,不知道这样可不可以,呵呵,今晚我再做,我的EMAIL: NX_DJ@126.COM ,希望得到你的demo。谢谢。
 
K

kia2004

Unregistered / Unconfirmed
GUEST, unregistred user!
LeeChange的代码通过了测试,学习中。。。
to liugaohui,呵呵,谢谢大家帮忙,你们给我了很大帮助,也提了思路,我会努力的,回头写好了我会把代码贴上来,大家一起交流。
creation-zy,你的代码通过了测试,但你的思路我还是不太明白啊
lynch2611,这个是从文本文件中抽取出来的大概有2g,需要得到序号的排序结果,而且除序号外,双列使用最大化排序,单列用最小化排列,并且后两列排序需要用到2、3列的数据,所以需要个通用算法,还得保证效率,比较头疼。。。
 
L

liugaohui

Unregistered / Unconfirmed
GUEST, unregistred user!
creation-zy大侠出手一定是精品!
 
D

design1

Unregistered / Unconfirmed
GUEST, unregistred user!
TO kia2004
已发,呵呵,顺便可以测试下速度哦,这里有好几位高手,看和几位高手的速度差多少,学习中....
 
C

creation-zy

Unregistered / Unconfirmed
GUEST, unregistred user!
思路如下:
背景:
Delphi的TStringList可以对内部字符串实现二分法高速排序。
字符串排序的原理为:对待比较大小的两个字符串从左到右进行扫描,对相同位置的字
符进行大小比较——ASCII码大的即大,若遇到相等的,则继续比较下一个字符,直到其中
一个字符串结束,最终排序的结果为小者在上,大者在上的字符串列表。(ps:TStringList
的排序对英文大小写字母有特殊处理,所以,我们使用十六进制编码来避免这个陷阱——十
六进制字符能被自然排序 0<1<2<...<9<A<B<...<F)。
例子: '1' > '0' , '01' < '02' , '1A' > '19' , '3F0021' > '3C9876'
若待排序的数据只有一列,并且可以很容易的转化为等长的字符串(同时要满足:数据
大的转换出来的字符串的值也大,不会造成排序错乱)。那么我们大可以直接将该列数据依
次编码为字符串并存入TStringList(利用AddObject将数据的初始序号强制转化为TObject
一并绑定存入),然后利用Sort方法就自动完成排序了。例子如下:
with TStringList.Createdo
begin
AddObject('018',TObject(1));
AddObject('002',TObject(2));
AddObject('019',TObject(3));
AddObject('310',TObject(4));
ShowMessage(Text);
Sort;
ShowMessage(Text);
Free;
end;

若待排序的数据列超过一列,那么不同数据列之间必然存在排序优先级的差别,我们可
以利用字符串可无限拼接的特点来排序:
AddObject('30'+'018',TObject(1));
AddObject('22'+'002',TObject(2));
AddObject('22'+'019',TObject(3));
AddObject('04'+'310',TObject(4));
——只要保证特定的列的值无论大小都能在拼接过程中保持相同的长度,就能够在对自
身进行正确排序的同时不影响其它列的排序行为。
至于倒序排列的问题,可以被转化为将该列所有值×-1然后再正向排序的问题从而得到
解决。但考虑到负号并不在0..F的ASCII码范围内,直接乘以-1是行不通的(即便将负数强
行转化为不带符号的HEX字符串,也会以FFFF...开头而破坏与以0000...开头的正数之间的
正常大小关系,不能采用)。所以,我在此通过给出的已知上下限范围(即参数MinNum以及
MaxNum),将所有数据都转化为正数:
正向排序: NewX := X - MinNum => NewX in [ 0 .. MaxNum-MinNum ]
反向排序: NewX := MaxNum - X => NewX in [ 0 .. MaxNum-MinNum ]
(注:原来给出的反向排序计算方法经过论证在MinNum<0时存在Bug,现在修正:)
对于上面的例子,如果我们需要对第二列进行从大到小的排列,实际过程就应该这样:
(MinNum=0, MaxNum=1000)
AddObject('30'+'982',TObject(1));
AddObject('22'+'998',TObject(2));
AddObject('22'+'981',TObject(3));
AddObject('04'+'690',TObject(4));
——对这组字符串排序后,3就会排在2的前面,达到了目的。
最后,我使用了一个小技巧——用一个整数数组来描述索引:
数值的绝对值表示排序时使用的列序号;
数值的符号决定了使用正向(小者在上),还是反向(大者在上)排序方式;
为零的索引值表示这个位置不参加排序;
:)
 
C

creation-zy

Unregistered / Unconfirmed
GUEST, unregistred user!
如果要对大量数据进行排序,考虑到时间复杂度,用二分法排序基本上是首选:)
如果数据源就是文本,那么对于正向排序的列,可以直接字符串拼接,连StrToInt都可以
省了,只要对需要反向排序列进行必要的转化后进行拼接。
如果待排序数据的容量可能超过物理内存的大小(2G文本?!即便楼主有8G以上的内存,
任何一个Win32应用的地址空间也无法超过2G...),那么就要考虑分段排序算法了...(最
简单的方案就是按照第一个排序字段的值进行分组,依次对每个组的内部进行排序,最后再
按照第一个排序字段的顺序将不同组拼接起来——这样,每次内部排序的数据量估计不会超
过100M,就算加上算法内部的临时空间开销,二分法排序也完全可以应付)。
ps:我的算法中,将每个数值都转化为了8个字符的十六进制字符串(IntToHex(xxx,8)),
考虑到楼主面临庞大的数据内存占用开销,可以根据实际情况进行控制——数值在0..255内
的话,2位足矣(不过,“序号”列肯定会大大超过255,需要特别处理)。
 
L

LeeChange

Unregistered / Unconfirmed
GUEST, unregistred user!
这题主要是解决Compare函数的问题,也就是两条数据怎么比大小。至于排序,实在是没什么新颖的东西好讲。5条数据,就算用O(2^n)的都体会不出差距来。如果数据量大,在解决了Compare函数后,完全可以用TList.Sort方法来排序,现成的QuickSort,O(nlogn)的。
 
X

xingxin00

Unregistered / Unconfirmed
GUEST, unregistred user!
受益匪浅,不错,顶一下,真是高手如云啊。
 
D

design1

Unregistered / Unconfirmed
GUEST, unregistred user!
上面两位大虾说的都很对啊,creation-zy的方法比较巧妙,走了一个捷径,呵呵,现在我担心的是对于2G的数据,楼主用这里讨论的几种方法好象....都不是完美的解决办法(包括我的),难道一下装载两G数据?如果如creation-zy所讲,一段一段来,那分段排序后的数据肯定还要再来一次排序,你说的分组不知道如何分,特别的,这里是同时对多列进行排序,不是单列!望赐教
"如果数据量大,在解决了Compare函数后,完全可以用TList.Sort方法来排序,现成的QuickSort,O(nlogn)的。"--呵呵,正是如此,我的算法里就是借鉴了TLIST的快速排序方法,但这个好象只能解决单列的,多列同时排序我处理起来还是写了好些代码,是不是有更好的办法呢,望赐教,另外,如果数据量真的达到2G的话,除非足够大的内存支持,不然还是真的要考虑额外的处理呢,
 
D

design1

Unregistered / Unconfirmed
GUEST, unregistred user!
不知道楼主的实际数据是怎么存放的,最好是具体场景!
 
D

design1

Unregistered / Unconfirmed
GUEST, unregistred user!
"不过今天有个思路,就是把3、5列的数取-,然后就可以将求小值转化为大值,进行排序备用,五维数组的后两维用作标志,不知道这样可不可以"--这样具体没试过,假如最大值和最小值的问题,我想可能你理解为两个数比大比小会更容易帮助你实现算法一些,"这题主要是解决Compare函数的问题,也就是两条数据怎么比大小"-如LeeChange所说,根据具体的数据,写具体的Compare方法!
 

Similar threads

回复
0
查看
501
万一
回复
0
查看
662
不得闲
D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
顶部