ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
楼主: 灰袍法师

[原创] 有史以来最快的希尔排序 - 比历史贴快10倍,比Excel排序更快 - 兼论堆排序和快速排序

  [复制链接]

TA的精华主题

TA的得分主题

发表于 2015-4-27 15:08 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
本帖已被收录到知识树中,索引项:排序
loquat 发表于 2015-4-27 14:56
1.法师大侠,我拿您的代码出去交流,结果别人给我了一段很简单的快排代码。比您本帖提供的快了将近50%
  我 ...

1、你那排序结果不对;
2、要比较,需在同条件下,数组、变量类型都要相同。

TA的精华主题

TA的得分主题

发表于 2015-4-27 15:47 | 显示全部楼层
Zamyi 发表于 2015-4-27 15:08
1、你那排序结果不对;
2、要比较,需在同条件下,数组、变量类型都要相同。

的确发现结果有误,继续研究。。。

TA的精华主题

TA的得分主题

发表于 2015-4-27 16:28 | 显示全部楼层
对楼主的代码稍作优化,使用模拟堆栈提高效率。
  1. Option Explicit

  2. '///////////////////////////////////////////////////////////////
  3. '// QucikSort_V2 function class
  4. '//
  5. '// LastUpdate:2004-1-22
  6. '// by Kwanhong Young (r4c Studio)
  7. '--
  8. '-- Updated: 20150427
  9. '-- by loquat
  10. '--
  11. '///////////////////////////////////////////////////////////////

  12. Private stack       As cStack_long

  13. Private Sub Class_Initialize()
  14.     Set stack = New cStack_long
  15. End Sub

  16. Private Sub Class_Terminate()
  17.     Set stack = Nothing
  18. End Sub

  19. Private Sub QuickSort(ByRef key_arr() As Long, L As Long, R As Long)
  20. Dim i As Long, j As Long, a As Long, b As Long, Mid As Long, offset As Long
  21. Dim Pivot, Swap
  22.     If R - L <= 60 Then
  23.         For offset = 0 To 18
  24.             For i = L + offset To R Step 19
  25.                 Swap = key_arr(i)
  26.                 For j = i - 19 To L + offset Step -19
  27.                     If Swap < key_arr(j) Then
  28.                         key_arr(j + 19) = key_arr(j)
  29.                         key_arr(j) = Swap
  30.                     Else
  31.                         Exit For
  32.                     End If
  33.                 Next j
  34.             Next i
  35.         Next offset
  36.         
  37.         For offset = 0 To 4
  38.             For i = L + offset To R Step 5
  39.                 Swap = key_arr(i)
  40.                 For j = i - 5 To L + offset Step -5
  41.                     If Swap < key_arr(j) Then
  42.                         key_arr(j + 5) = key_arr(j)
  43.                         key_arr(j) = Swap
  44.                     Else
  45.                         Exit For
  46.                     End If
  47.                 Next j
  48.             Next i
  49.         Next offset
  50.         
  51.         For i = L + 1 To R
  52.             Swap = key_arr(i)
  53.             For j = i - 1 To L Step -1
  54.                 If Swap < key_arr(j) Then
  55.                     key_arr(j + 1) = key_arr(j)
  56.                     key_arr(j) = Swap
  57.                 Else
  58.                     Exit For
  59.                 End If
  60.             Next j
  61.         Next i
  62.     Else
  63.    
  64.         Mid = L + 1 + Int(Rnd * (R - L - 1))
  65. '        Mid = (L + R) / 2
  66.         If key_arr(L) > key_arr(R) Then
  67.             Swap = key_arr(R)
  68.             key_arr(R) = key_arr(L)
  69.             key_arr(L) = Swap
  70.         End If
  71.         If key_arr(Mid) > key_arr(R) Then
  72.             Swap = key_arr(R)
  73.             key_arr(R) = key_arr(Mid)
  74.             key_arr(Mid) = Swap
  75.         End If
  76.         If key_arr(L) > key_arr(Mid) Then
  77.             Swap = key_arr(L)
  78.             key_arr(L) = key_arr(Mid)
  79.             key_arr(Mid) = Swap
  80.         End If
  81.         
  82.         Pivot = key_arr(Mid)
  83.         key_arr(Mid) = key_arr(R - 1)
  84.         key_arr(R - 1) = Pivot
  85.         i = L + 1
  86.         j = R - 2
  87.         While (i < j)
  88.             For i = i To R
  89.                 If key_arr(i) >= Pivot Then Exit For
  90.             Next i
  91.             For j = j To L Step -1
  92.                 If key_arr(j) <= Pivot Then Exit For
  93.             Next j
  94.             If (i < j) Then
  95.                 Swap = key_arr(i)
  96.                 key_arr(i) = key_arr(j)
  97.                 key_arr(j) = Swap
  98.                 i = i + 1
  99.                 j = j - 1
  100.             End If
  101.         Wend

  102.         For a = j To L Step -1
  103.             If key_arr(a) < Pivot Then Exit For
  104.         Next a
  105.         For b = i To R
  106.             If key_arr(b) > Pivot Then Exit For
  107.         Next b
  108.         
  109.         '递归方法
  110.         'If (L < A) Then Call QuickSort(key_arr, L, A)
  111.         'If (B < R) Then Call QuickSort(key_arr, B, R)
  112.         
  113.         '压栈方法
  114.         If (b < R) Then
  115.             stack.Push b
  116.             stack.Push R
  117.         End If
  118.         If (L < a) Then
  119.             stack.Push L
  120.             stack.Push a
  121.         End If
  122.     End If
  123. End Sub

  124. Public Sub StartSort(ByRef vArray() As Long)
  125.     Dim iLow As Long
  126.     Dim iHi As Long
  127.    
  128.     '//get range of array
  129.     iLow = LBound(vArray) '//Low bound
  130.     iHi = UBound(vArray)  '//High bound
  131.    
  132.     '//push low value to stack first
  133.     stack.Push iLow
  134.     stack.Push iHi
  135.    
  136.     '//use STACK, not RECURSION
  137.     Do
  138.         iHi = stack.Pop
  139.         iLow = stack.Pop
  140.         QuickSort vArray(), iLow, iHi   '//call the procedure
  141.     Loop Until stack.Count = 0
  142.    
  143. End Sub

  144. ;----cStack_Long.cls----


  145. Option Explicit

  146. '-----------------------------------------------------------------------
  147. '堆栈 (stack) - FOR LONG DATA TYPE
  148. '数据结构中的 Stack, 有Push、Pop、Peek等方法
  149. '
  150. 'LastUpdate:2004-1-23
  151. 'by Kwanhong Young (r4c Studio)
  152. '-----------------------------------------------------------------------

  153. Private sItem()   As Long
  154. Private iCount    As Long

  155. Private Sub Class_Initialize()
  156. '//start...
  157.     ReDim sItem(0)
  158.     iCount = 0
  159. End Sub

  160. Private Sub Class_Terminate()
  161. '//over
  162.     ReDim sItem(0)
  163.     iCount = 0
  164. End Sub

  165. Public Sub Push(ByVal vValue As Long)
  166.     sItem(iCount) = vValue
  167.     iCount = iCount + 1
  168.     ReDim Preserve sItem(iCount)
  169. End Sub

  170. Public Function Pop() As Long
  171.     If iCount > 0 Then
  172.         iCount = iCount - 1
  173.         Pop = sItem(iCount)
  174.         ReDim Preserve sItem(iCount)
  175.     End If
  176. End Function

  177. Public Function Peek() As Long
  178.     If iCount > 0 Then Peek = sItem(iCount - 1)
  179. End Function

  180. Public Property Get Count() As Long
  181.     Count = iCount
  182. End Property

  183. Public Sub GetAllItem(itm() As Long)
  184.     ReDim itm(iCount)
  185.     Dim i   As Long
  186.     For i = 0 To iCount - 1
  187.         itm(i) = sItem(i)
  188.     Next
  189. End Sub

  190. Public Function GetAllItem_toString(Optional ByVal cDelimiter As String = "|") As String
  191.     If iCount = 0 Then Exit Function
  192.     GetAllItem_toString = Join(sItem, cDelimiter)
  193. End Function
