打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
[转载]快速排序法(VB和VBA版、递归法版)
    先从数据序列中选一个元素,并将序列中所有比该元素小的元素都放到它的右边或左边,再对左右两边分别用同样的方法处之直到每一个待处理的序列的长度为1, 处理结束。
  在当前无序区R[1..H]中任取一个数据元素作为比较的"基准"(不妨记为X),用此基准将当前无序区划分为左右两个较小的无序区:R[1..I-1]和R[I+1..H],且左边的无序子区中数据元素均小于等于基准元素,右边的无序子区中数据元素均大于等于基准元素,而基准X则位于最终排序的位置上,即R[1..I-1]≤X.Key≤R[I+1..H](1≤I≤H),当R[1..I-1]和R[I+1..H]均非空时,分别对它们进行上述的划分过程,直至所有无序子区中的数据元素均已排序为止
  快速排序的基本思想是基于分治策略的。对于输入的子序列L[p..r],如果规模足够小则直接进行排序(比如用前述的冒泡、选择、插入排序均可),否则分三步处理:
  分解(Divide):将待排序列L[p..r]划分为两个非空子序列L[p..q]和L[q+1..r],使L[p..q]中任一元素的值不大于L[q+1..r]中任一元素的值。具体可通过这样的途径实现:在序列L[p..r]中选择数据元素L[q],经比较和移动后,L[q]将处于L[p..r]中间的适当位置,使得数据元素L[q]的值小于L[q+1..r]中任一元素的值。
  递归求解(Conquer):通过递归调用快速排序算法,分别对L[p..q]和L[q+1..r]进行排序。

  合并(Merge):由于对分解出的两个子序列的排序是就地进行的,所以在L[p..q]和L[q+1..r]都排好序后不需要执行任何计算L[p..r]就已排好序,即自然合并。

    对于基数基本是取最左边一位、最中间一位或最后一位,后面的代码小Y按最中间那位做为基数,进行递归排序。另外:小Y是非计算机专业的,有些坏毛病总是改不过来,习惯于把数组的最小的下标设置为“1”。

Option Base 1
Public Sub Qsort(first As Long, last As Long, dtlist() As Long)
    Dim i As Long
    Dim j As Long
    Dim mid As Long
    Dim save As Long
    i = first

    j = last
    mid = dtlist((first + last) / 2)
    Do
        Do While mid > dtlist(i)
            i = i + 1
        Loop
        Do While mid < dtlist(j)
            j = j - 1
        Loop
        If i <= j Then
            save = dtlist(i)
            dtlist(i) = dtlist(j)
            dtlist(j) = save
            i = i + 1
            j = j - 1
        End If
    Loop Until i > j
    If first < j Then Call Qsort(first, j, dtlist)
    If i < last Then Call Qsort(i, last, dtlist)
End Sub
    该段代码如果是EXCEL的VBA中,应写成模块级,以便在别的地方能更好的调用。

    然后小Y在一个工作表的代码区写下了如下代码,以在立即窗口进行检测(没有再次使用产生随机数的办法,虽然自己赋值麻烦,但是能较好的达到自己的目的)。同时,建议把数组量缩小,最好是三到五位,按单步运行代码,能更好的学习下面的代码。其实说真的,我总觉得这些在实际中用处较小,如果数据量过大,为何不通过ADO放到数据库里进行排序,然后再返回到EXCEL表或别的地方呢?更有过份的朋友,通过 CopyMemory虚拟指针来对一大串的字符串进行排序,感觉特别麻烦,而且递归法小Y一直不喜欢用,虽然速度很快,但是一旦数据上量了,就需要手动修改堆栈的数量。

Option Base 1
Sub test1()
Dim a(10) As Long
a(1) = 4
a(2) = 1
a(3) = 9
a(4) = 99
a(5) = 21
a(6) = 14
a(7) = 22
a(8) = 100
a(9) = 35

