【问题标题】:sort very long list of integers quickly in python在python中快速排序很长的整数列表
【发布时间】:2019-05-16 02:20:08
【问题描述】:

我有一个包含几亿个 np.uint8 元素的向量。它们的值范围仅从 0 到 255。

我需要对这个列表进行排序,我认为它应该比快速排序处理得更快。我想我可以找到所有值“0”的索引并将它们放在前面,然后对于所有值“1”并将它们放在最后一次插入之后,直到我完成为止。它将是唯一的突变后代,并带有一些索引并且应该很快工作。

是否有一个内置程序可以很好地、正确地执行此操作,并且可以在诸如“C”之类的快速的东西中完成,而无需我自己自制?你能指点我吗?

假设作为我实际问题的“玩具”,我想对 mandrill image 的 100 兆像素版本的每种颜色 (rgb) 的强度值进行排序,其中每种颜色都已转换为单一的、非常long,uint8 值的向量。如果我要在 python 中计算排序方法之间的差异,这将是合理的计算?

【问题讨论】:

  • 您是对的,如果您只有少量值(例如 256),您可以使用您描述的“桶排序”(其中箱数是值的数量)。它将在O(n) 时间内工作(有额外的空间影响)
  • 不要重新发明轮子。大多数语言现在都实现了合并排序,这比你可以自制的任何东西都快。您在这里描述的是基数排序,它只是在达到特定数字时增加索引。然后你可以重新创建有序数组。
  • 如果您搜索“Python 排序教程”这个短语,您会找到比我们在此处的答案中更好地解释它的资源。
  • 这是一个数组还是列表?如果是数组,是一维的吗?
  • 你打算对排序列表做什么?可能有比数据的排序副本更简单的东西,这取决于您要对结果做什么。例如。看看numpy.bincount

标签: python numpy sorting int


【解决方案1】:

您可能会发现 numpy.bincount 就是您所需要的。它计算数据中每个整数的出现次数。

例如,这里有一些随机的无符号 8 位整数:

In [100]: np.random.seed(8675309)                                                                                                                                                                      

In [101]: r = np.random.gamma(9, scale=8.5, size=100000).astype(np.uint8)                                                                                                                              

In [102]: r.min(), r.max()                                                                                                                                                                             
Out[102]: (11, 242)

使用bincount计算整数:

In [103]: b = np.bincount(r, minlength=256)                                                                                                                                                            

In [104]: b                                                                                                                                                                                            
Out[104]: 
array([   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
          1,    1,    3,    1,    5,   13,    9,   17,   24,   31,   27,
         41,   55,   63,   96,  131,  146,  178,  210,  204,  268,  297,
        308,  367,  422,  480,  512,  584,  635,  669,  671,  759,  830,
        885,  934,  955, 1025, 1105, 1146, 1145, 1344, 1271, 1353, 1300,
       1456, 1419, 1451, 1504, 1499, 1561, 1600, 1509, 1678, 1621, 1643,
       1633, 1616, 1574, 1677, 1664, 1682, 1625, 1608, 1581, 1598, 1575,
       1583, 1524, 1493, 1381, 1448, 1399, 1422, 1249, 1322, 1225, 1278,
       1174, 1246, 1128, 1161, 1077,  999, 1033,  980,  981,  897,  917,
        880,  813,  779,  774,  697,  716,  651,  612,  657,  592,  556,
        497,  482,  474,  484,  445,  411,  399,  354,  368,  363,  342,
        313,  301,  293,  263,  241,  249,  244,  196,  215,  182,  189,
        172,  161,  139,  143,  142,  120,  121,  104,  103,  112,   88,
         82,   88,   67,   60,   83,   57,   63,   59,   50,   52,   55,
         40,   34,   34,   43,   35,   33,   28,   24,   26,   20,   18,
         21,   26,   30,   17,   15,   12,   17,   11,    7,    6,   16,
          8,    3,    4,   12,    9,    6,    5,    8,   10,    7,    1,
          4,    8,    5,    3,    2,    1,    0,    1,    1,    0,    1,
          0,    0,    4,    2,    2,    0,    0,    2,    0,    1,    1,
          1,    4,    0,    0,    0,    0,    0,    0,    0,    0,    2,
          1,    0,    0,    0,    0,    0,    1,    0,    0,    0,    0,
          0,    0,    0,    1,    0,    0,    0,    0,    0,    0,    0,
          1,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0])

所以 0 在r 中出现 0 次,13 出现 3 次,依此类推:

In [105]: b[0], b[13]                                                                                                                                                                                  
Out[105]: (0, 3)

【讨论】:

    【解决方案2】:

    您可以在不使用 bincount 排序的情况下执行此操作并重复:

    In [11]: a = np.bincount(np.array([71, 9, 1, 2, 3, 4, 4, 4, 8, 9, 9, 71], dtype=np.uint8), minlength=256)
    
    In [12]: np.repeat(np.arange(256, dtype=np.uint8), a)
    Out[12]: array([ 1,  2,  3,  4,  4,  4,  8,  9,  9,  9, 71, 71], dtype=uint8)
    

    【讨论】:

      【解决方案3】:

      如果您只需要排序后的,那么bincount 确实是要走的路。但是,如果您需要的是更像 argsort,例如,您需要对一些其他相同长度的数组进行共同排序,那么您可以使用 this Q&A 它比较各种方法,其中一些方法比“幼稚”要快得多argsort.

      【讨论】:

        猜你喜欢
        • 2021-01-11
        • 1970-01-01
        • 2016-03-19
        • 2010-11-15
        • 1970-01-01
        • 2012-05-24
        • 2021-07-14
        • 1970-01-01
        • 2023-03-15
        相关资源
        最近更新 更多