复制代码

TA的精华主题

TA的得分主题

发表于 2015-4-27 16:32 | 显示全部楼层
另贴一个函数供交流,vbgood acme_pjz从qsort.c翻译来的代码。
http://www.vbgood.com/thread-89774-1-1.html
本楼代码默认是翻译的代码,如果设置成UseMSVCRT = 1,则使用系统msvcrt.dll中qsort
  1. Option Explicit

  2. #Const UseMSVCRT = 0

  3. #If UseMSVCRT Then   '使用msvcrt.dll中的qsort函数

  4. '/***
  5. '*qsort(base, num, wid, comp) - quicksort function for sorting arrays
  6. '*
  7. '*Purpose:
  8. '*   quicksort the array of elements
  9. '*   side effects:  sorts in place
  10. '*   maximum array size is number of elements times size of elements,
  11. '*   but is limited by the virtual address space of the processor
  12. '*
  13. '*Entry:
  14. '*   char *base = pointer to base of array
  15. '*   size_t num  = number of elements in the array
  16. '*   size_t width = width in bytes of each array element
  17. '*   int (*comp)() = pointer to function returning analog of strcmp for
  18. '*           strings, but supplied by user for comparing the array elements.
  19. '*           it accepts 2 pointers to elements.
  20. '*           Returns neg if 1<2, 0 if 1=2, pos if 1>2.
  21. '*
  22. '*Exit:
  23. '*   returns void
  24. '*
  25. '*Exceptions:
  26. '*   Input parameters are validated. Refer to the validation section of the function.
  27. '*
  28. '*******************************************************************************/

  29. Private Declare Function CallWindowProc Lib "user32.dll" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
  30. Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)
  31. Private Declare Function LoadLibrary Lib "kernel32.dll" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
  32. Private Declare Function FreeLibrary Lib "kernel32.dll" (ByVal hLibModule As Long) As Long
  33. Private Declare Function GetProcAddress Lib "kernel32.dll" (ByVal hModule As Long, ByVal lpProcName As String) As Long

  34. Private m_bCode(255) As Byte, m_hMod As Long, m_lpFunc As Long
  35. Private m_lpObjPtr As Long, m_nUserData As Long

  36. #End If

  37. Public Function Compare(ByVal Index1 As Long, ByVal Index2 As Long, ByVal nUserData As Long) As Long
  38. 'default implementation (???)
  39. If Index1 < Index2 Then Compare = -1 Else _
  40. If Index1 > Index2 Then Compare = 1 Else Compare = 0
  41. End Function

  42. Friend Sub QuickSort(idxArray() As Long, ByVal nStart As Long, ByVal nEnd As Long, Optional ByVal obj As ISort2, Optional ByVal nUserData As Long, Optional ByVal nLimit As Long = 8)
  43. '///check
  44. If nEnd - nStart <= 1 Then Exit Sub
  45. If obj Is Nothing Then Set obj = Me
  46. '///
  47. #If UseMSVCRT Then
  48. If m_lpFunc Then
  49. m_lpObjPtr = ObjPtr(obj)
  50. m_nUserData = nUserData
  51. CallWindowProc VarPtr(m_bCode(0)), VarPtr(idxArray(nStart)), nEnd - nStart + 1, m_lpFunc, 0
  52. Exit Sub
  53. End If
  54. #Else
  55. '////////////////////////////////TODO:translate qsort.c into VB
  56. Dim i As Long, j As Long, k As Long 'temp
  57. Dim nMid As Long '/* points to middle of subarray */
  58. Dim lpStart As Long, lpEnd As Long '/* traveling pointers for partition step */
  59. Dim nSize As Long '/* size of the sub-array */
  60. Dim nStartStack(31) As Long, nEndStack(31) As Long, nStack As Long '/* stack for saving sub-array to be processed */
  61. '/* this entry point is for pseudo-recursion calling: setting
  62. '   lo and hi and jumping to here is like recursion, but stkptr is
  63. '   preserved, locals aren't, so we preserve stuff on the stack */
  64. Recurse:
  65. 'size = (hi - lo) / width + 1;        /* number of el's to sort */
  66. nSize = nEnd - nStart + 1
  67. '/* below a certain size, it is faster to use a O(n^2) sorting method */
  68. If nSize <= nLimit Then
  69. 'shortsort
  70. If nSize > 1 Then
  71.   Do
  72.    lpStart = nStart
  73.    i = idxArray(lpStart)
  74.    For lpEnd = nStart + 1 To nEnd
  75.     j = idxArray(lpEnd)
  76.     If obj.Compare(j, i, nUserData) > 0 Then lpStart = lpEnd: i = j
  77.    Next lpEnd
  78.    If lpStart < nEnd Then idxArray(lpStart) = idxArray(nEnd): idxArray(nEnd) = i
  79.    nEnd = nEnd - 1
  80.   Loop While nEnd > nStart
  81. End If
  82. Else
  83. '    /* First we pick a partitioning element.  The efficiency of the
  84. '       algorithm demands that we find one that is approximately the median
  85. '       of the values, but also that we select one fast.  We choose the
  86. '       median of the first, middle, and last elements, to avoid bad
  87. '       performance in the face of already sorted data, or data that is made
  88. '       up of multiple sorted runs appended together.  Testing shows that a
  89. '       median-of-three algorithm provides better performance than simply
  90. '       picking the middle element for the latter case. */
  91. '    mid = lo + (size / 2) * width;      /* find middle element */
  92.     nMid = nStart + nSize \ 2
  93. '
  94. '    /* Sort the first, middle, last elements into order */
  95. '    if (__COMPARE(context, lo, mid) > 0) swap(lo, mid, width);
  96.     i = idxArray(nStart): j = idxArray(nMid)
  97.     If obj.Compare(i, j, nUserData) > 0 Then idxArray(nStart) = j: idxArray(nMid) = i
  98. '    if (__COMPARE(context, lo, hi) > 0) swap(lo, hi, width);
  99.     i = idxArray(nStart): j = idxArray(nEnd)
  100.     If obj.Compare(i, j, nUserData) > 0 Then idxArray(nStart) = j: idxArray(nEnd) = i
  101. '    if (__COMPARE(context, mid, hi) > 0) swap(mid, hi, width);
  102.     i = idxArray(nMid): j = idxArray(nEnd)
  103.     If obj.Compare(i, j, nUserData) > 0 Then idxArray(nMid) = j: idxArray(nEnd) = i
  104. '
  105. '    /* We now wish to partition the array into three pieces, one consisting
  106. '       of elements <= partition element, one of elements equal to the
  107. '       partition element, and one of elements > than it.  This is done
  108. '       below; comments indicate conditions established at every step. */
  109. '
  110. '    loguy = lo;
  111. '    higuy = hi;
  112.     lpStart = nStart
  113.     lpEnd = nEnd
  114. '
  115. '    /* Note that higuy decreases and loguy increases on every iteration,
  116. '       so loop must terminate. */
  117. '    for (;;) {
  118.     Do
  119. '        /* lo <= loguy < hi, lo < higuy <= hi,
  120. '           A[i] <= A[mid] for lo <= i <= loguy,
  121. '           A[i] > A[mid] for higuy <= i < hi,
  122. '           A[hi] >= A[mid] */
  123. '
  124. '        /* The doubled loop is to avoid calling comp(mid,mid), since some
  125. '           existing comparison funcs don't work when passed the same
  126. '           value for both pointers. */
  127.         i = idxArray(nMid)
  128. '        if (mid > loguy) {
  129. '            do  {
  130. '                loguy += width;
  131. '            } while (loguy < mid && __COMPARE(context, loguy, mid) <= 0);
  132. '        }
  133.         If nMid > lpStart Then
  134.          Do
  135.           lpStart = lpStart + 1
  136.           j = idxArray(lpStart)
  137.           If lpStart >= nMid Then Exit Do
  138.          Loop While obj.Compare(j, i, nUserData) <= 0
  139.         End If
  140. '        if (mid <= loguy) {
  141. '            do  {
  142. '                loguy += width;
  143. '            } while (loguy <= hi && __COMPARE(context, loguy, mid) <= 0);
  144. '        }
  145.         If nMid <= lpStart Then
  146.          Do
  147.           lpStart = lpStart + 1
  148.           If lpStart > nEnd Then Exit Do
  149.           j = idxArray(lpStart)
  150.          Loop While obj.Compare(j, i, nUserData) <= 0
  151.         End If
  152. '
  153. '        /* lo < loguy <= hi+1, A[i] <= A[mid] for lo <= i < loguy,
  154. '           either loguy > hi or A[loguy] > A[mid] */
  155. '
  156. '        do  {
  157. '            higuy -= width;
  158. '        } while (higuy > mid && __COMPARE(context, higuy, mid) > 0);
  159.         Do
  160.          lpEnd = lpEnd - 1
  161.          k = idxArray(lpEnd)
  162.          If lpEnd <= nMid Then Exit Do
  163.         Loop While obj.Compare(k, i, nUserData) > 0
  164. '
  165. '        /* lo <= higuy < hi, A[i] > A[mid] for higuy < i < hi,
  166. '           either higuy == lo or A[higuy] <= A[mid] */
  167. '
  168. '        if (higuy < loguy)
  169. '            break;
  170.         If lpEnd < lpStart Then Exit Do
  171. '
  172. '        /* if loguy > hi or higuy == lo, then we would have exited, so
  173. '           A[loguy] > A[mid], A[higuy] <= A[mid],
  174. '           loguy <= hi, higuy > lo */
  175. '
  176. '        swap(loguy, higuy, width);
  177.         If lpEnd > lpStart Then idxArray(lpStart) = k: idxArray(lpEnd) = j
  178. '
  179. '        /* If the partition element was moved, follow it.  Only need
  180. '           to check for mid == higuy, since before the swap,
  181. '           A[loguy] > A[mid] implies loguy != mid. */
  182. '
  183. '        if (mid == higuy)
  184. '            mid = loguy;
  185.         If nMid = lpEnd Then nMid = lpStart
  186. '
  187. '        /* A[loguy] <= A[mid], A[higuy] > A[mid]; so condition at top
  188. '           of loop is re-established */
  189. '    }
  190.     Loop
  191. '
  192. '    /*     A[i] <= A[mid] for lo <= i < loguy,
  193. '           A[i] > A[mid] for higuy < i < hi,
  194. '           A[hi] >= A[mid]
  195. '           higuy < loguy
  196. '       implying:
  197. '           higuy == loguy-1
  198. '           or higuy == hi - 1, loguy == hi + 1, A[hi] == A[mid] */
  199. '
  200. '    /* Find adjacent elements equal to the partition element.  The
  201. '       doubled loop is to avoid calling comp(mid,mid), since some
  202. '       existing comparison funcs don't work when passed the same value
  203. '       for both pointers. */
  204. '
  205. '    higuy += width;
  206.     lpEnd = lpEnd + 1
  207. '    if (mid < higuy) {
  208. '        do  {
  209. '            higuy -= width;
  210. '        } while (higuy > mid && __COMPARE(context, higuy, mid) == 0);
  211. '    }
  212.     i = idxArray(nMid)
  213.     If nMid < lpEnd Then
  214.      Do
  215.       lpEnd = lpEnd - 1
  216.       If lpEnd <= nMid Then Exit Do
  217.      Loop While obj.Compare(idxArray(lpEnd), i, nUserData) = 0
  218.     End If
  219. '    if (mid >= higuy) {
  220. '        do  {
  221. '            higuy -= width;
  222. '        } while (higuy > lo && __COMPARE(context, higuy, mid) == 0);
  223. '    }
  224.     If nMid >= lpEnd Then
  225.      Do
  226.       lpEnd = lpEnd - 1
  227.       If lpEnd <= nStart Then Exit Do
  228.      Loop While obj.Compare(idxArray(lpEnd), i, nUserData) = 0
  229.     End If
  230. '
  231. '    /* OK, now we have the following:
  232. '          higuy < loguy
  233. '          lo <= higuy <= hi
  234. '          A[i]  <= A[mid] for lo <= i <= higuy
  235. '          A[i]  == A[mid] for higuy < i < loguy
  236. '          A[i]  >  A[mid] for loguy <= i < hi
  237. '          A[hi] >= A[mid] */
  238. '
  239. '    /* We've finished the partition, now we want to sort the subarrays
  240. '       [lo, higuy] and [loguy, hi].
  241. '       We do the smaller one first to minimize stack usage.
  242. '       We only sort arrays of length 2 or more.*/
  243. '
  244. '    if ( higuy - lo >= hi - loguy ) {
  245.     If lpEnd - nStart >= nEnd - lpStart Then
  246. '        if (lo < higuy) {
  247. '            lostk[stkptr] = lo;
  248. '            histk[stkptr] = higuy;
  249. '            ++stkptr;
  250. '        }                           /* save big recursion for later */
  251.         If nStart < lpEnd Then
  252.          nStartStack(nStack) = nStart
  253.          nEndStack(nStack) = lpEnd
  254.          nStack = nStack + 1
  255.         End If
  256. '        if (loguy < hi) {
  257. '            lo = loguy;
  258. '            goto recurse;           /* do small recursion */
  259. '        }
  260.         If lpStart < nEnd Then
  261.          nStart = lpStart
  262.          GoTo Recurse
  263.         End If
  264. '    }
  265.     Else
  266. '    else {
  267. '        if (loguy < hi) {
  268. '            lostk[stkptr] = loguy;
  269. '            histk[stkptr] = hi;
  270. '            ++stkptr;               /* save big recursion for later */
  271. '        }
  272.         If lpStart < nEnd Then
  273.          nStartStack(nStack) = lpStart
  274.          nEndStack(nStack) = nEnd
  275.          nStack = nStack + 1
  276.         End If
  277. '
  278. '        if (lo < higuy) {
  279. '            hi = higuy;
  280. '            goto recurse;           /* do small recursion */
  281. '        }
  282.         If nStart < lpEnd Then
  283.          nEnd = lpEnd
  284.          GoTo Recurse
  285.         End If
  286. '    }
  287.     End If
  288. End If
  289. '/* We have sorted the array, except for any pending sorts on the stack.
  290. '   Check if there are any, and do them. */
  291. nStack = nStack - 1
  292. If nStack >= 0 Then
  293. nStart = nStartStack(nStack)
  294. nEnd = nEndStack(nStack)
  295. GoTo Recurse '/* pop subarray from stack */
  296. End If
  297. 'else
  298. '    return;                 /* all subarrays done */
  299. '////////////////////////////////
  300. #End If
  301. End Sub

  302. #If UseMSVCRT Then

  303. Private Sub Class_Initialize()
  304. Dim s As String
  305. '///
  306. m_hMod = LoadLibrary("msvcrt.dll")
  307. m_lpFunc = GetProcAddress(m_hMod, "qsort")
  308. '///
  309. s = "89 E0 E8 00 00 00 00 83 04 24 15 6A 04 FF 70 08" + _
  310. "FF 70 04 FF 50 0C 83 C4 10 C2 10 00 6A 00 89 E0" + _
  311. "8B 15 ObjPtr 50 FF 35 UserData 8B 48 0C" + _
  312. "8B 40 08 FF 31 FF 30 8B 0A 52 FF 51 1C 58 C3"
  313. s = Replace(s, "ObjPtr", ReverseHex(VarPtr(m_lpObjPtr)))
  314. s = Replace(s, "UserData", ReverseHex(VarPtr(m_nUserData)))
  315. CodeFromString s, m_bCode
  316. End Sub

  317. Private Sub Class_Terminate()
  318. FreeLibrary m_hMod
  319. End Sub

  320. Private Sub CodeFromString(ByVal s As String, ByRef b() As Byte)
  321. Dim m As Long, i As Long
  322. s = Replace(s, " ", "")
  323. s = Replace(s, ",", "")
  324. m = Len(s) \ 2
  325. For i = 0 To m - 1
  326. b(i) = Val("&H" + Mid(s, i + i + 1, 2))
  327. Next i
  328. End Sub

  329. Private Function ReverseHex(ByVal n As Long) As String
  330. Dim s As String
  331. s = Right("00000000" + Hex(n), 8)
  332. ReverseHex = Mid(s, 7, 2) + Mid(s, 5, 2) + Mid(s, 3, 2) + Mid(s, 1, 2)
  333. End Function

  334. #End If