a(10) = 3
Call Qsort(LBound(a()), UBound(a()), a())
For i = LBound(a()) To UBound(a())
Debug.Print a(i)
Next
End Sub
    前两天听清华大学严蔚敏教授讲《数据结构》时听到一句明言:算法+数据结构=程序,这也是小Y回头过来再次学习算法的一个原因。准备听《经济法了》,明天上午再加上希尔(shell)排序法的内容,同时,对本文中的部分地方进行修改,大家别丢砖头哈。

 

    先从数据序列中选一个元素,并将序列中所有比该元素小的元素都放到它的右边或左边,再对左右两边分别用同样的方法处之直到每一个待处理的序列的长度为1, 处理结束。
  在当前无序区R[1..H]中任取一个数据元素作为比较的"基准"(不妨记为X),用此基准将当前无序区划分为左右两个较小的无序区:R[1..I-1]和R[I+1..H],且左边的无序子区中数据元素均小于等于基准元素,右边的无序子区中数据元素均大于等于基准元素,而基准X则位于最终排序的位置上,即R[1..I-1]≤X.Key≤R[I+1..H](1≤I≤H),当R[1..I-1]和R[I+1..H]均非空时,分别对它们进行上述的划分过程,直至所有无序子区中的数据元素均已排序为止
  快速排序的基本思想是基于分治策略的。对于输入的子序列L[p..r],如果规模足够小则直接进行排序(比如用前述的冒泡、选择、插入排序均可),否则分三步处理:
  分解(Divide):将待排序列L[p..r]划分为两个非空子序列L[p..q]和L[q+1..r],使L[p..q]中任一元素的值不大于L[q+1..r]中任一元素的值。具体可通过这样的途径实现:在序列L[p..r]中选择数据元素L[q],经比较和移动后,L[q]将处于L[p..r]中间的适当位置,使得数据元素L[q]的值小于L[q+1..r]中任一元素的值。
  递归求解(Conquer):通过递归调用快速排序算法,分别对L[p..q]和L[q+1..r]进行排序。

  合并(Merge):由于对分解出的两个子序列的排序是就地进行的,所以在L[p..q]和L[q+1..r]都排好序后不需要执行任何计算L[p..r]就已排好序,即自然合并。

    对于基数基本是取最左边一位、最中间一位或最后一位,后面的代码小Y按最中间那位做为基数,进行递归排序。另外:小Y是非计算机专业的,有些坏毛病总是改不过来,习惯于把数组的最小的下标设置为“1”。

Option Base 1
Public Sub Qsort(first As Long, last As Long, dtlist() As Long)
    Dim i As Long
    Dim j As Long
    Dim mid As Long
    Dim save As Long
    i = first

    j = last
    mid = dtlist((first + last) / 2)
    Do
        Do While mid > dtlist(i)
            i = i + 1
        Loop
        Do While mid < dtlist(j)
            j = j - 1
        Loop
        If i <= j Then
            save = dtlist(i)
            dtlist(i) = dtlist(j)
            dtlist(j) = save
            i = i + 1
            j = j - 1
        End If
    Loop Until i > j
    If first < j Then Call Qsort(first, j, dtlist)
    If i < last Then Call Qsort(i, last, dtlist)
End Sub
    该段代码如果是EXCEL的VBA中,应写成模块级,以便在别的地方能更好的调用。

    然后小Y在一个工作表的代码区写下了如下代码,以在立即窗口进行检测(没有再次使用产生随机数的办法,虽然自己赋值麻烦,但是能较好的达到自己的目的)。同时,建议把数组量缩小,最好是三到五位,按单步运行代码,能更好的学习下面的代码。其实说真的,我总觉得这些在实际中用处较小,如果数据量过大,为何不通过ADO放到数据库里进行排序,然后再返回到EXCEL表或别的地方呢?更有过份的朋友,通过 CopyMemory虚拟指针来对一大串的字符串进行排序,感觉特别麻烦,而且递归法小Y一直不喜欢用,虽然速度很快,但是一旦数据上量了,就需要手动修改堆栈的数量。

Option Base 1
Sub test1()
Dim a(10) As Long
a(1) = 4
a(2) = 1
a(3) = 9
a(4) = 99
a(5) = 21
a(6) = 14
a(7) = 22
a(8) = 100
a(9) = 35

