【问题标题】:Can you formulate a monoid or semigroup for the radix sort?你能为基数排序制定一个幺半群或半群吗?
【发布时间】:2014-02-21 11:52:32
【问题描述】:

这是基数排序的伪代码:

Pseudocode for Radix Sort:
Radix-Sort(A, d)
// Each key in A[1..n] is a d-digit integer. (Digits are
// numbered 1 to d from right to left.)
1. for i = 1 to d do
Use a stable sorting algorithm to sort A on digit i.

这是基数排序的 Scala 代码:

object RadixSort {
  val WARP_SIZE = 32

  def main(args: Array[String]) = {
    var A = Array(123,432,654,3123,654,2123,543,131,653,123)

    radixSortUintHost(A, 4).foreach(i => println(i))
  }

  // LSB radix sort
  def radixSortUintHost(A: Array[Int], bits: Int): Array[Int] = {
    var a = A
    var b = new Array[Int](a.length)

    var rshift = 0
    var mask = ~(-1 << bits)

    while (mask != 0) {
      val cntArray = new Array[Int](1 << bits)

      for (p <- 0 until a.length) {
        var key = (a(p) & mask) >> rshift
        cntArray(key)+= 1
      }

      for (i <- 1 until cntArray.length)
        cntArray(i) += cntArray(i-1)

      for (p <- a.length-1 to 0 by -1) {
        var key = (a(p) & mask) >> rshift
        cntArray(key)-= 1
        b(cntArray(key)) = a(p)
      }

      val temp = b
      b = a
      a = temp

      mask <<= bits
      rshift += bits
    }

    b
  }
}

这是基数排序的 Haskell 代码:

import Data.Bits (Bits(testBit, bitSize))
import Data.List (partition)

lsdSort :: (Ord a, Bits a) => [a] -> [a]
lsdSort = fixSort positiveLsdSort

msdSort :: (Ord a, Bits a) => [a] -> [a]
msdSort = fixSort positiveMsdSort

-- Fix a sort that puts negative numbers at the end, like positiveLsdSort and positiveMsdSort
fixSort sorter list = uncurry (flip (++)) (break (< 0) (sorter list))

positiveLsdSort :: (Bits a) => [a] -> [a]
positiveLsdSort list = foldl step list [0..bitSize (head list)] where
step list bit = uncurry (++) (partition (not . flip testBit bit) list)

positiveMsdSort :: (Bits a) => [a] -> [a]
positiveMsdSort list = aux (bitSize (head list) - 1) list where
aux _ [] = []
aux (-1) list = list
aux bit list = aux (bit - 1) lower ++ aux (bit - 1) upper where
    (lower, upper) = partition (not . flip testBit bit) list

我的问题是:你能为基数排序制定一个幺半群或半群吗?

【问题讨论】:

  • 你的意思是一个新的半群实例,它的二元运算使用基数排序来保持顺序?
  • 您不能“将算法(排序或其他)编写为幺半群”。您也许可以使用 monoids 来制定算法,就像对您的其他问题stackoverflow.com/questions/21877572/… 的回答一样
  • 谢谢@AlexeyRomanov - 这很有帮助 - 我已经更新了问题。

标签: scala haskell radix monoids semigroup


【解决方案1】:

基数排序不变式是使用前 k 位对数据进行排序。 如果您想要一个添加更多数据排序的操作,您要求的是合并排序功能而不是基数。 如果您要向所有记录添加数据位,则可以使用 monoid。

编辑:幺半群的 hart 是一个关联操作。 我们可以将排序位视为应用偏序的一种方式。你一点一点地注入所有记录的数据。每个位都应用一个偏序。这是关联的,您可以合并一些位以获得更精细的偏序。注意顺序很重要,但它仍然是关联的。因此可以被视为 monad

【讨论】:

  • 谢谢@Meir - 假设我想要一个基数排序 - 你会怎么做?
【解决方案2】:

我认为您可能对基数排序的想法过于字面化了。抽象地说,我想你想要的幺半群是

  1. 排序的列表
  2. 合并

最大的问题是您希望如何表示已排序的列表。如果您将它们表示为已排序的 Haskell 列表,则合并操作是合并排序中常用的逐段合并。如果您以更“激进”的方式表示它们,那么您将拥有各种 trie。您可能可以找到一些用于合并尝试的算法。 bytestring-trie 中有一个,但似乎没有任何关于其实现的记录。

【讨论】:

  • 假设我想编写自己的数据结构?
  • @hawkeye,我不明白谁编写数据结构的意义。你能解释一下吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-12
  • 1970-01-01
  • 2016-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多