复制代码

TA的精华主题

TA的得分主题

发表于 2015-4-27 16:46 | 显示全部楼层
一个代码供大婶们来修改上文代码,vbGood坛acme_pjz翻译的qsort.c
上文主要是两个类模块,应该可以只用一个做到吧
  1. Option Explicit

  2. #Const UseMSVCRT = 0

  3. #If UseMSVCRT Then

  4. '/***
  5. '*qsort(base, num, wid, comp) - quicksort function for sorting arrays
  6. '*
  7. '*Purpose:
  8. '*   quicksort the array of elements
  9. '*   side effects:  sorts in place
  10. '*   maximum array size is number of elements times size of elements,
  11. '*   but is limited by the virtual address space of the processor
  12. '*
  13. '*Entry:
  14. '*   char *base = pointer to base of array
  15. '*   size_t num  = number of elements in the array
  16. '*   size_t width = width in bytes of each array element
  17. '*   int (*comp)() = pointer to function returning analog of strcmp for
  18. '*           strings, but supplied by user for comparing the array elements.
  19. '*           it accepts 2 pointers to elements.
  20. '*           Returns neg if 1<2, 0 if 1=2, pos if 1>2.
  21. '*
  22. '*Exit:
  23. '*   returns void
  24. '*
  25. '*Exceptions:
  26. '*   Input parameters are validated. Refer to the validation section of the function.
  27. '*
  28. '*******************************************************************************/

  29. Private Declare Function CallWindowProc Lib "user32.dll" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
  30. Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)
  31. Private Declare Function LoadLibrary Lib "kernel32.dll" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
  32. Private Declare Function FreeLibrary Lib "kernel32.dll" (ByVal hLibModule As Long) As Long
  33. Private Declare Function GetProcAddress Lib "kernel32.dll" (ByVal hModule As Long, ByVal lpProcName As String) As Long

  34. Private m_bCode(255) As Byte, m_hMod As Long, m_lpFunc As Long
  35. Private m_lpObjPtr As Long, m_nUserData As Long

  36. #End If

  37. Public Function Compare(ByVal Index1 As Long, ByVal Index2 As Long, ByVal nUserData As Long) As Long
  38. 'default implementation (???)
  39. If Index1 < Index2 Then Compare = -1 Else _
  40. If Index1 > Index2 Then Compare = 1 Else Compare = 0
  41. End Function

  42. Friend Sub QuickSort(idxArray() As Long, ByVal nStart As Long, ByVal nEnd As Long, Optional ByVal obj As ISort2, Optional ByVal nUserData As Long, Optional ByVal nLimit As Long = 8)
  43. '///check
  44. If nEnd - nStart <= 1 Then Exit Sub
  45. If obj Is Nothing Then Set obj = Me
  46. '///
  47. #If UseMSVCRT Then
  48. If m_lpFunc Then
  49. m_lpObjPtr = ObjPtr(obj)
  50. m_nUserData = nUserData
  51. CallWindowProc VarPtr(m_bCode(0)), VarPtr(idxArray(nStart)), nEnd - nStart + 1, m_lpFunc, 0
  52. Exit Sub
  53. End If
  54. #Else
  55. '////////////////////////////////TODO:translate qsort.c into VB
  56. Dim i As Long, j As Long, k As Long 'temp
  57. Dim nMid As Long '/* points to middle of subarray */
  58. Dim lpStart As Long, lpEnd As Long '/* traveling pointers for partition step */
  59. Dim nSize As Long '/* size of the sub-array */
  60. Dim nStartStack(31) As Long, nEndStack(31) As Long, nStack As Long '/* stack for saving sub-array to be processed */
  61. '/* this entry point is for pseudo-recursion calling: setting
  62. '   lo and hi and jumping to here is like recursion, but stkptr is
  63. '   preserved, locals aren't, so we preserve stuff on the stack */
  64. Recurse:
  65. 'size = (hi - lo) / width + 1;        /* number of el's to sort */
  66. nSize = nEnd - nStart + 1
  67. '/* below a certain size, it is faster to use a O(n^2) sorting method */
  68. If nSize <= nLimit Then
  69. 'shortsort
  70. If nSize > 1 Then
  71.   Do
  72.    lpStart = nStart
  73.    i = idxArray(lpStart)
  74.    For lpEnd = nStart + 1 To nEnd
  75.     j = idxArray(lpEnd)
  76.     If obj.Compare(j, i, nUserData) > 0 Then lpStart = lpEnd: i = j
  77.    Next lpEnd
  78.    If lpStart < nEnd Then idxArray(lpStart) = idxArray(nEnd): idxArray(nEnd) = i
  79.    nEnd = nEnd - 1
  80.   Loop While nEnd > nStart
  81. End If
  82. Else
  83. '    /* First we pick a partitioning element.  The efficiency of the
  84. '       algorithm demands that we find one that is approximately the median
  85. '       of the values, but also that we select one fast.  We choose the
  86. '       median of the first, middle, and last elements, to avoid bad
  87. '       performance in the face of already sorted data, or data that is made
  88. '       up of multiple sorted runs appended together.  Testing shows that a
  89. '       median-of-three algorithm provides better performance than simply
  90. '       picking the middle element for the latter case. */
  91. '    mid = lo + (size / 2) * width;      /* find middle element */
  92.     nMid = nStart + nSize \ 2
  93. '
  94. '    /* Sort the first, middle, last elements into order */
  95. '    if (__COMPARE(context, lo, mid) > 0) swap(lo, mid, width);
  96.     i = idxArray(nStart): j = idxArray(nMid)
  97.     If obj.Compare(i, j, nUserData) > 0 Then idxArray(nStart) = j: idxArray(nMid) = i
  98. '    if (__COMPARE(context, lo, hi) > 0) swap(lo, hi, width);
  99.     i = idxArray(nStart): j = idxArray(nEnd)
  100.     If obj.Compare(i, j, nUserData) > 0 Then idxArray(nStart) = j: idxArray(nEnd) = i
  101. '    if (__COMPARE(context, mid, hi) > 0) swap(mid, hi, width);
  102.     i = idxArray(nMid): j = idxArray(nEnd)
  103.     If obj.Compare(i, j, nUserData) > 0 Then idxArray(nMid) = j: idxArray(nEnd) = i
  104. '
  105. '    /* We now wish to partition the array into three pieces, one consisting
  106. '       of elements <= partition element, one of elements equal to the
  107. '       partition element, and one of elements > than it.  This is done
  108. '       below; comments indicate conditions established at every step. */
  109. '
  110. '    loguy = lo;
  111. '    higuy = hi;
  112.     lpStart = nStart
  113.     lpEnd = nEnd
  114. '
  115. '    /* Note that higuy decreases and loguy increases on every iteration,
  116. '       so loop must terminate. */
  117. '    for (;;) {
  118.     Do
  119. '        /* lo <= loguy < hi, lo < higuy <= hi,
  120. '           A[i] <= A[mid] for lo <= i <= loguy,
  121. '           A[i] > A[mid] for higuy <= i < hi,
  122. '           A[hi] >= A[mid] */
  123. '
  124. '        /* The doubled loop is to avoid calling comp(mid,mid), since some
  125. '           existing comparison funcs don't work when passed the same
  126. '           value for both pointers. */
  127.         i = idxArray(nMid)
  128. '        if (mid > loguy) {
  129. '            do  {
  130. '                loguy += width;
  131. '            } while (loguy < mid && __COMPARE(context, loguy, mid) <= 0);
  132. '        }
  133.         If nMid > lpStart Then
  134.          Do
  135.           lpStart = lpStart + 1
  136.           j = idxArray(lpStart)
  137.           If lpStart >= nMid Then Exit Do
  138.          Loop While obj.Compare(j, i, nUserData) <= 0
  139.         End If
  140. '        if (mid <= loguy) {
  141. '            do  {
  142. '                loguy += width;
  143. '            } while (loguy <= hi && __COMPARE(context, loguy, mid) <= 0);
  144. '        }
  145.         If nMid <= lpStart Then
  146.          Do
  147.           lpStart = lpStart + 1
  148.           If lpStart > nEnd Then Exit Do
  149.           j = idxArray(lpStart)
  150.          Loop While obj.Compare(j, i, nUserData) <= 0
  151.         End If
  152. '
  153. '        /* lo < loguy <= hi+1, A[i] <= A[mid] for lo <= i < loguy,
  154. '           either loguy > hi or A[loguy] > A[mid] */
  155. '
  156. '        do  {
  157. '            higuy -= width;
  158. '        } while (higuy > mid && __COMPARE(context, higuy, mid) > 0);
  159.         Do
  160.          lpEnd = lpEnd - 1
  161.          k = idxArray(lpEnd)
  162.          If lpEnd <= nMid Then Exit Do
  163.         Loop While obj.Compare(k, i, nUserData) > 0
  164. '
  165. '        /* lo <= higuy < hi, A[i] > A[mid] for higuy < i < hi,
  166. '           either higuy == lo or A[higuy] <= A[mid] */
  167. '
  168. '        if (higuy < loguy)
  169. '            break;
  170.         If lpEnd < lpStart Then Exit Do
  171. '
  172. '        /* if loguy > hi or higuy == lo, then we would have exited, so
  173. '           A[loguy] > A[mid], A[higuy] <= A[mid],
  174. '           loguy <= hi, higuy > lo */
  175. '
  176. '        swap(loguy, higuy, width);
  177.         If lpEnd > lpStart Then idxArray(lpStart) = k: idxArray(lpEnd) = j
  178. '
  179. '        /* If the partition element was moved, follow it.  Only need
  180. '           to check for mid == higuy, since before the swap,
  181. '           A[loguy] > A[mid] implies loguy != mid. */
  182. '
  183. '        if (mid == higuy)
  184. '            mid = loguy;
  185.         If nMid = lpEnd Then nMid = lpStart
  186. '
  187. '        /* A[loguy] <= A[mid], A[higuy] > A[mid]; so condition at top
  188. '           of loop is re-established */
  189. '    }
  190.     Loop
  191. '
  192. '    /*     A[i] <= A[mid] for lo <= i < loguy,
  193. '           A[i] > A[mid] for higuy < i < hi,
  194. '           A[hi] >= A[mid]
  195. '           higuy < loguy
  196. '       implying:
  197. '           higuy == loguy-1
  198. '           or higuy == hi - 1, loguy == hi + 1, A[hi] == A[mid] */
  199. '
  200. '    /* Find adjacent elements equal to the partition element.  The
  201. '       doubled loop is to avoid calling comp(mid,mid), since some
  202. '       existing comparison funcs don't work when passed the same value
  203. '       for both pointers. */
  204. '
  205. '    higuy += width;
  206.     lpEnd = lpEnd + 1
  207. '    if (mid < higuy) {
  208. '        do  {
  209. '            higuy -= width;
  210. '        } while (higuy > mid && __COMPARE(context, higuy, mid) == 0);
  211. '    }
  212.     i = idxArray(nMid)
  213.     If nMid < lpEnd Then
  214.      Do
  215.       lpEnd = lpEnd - 1
  216.       If lpEnd <= nMid Then Exit Do
  217.      Loop While obj.Compare(idxArray(lpEnd), i, nUserData) = 0
  218.     End If
  219. '    if (mid >= higuy) {
  220. '        do  {
  221. '            higuy -= width;
  222. '        } while (higuy > lo && __COMPARE(context, higuy, mid) == 0);
  223. '    }
  224.     If nMid >= lpEnd Then
  225.      Do
  226.       lpEnd = lpEnd - 1
  227.       If lpEnd <= nStart Then Exit Do
  228.      Loop While obj.Compare(idxArray(lpEnd), i, nUserData) = 0
  229.     End If
  230. '
  231. '    /* OK, now we have the following:
  232. '          higuy < loguy
  233. '          lo <= higuy <= hi
  234. '          A[i]  <= A[mid] for lo <= i <= higuy
  235. '          A[i]  == A[mid] for higuy < i < loguy
  236. '          A[i]  >  A[mid] for loguy <= i < hi
  237. '          A[hi] >= A[mid] */
  238. '
  239. '    /* We've finished the partition, now we want to sort the subarrays
  240. '       [lo, higuy] and [loguy, hi].
  241. '       We do the smaller one first to minimize stack usage.
  242. '       We only sort arrays of length 2 or more.*/
  243. '
  244. '    if ( higuy - lo >= hi - loguy ) {
  245.     If lpEnd - nStart >= nEnd - lpStart Then
  246. '        if (lo < higuy) {
  247. '            lostk[stkptr] = lo;
  248. '            histk[stkptr] = higuy;
  249. '            ++stkptr;
  250. '        }                           /* save big recursion for later */
  251.         If nStart < lpEnd Then
  252.          nStartStack(nStack) = nStart
  253.          nEndStack(nStack) = lpEnd
  254.          nStack = nStack + 1
  255.         End If
  256. '        if (loguy < hi) {
  257. '            lo = loguy;
  258. '            goto recurse;           /* do small recursion */
  259. '        }
  260.         If lpStart < nEnd Then
  261.          nStart = lpStart
  262.          GoTo Recurse
  263.         End If
  264. '    }
  265.     Else
  266. '    else {
  267. '        if (loguy < hi) {
  268. '            lostk[stkptr] = loguy;
  269. '            histk[stkptr] = hi;
  270. '            ++stkptr;               /* save big recursion for later */
  271. '        }
  272.         If lpStart < nEnd Then
  273.          nStartStack(nStack) = lpStart
  274.          nEndStack(nStack) = nEnd
  275.          nStack = nStack + 1
  276.         End If
  277. '
  278. '        if (lo < higuy) {
  279. '            hi = higuy;
  280. '            goto recurse;           /* do small recursion */
  281. '        }
  282.         If nStart < lpEnd Then
  283.          nEnd = lpEnd
  284.          GoTo Recurse
  285.         End If
  286. '    }
  287.     End If
  288. End If
  289. '/* We have sorted the array, except for any pending sorts on the stack.
  290. '   Check if there are any, and do them. */
  291. nStack = nStack - 1
  292. If nStack >= 0 Then
  293. nStart = nStartStack(nStack)
  294. nEnd = nEndStack(nStack)
  295. GoTo Recurse '/* pop subarray from stack */
  296. End If
  297. 'else
  298. '    return;                 /* all subarrays done */
  299. '////////////////////////////////
  300. #End If
  301. End Sub

  302. #If UseMSVCRT Then

  303. Private Sub Class_Initialize()
  304. Dim s As String
  305. '///
  306. m_hMod = LoadLibrary("msvcrt.dll")
  307. m_lpFunc = GetProcAddress(m_hMod, "qsort")
  308. '///
  309. s = "89 E0 E8 00 00 00 00 83 04 24 15 6A 04 FF 70 08" + _
  310. "FF 70 04 FF 50 0C 83 C4 10 C2 10 00 6A 00 89 E0" + _
  311. "8B 15 ObjPtr 50 FF 35 UserData 8B 48 0C" + _
  312. "8B 40 08 FF 31 FF 30 8B 0A 52 FF 51 1C 58 C3"
  313. s = Replace(s, "ObjPtr", ReverseHex(VarPtr(m_lpObjPtr)))
  314. s = Replace(s, "UserData", ReverseHex(VarPtr(m_nUserData)))
  315. CodeFromString s, m_bCode
  316. End Sub

  317. Private Sub Class_Terminate()
  318. FreeLibrary m_hMod
  319. End Sub

  320. Private Sub CodeFromString(ByVal s As String, ByRef b() As Byte)
  321. Dim m As Long, i As Long
  322. s = Replace(s, " ", "")
  323. s = Replace(s, ",", "")
  324. m = Len(s) \ 2
  325. For i = 0 To m - 1
  326. b(i) = Val("&H" + Mid(s, i + i + 1, 2))
  327. Next i
  328. End Sub

  329. Private Function ReverseHex(ByVal n As Long) As String
  330. Dim s As String
  331. s = Right("00000000" + Hex(n), 8)
  332. ReverseHex = Mid(s, 7, 2) + Mid(s, 5, 2) + Mid(s, 3, 2) + Mid(s, 1, 2)
  333. End Function

  334. #End If
