【问题标题】:Sorting 2D Array - VBScript - RadixSort Fastest - Integer - Code Requested对二维数组进行排序 - VBScript - RadixSort 最快 - 整数 - 请求代码
【发布时间】:2013-02-24 20:13:50
【问题描述】:

您能否协助/请求代码片段以有效排序。 找不到 vbscript 的基数排序 - 二维数组/能够很好地实现。

我的数组的示例结构是:

resultarray(0,1) = "Name1"
resultarray(1,1) = "Score1"
resultarray(2,1) = "Category1"
resultarray(3,1) = "OtherDetail1"
resultarray(4,1) = "OtherDetail1"
resultarray(5,1) = "OtherDetail1"

resultarray(0,2) = "Name2"
resultarray(1,2) = "Score2"
resultarray(2,2) = "Category2"
resultarray(3,2) = "OtherDetail2"
resultarray(4,2) = "OtherDetail2"
resultarray(5,2) = "OtherDetail2"

resultarray(0,3) = "Name3"
resultarray(1,3) = "Score3"
resultarray(2,3) = "Category3"
resultarray(3,3) = "OtherDetail3"
resultarray(4,3) = "OtherDetail3"
resultarray(5,3) = "OtherDetail3"

数组必须根据第二列进行排序,即分数。 行数大约为几百万。 分数将始终为正整数(在不久的将来需要两位小数)。 速度非常重要,因为这必须针对 30 到 40 个不同组的几万到几百万个数字进行。

目前使用 Quicksort 完全来自:

http://www.4guysfromrolla.com/webtech/012799-3.shtml

我在我的实现中交换了行 列,那么这工作正常。 但是慢。 是否值得从现有的 QuickSort 更改排序技术。

我打算稍后使用二分搜索根据分数匹配搜索大约 2000 个元素。

谢谢

