如何在Ruby中实现Java的Comparable模块

问题描述

我目前正在翻Robert Sedgewick's Algorithms本书。在实现优先级队列的书中,使用了Comparable模块。在查看top k frequent elements leetcode problem时,我注意到我的Ruby实现中会出现错误。

def top_k_frequent(nums,k)
  ans = []
  h = Hash.new(0)

  nums.each do |num|
    h[num] += 1
  end

  heap = Heap.new
  h.each do |k,v|
    heap.insert({k => v})
  end

  k.times do
    a = heap.del_max
    ans.push(a.keys[0])
  end

  ans
end


class Heap
  def initialize
    @n = 0
    @pq = []
  end

  def insert(v)
    @pq[@n += 1] = v
    swim(@n)
  end

  def swim(k)
    while k > 1 && less((k / 2).floor,k)
      swap((k / 2).floor,k)
      k = k/2
    end
  end

  def swap(i,j)
    temp = @pq[i]
    @pq[i] = @pq[j]
    @pq[j] = temp
  end

  def less(i,j)
    @pq[i].values[0] < @pq[j].values[0]
  end

  def del_max
    max = @pq[1]
    swap(1,@n)
    @n -= 1
    @pq[@n + 1] = nil
    sink(1)
    max
  end

  def sink(k)
    while 2 * k <= @n
      j = 2 * k

      if !@pq[j + 1].nil?
        j += 1 if j > 1 && @pq[j].values[0] < @pq[j + 1].values[0]
      end
      break if !less(k,j)

      swap(k,j)
      k = j
    end
  end
end

上面是Java Priority Queue实现。

解决方法

Ruby的可比运算符为<=>,它将返回-101nil中的一个(nil表示无法比较)。

为了比较两个对象,两个都需要实现方法def <=>(other)。它不在Object上,因此在任何未实现它或从实现它的类扩展的对象上不可用。例如,数字和字符串确实具有实现。哈希不。

认为在您的情况下,问题略有不同。

调用queue.insert(my_hash)时,您希望算法分解my_hash并以此为基础。取而代之的是,该算法将哈希作为单个原子对象并将其插入。

如果添加以下内容:

class Tuple
  attr_accessor :key,:value

  def initialize(key,value)
    @key = key
    @value = value
  end

  def <=>(other)
    return nil unless other.is_a?(Tuple)
    value <=> other.value
  end
end

然后这将允许您执行以下操作:

hsh = { 1 => 3,2 => 2,3 => 1}
tuples = hsh.map { |k,v| Tuple.new(k,v) }

tuples.each { |tuple| my_heap.insert(tuple) }

您将所有数据都放在堆中。

检索项目时,它将是一个元组,因此您只需调用item.keyitem.value即可访问数据。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...