复制代码

TA的精华主题

TA的得分主题

发表于 2015-4-27 16:53 | 显示全部楼层
法师的几个所谓快速排序实质上是混合排序,用快速排序+(希尔、插入、冒泡)作为排序,它的优化体现在以下几个好处:
1、减少递归,当排序的R-L小于某个值时,改用其他(如希尔)排序,这样递归次数减少不少,但深度还不够,这个判断应该放在在调用递归时候判断,可以省一倍递归量;
2、优化对重复值的敏感性,原始快速排序对重复值多速度下降得很快;
3、用随机枢纽值+三值取中提高快排的稳定性。
如果按随机值作数据源,这个优化也就快17%左右而已。而事实上,如果真要提到速度上,指定数据类型是必不可少的,对于数值型,快慢差别不大,对于字符串型,相差很大,需要用指针才能做得更快。

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2015-4-27 17:09 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
本帖最后由 汇铁 于 2015-4-27 17:10 编辑
Zamyi 发表于 2015-4-27 16:53
法师的几个所谓快速排序实质上是混合排序,用快速排序+(希尔、插入、冒泡)作为排序,它的优化体现在以下几 ...

在这折腾啊。我还在那边等你。你在我的一亿取十万中,首次给出的的代码是不是有误?

字符型,要快的话。可不是用指针的问题。要用链表。我是这样想的。