a(10) = 3
Call Qsort(LBound(a()), UBound(a()), a())
For i = LBound(a()) To UBound(a())
Debug.Print a(i)
Next
End Sub
    前两天听清华大学严蔚敏教授讲《数据结构》时听到一句明言:算法+数据结构=程序,这也是小Y回头过来再次学习算法的一个原因。准备听《经济法了》,明天上午再加上希尔(shell)排序法的内容,同时,对本文中的部分地方进行修改,大家别丢砖头哈。

 

    先从数据序列中选一个元素,并将序列中所有比该元素小的元素都放到它的右边或左边,再对左右两边分别用同样的方法处之直到每一个待处理的序列的长度为1, 处理结束。
  在当前无序区R[1..H]中任取一个数据元素作为比较的"基准"(不妨记为X),用此基准将当前无序区划分为左右两个较小的无序区:R[1..I-1]和R[I+1..H],且左边的无序子区中数据元素均小于等于基准元素,右边的无序子区中数据元素均大于等于基准元素,而基准X则位于最终排序的位置上,即R[1..I-1]≤X.Key≤R[I+1..H](1≤I≤H),当R[1..I-1]和R[I+1..H]均非空时,分别对它们进行上述的划分过程,直至所有无序子区中的数据元素均已排序为止
  快速排序的基本思想是基于分治策略的。对于输入的子序列L[p..r],如果规模足够小则直接进行排序(比如用前述的冒泡、选择、插入排序均可),否则分三步处理:
  分解(Divide):将待排序列L[p..r]划分为两个非空子序列L[p..q]和L[q+1..r],使L[p..q]中任一元素的值不大于L[q+1..r]中任一元素的值。具体可通过这样的途径实现:在序列L[p..r]中选择数据元素L[q],经比较和移动后,L[q]将处于L[p..r]中间的适当位置,使得数据元素L[q]的值小于L[q+1..r]中任一元素的值。
  递归求解(Conquer):通过递归调用快速排序算法,分别对L[p..q]和L[q+1..r]进行排序。

  合并(Merge):由于对分解出的两个子序列的排序是就地进行的,所以在L[p..q]和L[q+1..r]都排好序后不需要执行任何计算L[p..r]就已排好序,即自然合并。

    对于基数基本是取最左边一位、最中间一位或最后一位,后面的代码小Y按最中间那位做为基数,进行递归排序。另外:小Y是非计算机专业的,有些坏毛病总是改不过来,习惯于把数组的最小的下标设置为“1”。

Option Base 1
Public Sub Qsort(first As Long, last As Long, dtlist() As Long)
    Dim i As Long
    Dim j As Long
    Dim mid As Long
    Dim save As Long
    i = first

    j = last
    mid = dtlist((first + last) / 2)
    Do
        Do While mid > dtlist(i)
            i = i + 1
        Loop
        Do While mid < dtlist(j)
            j = j - 1
        Loop
        If i <= j Then
            save = dtlist(i)
            dtlist(i) = dtlist(j)
            dtlist(j) = save
            i = i + 1
            j = j - 1
        End If
    Loop Until i > j
    If first < j Then Call Qsort(first, j, dtlist)
    If i < last Then Call Qsort(i, last, dtlist)
End Sub
    该段代码如果是EXCEL的VBA中,应写成模块级,以便在别的地方能更好的调用。

    然后小Y在一个工作表的代码区写下了如下代码,以在立即窗口进行检测(没有再次使用产生随机数的办法,虽然自己赋值麻烦,但是能较好的达到自己的目的)。同时,建议把数组量缩小,最好是三到五位,按单步运行代码,能更好的学习下面的代码。其实说真的,我总觉得这些在实际中用处较小,如果数据量过大,为何不通过ADO放到数据库里进行排序,然后再返回到EXCEL表或别的地方呢?更有过份的朋友,通过 CopyMemory虚拟指针来对一大串的字符串进行排序,感觉特别麻烦,而且递归法小Y一直不喜欢用,虽然速度很快,但是一旦数据上量了,就需要手动修改堆栈的数量。

Option Base 1
Sub test1()
Dim a(10) As Long
a(1) = 4
a(2) = 1
a(3) = 9
a(4) = 99
a(5) = 21
a(6) = 14
a(7) = 22
a(8) = 100
a(9) = 35

a(10) = 3
Call Qsort(LBound(a()), UBound(a()), a())
For i = LBound(a()) To UBound(a())
Debug.Print a(i)
Next
End Sub
    前两天听清华大学严蔚敏教授讲《数据结构》时听到一句明言:算法+数据结构=程序,这也是小Y回头过来再次学习算法的一个原因。准备听《经济法了》,明天上午再加上希尔(shell)排序法的内容,同时,对本文中的部分地方进行修改,大家别丢砖头哈。

 

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
八种排序算法总结(6)
第8章 排序
快速排序你真的会了吗?
数据结构系列8
js实现快速排序(in
内部排序
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服