【问题讨论】:

    标签: algorithm optimization vbscript sorting


    【解决方案1】:

    这样的事情怎么样(使用最大分数作为 sortedarray 的上维):

    Dim sortedarray(5, MAXIMUM_SCORE_GOES_HERE)
    for i=LBound(resultarray) to UBound(resultarray)
        idxTarget = resultarray(1,i);
        sortedarray(0,idxTarget) = resultarray(0,i)
        sortedarray(1,idxTarget) = resultarray(1,i)
        sortedarray(2,idxTarget) = resultarray(2,i)
        sortedarray(3,idxTarget) = resultarray(3,i)
        sortedarray(4,idxTarget) = resultarray(4,i)
        sortedarray(5,idxTarget) = resultarray(5,i)
    Next
    

    这是基数排序,没有基数部分。没有比这更快的了。我像你一样展开了“内循环”,但是如果有一个内循环,它可能会更快:而不是索引第一个维度,尝试循环遍历它,它实际上可能更快。此外,您可能想尝试 For Each...Next 而不是上面编写的 for 循环:有时 For Each 更快。但就排序算法而言,更快是不可能的。

    【讨论】:

    • 另一个问题,我现在面临的是“堆栈空间不足”。不要认为这是记录的数量,(仅约 250,000 条)。
    • 在排序过程中是否这样做?在哪一行?
    • '== 递归调用函数 .. Quicksort 的美妙之处 '== 第一部分中有 2 个或更多项 if loBound
    • 尝试使用不同的数据集,它适用于具有 450,000 行的一组数据。是比较的次数造成了差异吗?如何解决这个问题。
    • 好吧,快速排序递归的,所以这是有道理的。如果枢轴被完美地选择,你将有更少的递归调用,但我认为你想做的比快速排序更好。
    【解决方案2】:

    我不知道您在更改和弯曲数据方面有多灵活,但您可以使用 ArrayList 并对其执行 Sort 方法。这是一个概念证明:

    option explicit
    ' Create an arraylist to add items to
    Dim i, score, t
    dim list : Set list = CreateObject("System.Collections.ArrayList")
    
    for i = 0 to 1000000
            ' Make an arbitrairy score between 0 and 100
            score = cint(rnd*100)
            ' pad with zero's to make the sort work correctly
            score = string(3 - len(score), "0") & score
            ' Add it to the arraylist
            list.add join(array(score, "name", "category", "details1", "details2", "details3"), vbTab)
    Next
    
    ' Sort the list
    t = timer()
    list.sort
    
    ' Show the list
    wscript.echo "duration: " & timer() - t
    wscript.echo join(list.toArray(), vbNewLine)
    

    这会返回 2.6 秒的持续时间来对我的机器(Intel i5)上的 1.000.000 个项目进行排序。

    如前所述,您不能直接在数据格式上使用它,但如果性能是一项重要要求,则值得更改您的数据模型。

    【讨论】:

    • 补充思考(尤其是SortedList),见stackoverflow.com/q/14563678/603855
    • @Ekkehard.Horner 考虑过这一点,但关键列表(即分数)必须是唯一的,同时可以呈现相同的分数。我无法让 sortedlist 为键列表中的 longs 以外的其他值工作,但也许我做错了什么。否则会很好,因为您可以在值条目中添加自制 ScoreItem 对象。
    【解决方案3】:

    说明原因

    1. 您不应在 ArrayList 中复制原始数组中的数据,而应使用/存储索引
    2. SortedList 适用于分组问题(不是排序)

    概念证明脚本:

      Dim nRecs : nRecs = 100
      ReDim aOrg(1, nRecs)
      Dim i
      For i = 1 To nRecs ' aOrg[0] intentinally wasted
          aOrg(0, i) = "Item " &  i
          aOrg(1, i) = IRandR(5, 16)
      Next
      Dim slX : Set slX = CreateObject("System.Collections.SortedList")
      For i = 1 To nRecs
          If Not slX.Contains(aOrg(1, i)) Then Set slX(aOrg(1, i)) = CreateObject("System.Collections.ArrayList")
          slX(aOrg(1, i)).Add i
      Next
      For i = 0 To slX.Count - 1
          WScript.Echo "---- #", i, "score:", slX.GetKey(i)
          WScript.Echo vbTab, Join(slX.GetByIndex(i).ToArray())
          WScript.Echo vbTab, Join(GetCargo(aOrg, slX.GetByIndex(i)))
      Next
    
    Function GetCargo(aO, aI)
      ReDim aTmp(aI.Count - 1)
      Dim i
      For i = 0 To UBound(aTmp)
          aTmp(i) = aO(0, aI(i))
      Next
      GetCargo = aTmp
    End Function
    

    输出:

    ---- # 0 score: 5
             7 11 18 23 44 50 69 85 96 99
             Item 7 Item 11 Item 18 Item 23 Item 44 Item 50 Item 69 Item 85 Item 96 Item 99
    ---- # 1 score: 6
             41 46 47 58 59 80
             Item 41 Item 46 Item 47 Item 58 Item 59 Item 80
    ---- # 2 score: 7
             29 36 39 66 67 72 95 97
             Item 29 Item 36 Item 39 Item 66 Item 67 Item 72 Item 95 Item 97
    ---- # 3 score: 8
             4 5 26 30 49 51 53 57 64 75 93
             Item 4 Item 5 Item 26 Item 30 Item 49 Item 51 Item 53 Item 57 Item 64 Item 75 Item 93
    ---- # 4 score: 9
             12 15 20 52 56 61 62 74 79 88 94 100
             Item 12 Item 15 Item 20 Item 52 Item 56 Item 61 Item 62 Item 74 Item 79 Item 88 Item 94 Item 100
    ---- # 5 score: 10
             2 21 25 40 70 86 90 91 92
             Item 2 Item 21 Item 25 Item 40 Item 70 Item 86 Item 90 Item 91 Item 92
    ---- # 6 score: 11
             3 24 27 33 45 65 68 77 78 81
             Item 3 Item 24 Item 27 Item 33 Item 45 Item 65 Item 68 Item 77 Item 78 Item 81
    ---- # 7 score: 12
             1 10 28 37 43 60 63 82 89
             Item 1 Item 10 Item 28 Item 37 Item 43 Item 60 Item 63 Item 82 Item 89
    ---- # 8 score: 13
             6 8 9 14 22 48 73
             Item 6 Item 8 Item 9 Item 14 Item 22 Item 48 Item 73
    ---- # 9 score: 14
             13 17 31 32 71 84
             Item 13 Item 17 Item 31 Item 32 Item 71 Item 84
    ---- # 10 score: 15
             16 19 34 35 38 42 54 55 76 83 87 98
             Item 16 Item 19 Item 34 Item 35 Item 38 Item 42 Item 54 Item 55 Item 76 Item 83 Item 87 Item 98
    

    【讨论】:

      猜你喜欢
      • 2017-09-14
      • 1970-01-01
      • 2021-02-03
      • 2011-12-17
      • 2013-08-17
      • 2015-09-17
      • 2021-05-23
      相关资源
      最近更新 更多