点评

VB有链表吗?  发表于 2015-4-27 17:15

TA的精华主题

TA的得分主题

发表于 2015-4-27 17:17 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
本帖最后由 汇铁 于 2015-4-27 17:18 编辑
Zamyi 发表于 2015-4-27 16:53
法师的几个所谓快速排序实质上是混合排序,用快速排序+(希尔、插入、冒泡)作为排序,它的优化体现在以下几 ...
Zamyi  VB有链表吗?
可用数组代替或叫模拟。

我在一亿取十万的链排序中。已经用了。

TA的精华主题

TA的得分主题

发表于 2015-4-28 08:41 | 显示全部楼层
Zamyi 发表于 2015-4-27 15:08
1、你那排序结果不对;
2、要比较,需在同条件下,数组、变量类型都要相同。
  1. '测试代码
  2. Sub test()
  3. Dim n() As Long
  4. m = 1048576
  5. ReDim n(1 To m)
  6. For i = 1 To m
  7.     n(i) = 10000 * Rnd
  8. Next
  9. Dim a() As Long, b() As Long   '保证变量类型相同
  10. a = n: b = n     '保证数组相同
  11. t = Timer
  12. QuickSort_A1 a, LBound(a), UBound(a)  '对数组a排序
  13. Debug.Print Timer - t
  14. iSum = 0
  15. For i = 1 To m - 1
  16.     iSum = iSum - (a(i) > a(i + 1))
  17. Next
  18. Debug.Print iSum  '如果iSum不等于0,证明算法有误
  19. t = Timer
  20. QuickSort b           '对数组b排序
  21. Debug.Print Timer - t
  22. jSum = 0
  23. For i = 1 To m - 1
  24.     jSum = jSum - (b(i) > b(i + 1))
  25. Next
  26. Debug.Print jSum  '如果iSum不等于0,证明算法有误
  27. End Sub
