VB版人气不高么,大家讨论起来吧:一个另类的排序有关问题,顶者有分!提出好建议的给更多分!
VB版人气不高么,大家讨论起来吧:一个另类的排序问题,顶者有分!!提出好建议的给更多分!!!!!!!
相信每一个程序员在写程序的时候,都或多或少地接触过排序问题.(还别说,我就真见过从来不写排序代码的家伙,号称是写数据库应用的,只要写SORT BY什么的,从来不自己写排序代码的牛人)什么冒泡排序,插入排序,快速排序等等,想必都听出老茧来了.但是很多时候程序的要求并非直接要求你将一列数据从大到小,或者从小到大排一下就算完了.在此我想把我自己在实际应用中遇到的一种排序要求和我所使用的方法介绍给大家.
在我之前的系列文章中,曾经介绍了一种关于图像滤波的算法.该算法的效果不错,但是由于运算量比较大,所以处理速度相对其它功能就稍微慢一些.文章参考:http://blog.yesky.com/blog/wallescai/archive/2007/07/10/1692197.html
在该篇文章中,我主要介绍的是滤波算法的原理和算法.而这个算法中用到了一个比较另类的排序,具体要求如下:
在一个长度为N的乱序整数数列中指定某一个数字,选出整个数列中和该数字的差值最小的M个数字.然后将这些数字求平均值.(其实这就是前面提到的那个滤波算法的关键核心)
N = (R * 2 + 1)^2 (R = 1,2,3,4...); => N = (9,25,49,81...)
M = N/2 (一般取值略小于M的一半)
这并非严格意义上的排序,但是我想很多朋友如果在看完这些要求之后的第一反应就是:排序问题,然后就兴致勃勃的开始写代码.
先别急,还有一个附加条件,由于这个算法是嵌在图像处理算法中的,图像中的每一个像素都需要应用到这个算法3次(红,绿,蓝三种颜色都要参与计算),因此哪怕是一个800*600大小的图片最少也需要进行(800-2)*(600-2)*3 = 1431612次排序.所以要求这个算法异常精简快速.
关于这个排序的算法,我已经在****的论坛中和大家讨论过,参考:http://topic.****.net/t/20060907/13/5005438.html
并且在帖子的后面,我总结出了一个比较快速的算法.并且将之用于我的程序之中,我所公布的那个最新版本的ImageCast就是采用了这个排序算法.
但是,今天在仔细研究了这个算法之后,我发现自己错了.这个算法还依然没有达到它的最高效率,它依然有可挖掘的地方.
首先介绍思路:
假定原数列为A(N),选定的参考数字为S,最后要选出与S值最接近的M个数字
首先建立一个和原数列相同长度的数组B(N).数组B用来存放A(N)中每一个元素和S的差的绝对值
然后将数组B的前M个值和后N-M个值去比较,如果前者大于后者,则两者交换位置,同时将远数组A的对应元素也交换位置.
测试代码为:
Option Explicit
Private Declare Function timeGetTime Lib "winmm.dll "() As Long
Private Declare Sub CopyMemory Lib "kernel32 " Alias "RtlMoveMemory " (pDest As Any, pSrc As Any, ByVal ByteLen As Long)
Const ALL As Long = 1000 '待选数组长度,上文中的N
Const NEAR As Long = 5 '最接近选定数字的数量,上文中的M
Dim A(ALL - 1) As Long '这个数组用来存放原始数据
Dim B(All - 1) As Long '用于生成最初的原始数据,每次测试时拷贝去A将A初始化
Private Sub Form_Load()
Dim I As Long
For I = 0 To ALL - 1
B(I) = Rnd * All '产生一个随机数列
Next
End Sub
Private Sub FSort(ByVal Test As Long)
Dim D(ALL - 1) As Long
Dim I As Long
Dim L As Long
Dim M As Long
Dim N As Long
For I = 0 To ALL - 1 '先获得数组每一个元素和指定数字的差值
D(I) = Abs(A(I) - Test)
Next
For N = 0 To NEAR '关键循环,总的循环次数为 Near*(All-Near)
For I = NEAR + 1 To 999
If D(N) > D(I) Then '将前面的值和后面的值比较
相信每一个程序员在写程序的时候,都或多或少地接触过排序问题.(还别说,我就真见过从来不写排序代码的家伙,号称是写数据库应用的,只要写SORT BY什么的,从来不自己写排序代码的牛人)什么冒泡排序,插入排序,快速排序等等,想必都听出老茧来了.但是很多时候程序的要求并非直接要求你将一列数据从大到小,或者从小到大排一下就算完了.在此我想把我自己在实际应用中遇到的一种排序要求和我所使用的方法介绍给大家.
在我之前的系列文章中,曾经介绍了一种关于图像滤波的算法.该算法的效果不错,但是由于运算量比较大,所以处理速度相对其它功能就稍微慢一些.文章参考:http://blog.yesky.com/blog/wallescai/archive/2007/07/10/1692197.html
在该篇文章中,我主要介绍的是滤波算法的原理和算法.而这个算法中用到了一个比较另类的排序,具体要求如下:
在一个长度为N的乱序整数数列中指定某一个数字,选出整个数列中和该数字的差值最小的M个数字.然后将这些数字求平均值.(其实这就是前面提到的那个滤波算法的关键核心)
N = (R * 2 + 1)^2 (R = 1,2,3,4...); => N = (9,25,49,81...)
M = N/2 (一般取值略小于M的一半)
这并非严格意义上的排序,但是我想很多朋友如果在看完这些要求之后的第一反应就是:排序问题,然后就兴致勃勃的开始写代码.
先别急,还有一个附加条件,由于这个算法是嵌在图像处理算法中的,图像中的每一个像素都需要应用到这个算法3次(红,绿,蓝三种颜色都要参与计算),因此哪怕是一个800*600大小的图片最少也需要进行(800-2)*(600-2)*3 = 1431612次排序.所以要求这个算法异常精简快速.
关于这个排序的算法,我已经在****的论坛中和大家讨论过,参考:http://topic.****.net/t/20060907/13/5005438.html
并且在帖子的后面,我总结出了一个比较快速的算法.并且将之用于我的程序之中,我所公布的那个最新版本的ImageCast就是采用了这个排序算法.
但是,今天在仔细研究了这个算法之后,我发现自己错了.这个算法还依然没有达到它的最高效率,它依然有可挖掘的地方.
首先介绍思路:
假定原数列为A(N),选定的参考数字为S,最后要选出与S值最接近的M个数字
首先建立一个和原数列相同长度的数组B(N).数组B用来存放A(N)中每一个元素和S的差的绝对值
然后将数组B的前M个值和后N-M个值去比较,如果前者大于后者,则两者交换位置,同时将远数组A的对应元素也交换位置.
测试代码为:
Option Explicit
Private Declare Function timeGetTime Lib "winmm.dll "() As Long
Private Declare Sub CopyMemory Lib "kernel32 " Alias "RtlMoveMemory " (pDest As Any, pSrc As Any, ByVal ByteLen As Long)
Const ALL As Long = 1000 '待选数组长度,上文中的N
Const NEAR As Long = 5 '最接近选定数字的数量,上文中的M
Dim A(ALL - 1) As Long '这个数组用来存放原始数据
Dim B(All - 1) As Long '用于生成最初的原始数据,每次测试时拷贝去A将A初始化
Private Sub Form_Load()
Dim I As Long
For I = 0 To ALL - 1
B(I) = Rnd * All '产生一个随机数列
Next
End Sub
Private Sub FSort(ByVal Test As Long)
Dim D(ALL - 1) As Long
Dim I As Long
Dim L As Long
Dim M As Long
Dim N As Long
For I = 0 To ALL - 1 '先获得数组每一个元素和指定数字的差值
D(I) = Abs(A(I) - Test)
Next
For N = 0 To NEAR '关键循环,总的循环次数为 Near*(All-Near)
For I = NEAR + 1 To 999
If D(N) > D(I) Then '将前面的值和后面的值比较