复制代码
  1. '仙剑魔的代码
  2. Public Sub QuickSort(ByRef vArray() As Long)
  3.     Dim iLow As Long
  4.     Dim iHi As Long
  5.    
  6.     '//get range of array
  7.     iLow = LBound(vArray) '//Low bound
  8.     iHi = UBound(vArray)  '//High bound
  9.    
  10.     '//use STACK, not RECURSION
  11.     StartSort vArray(), iLow, iHi   '//call the procedure
  12.    
  13. End Sub

  14. Private Sub StartSort(ByRef key_arr() As Long, L As Long, R As Long)
  15.     Dim i As Long, j As Long
  16.     Dim x As Long, Swap As Long
  17.     If R - L <= 16 Then
  18.         For i = L To R
  19.             x = i
  20.             For j = i + 1 To R
  21.                 If key_arr(j) < key_arr(x) Then
  22.                     x = j
  23.                 End If
  24.             Next j
  25.             
  26.             If x > i Then
  27.                 Swap = key_arr(i)
  28.                 key_arr(i) = key_arr(x)
  29.                 key_arr(x) = Swap
  30.             End If
  31.         Next i
  32.     Else
  33.         x = key_arr((L + R) \ 2)
  34.         i = L
  35.         j = R
  36.         Do While i <= j
  37.             Do While key_arr(i) < x
  38.                 i = i + 1
  39.             Loop
  40.             
  41.             Do While key_arr(j) > x
  42.                 j = j - 1
  43.             Loop
  44.            
  45.             If i <= j Then
  46.                 Swap = key_arr(i)
  47.                 key_arr(i) = key_arr(j)
  48.                 key_arr(j) = Swap
  49.                 i = i + 1
  50.                 j = j - 1
  51.             End If
  52.         Loop

  53.         '递归方法
  54.         If (L < j) Then Call StartSort(key_arr, L, j)
  55.         If (i < R) Then Call StartSort(key_arr, i, R)
  56.     End If
  57. End Sub
复制代码
  1. '法师的代码
  2. Public Sub QuickSort_A1(ByRef key_arr() As Long, L As Long, R As Long)
  3. Dim i As Long, j As Long, a As Long, b As Long, Mid As Long, offset As Long
  4. Dim Pivot, Swap
  5.     If R - L <= 60 Then
  6.         For offset = 0 To 18
  7.             For i = L + offset To R Step 19
  8.                 Swap = key_arr(i)
  9.                 For j = i - 19 To L + offset Step -19
  10.                     If Swap < key_arr(j) Then
  11.                         key_arr(j + 19) = key_arr(j)
  12.                         key_arr(j) = Swap
  13.                     Else
  14.                         Exit For
  15.                     End If
  16.                 Next j
  17.             Next i
  18.         Next offset
  19.         
  20.         For offset = 0 To 4
  21.             For i = L + offset To R Step 5
  22.                 Swap = key_arr(i)
  23.                 For j = i - 5 To L + offset Step -5
  24.                     If Swap < key_arr(j) Then
  25.                         key_arr(j + 5) = key_arr(j)
  26.                         key_arr(j) = Swap
  27.                     Else
  28.                         Exit For
  29.                     End If
  30.                 Next j
  31.             Next i
  32.         Next offset
  33.         
  34.         For i = L + 1 To R
  35.             Swap = key_arr(i)
  36.             For j = i - 1 To L Step -1
  37.                 If Swap < key_arr(j) Then
  38.                     key_arr(j + 1) = key_arr(j)
  39.                     key_arr(j) = Swap
  40.                 Else
  41.                     Exit For
  42.                 End If
  43.             Next j
  44.         Next i
  45.     Else
  46.    
  47.         Mid = L + 1 + Int(Rnd * (R - L - 1))
  48. '        Mid = (L + R) / 2
  49.         If key_arr(L) > key_arr(R) Then
  50.             Swap = key_arr(R)
  51.             key_arr(R) = key_arr(L)
  52.             key_arr(L) = Swap
  53.         End If
  54.         If key_arr(Mid) > key_arr(R) Then
  55.             Swap = key_arr(R)
  56.             key_arr(R) = key_arr(Mid)
  57.             key_arr(Mid) = Swap
  58.         End If
  59.         If key_arr(L) > key_arr(Mid) Then
  60.             Swap = key_arr(L)
  61.             key_arr(L) = key_arr(Mid)
  62.             key_arr(Mid) = Swap
  63.         End If
  64.         
  65.         Pivot = key_arr(Mid)
  66.         key_arr(Mid) = key_arr(R - 1)
  67.         key_arr(R - 1) = Pivot
  68.         i = L + 1
  69.         j = R - 2
  70.         While (i < j)
  71.             For i = i To R
  72.                 If key_arr(i) >= Pivot Then Exit For
  73.             Next i
  74.             For j = j To L Step -1
  75.                 If key_arr(j) <= Pivot Then Exit For
  76.             Next j
  77.             If (i < j) Then
  78.                 Swap = key_arr(i)
  79.                 key_arr(i) = key_arr(j)
  80.                 key_arr(j) = Swap
  81.                 i = i + 1
  82.                 j = j - 1
  83.             End If
  84.         Wend

  85.         For a = j To L Step -1
  86.             If key_arr(a) < Pivot Then Exit For
  87.         Next a
  88.         For b = i To R
  89.             If key_arr(b) > Pivot Then Exit For
  90.         Next b
  91.         
  92.         '递归方法
  93.         If (L < a) Then Call QuickSort_A1(key_arr, L, a)
  94.         If (b < R) Then Call QuickSort_A1(key_arr, b, R)
  95.         
  96.     End If
  97. End Sub
复制代码

TA的精华主题

TA的得分主题

发表于 2015-4-28 08:45 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖最后由 loquat 于 2015-4-28 09:00 编辑

测试环境,win7 32位 i5-3470 3.2GHz, 4G内存
楼上代码本人电脑上的测试结果:
1.425781
0
.9628906
0
提升了32%
如果在VB6里,开启优化,编译后的结果如下:
.3867188
0
.1660156
0
提升了57%
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-11-15 07:39 , Processed in 0.038463 second(s), 12 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表