当前位置: 首页 > 知识库问答 >
问题:

Ruby中的递归合并排序

鄢修德
2023-03-14

我正在尝试编写一个ruby方法,它可以递归地执行合并排序。我有这个方法,但这是一次我偶然得到它的工作,所以我不知道它为什么工作,并很想了解我写的代码是如何工作的。在psuedocode中,我遵循的步骤如下所示。

  1. 拆分长度为n的原始数组,直到我拥有长度为1的n个数组
  2. 一次合并和排序长度为m的2个数组,以返回长度为m*2的数组
  3. 重复上述步骤,直到我有一个长度为n的当前排序数组

基本上,在我看来,这是一个分支成n个分支的大树,每个分支包含长度为1的数组。然后我需要取这n个分支,并以某种方式将它们合并回方法中的一个分支。

def merge_sort(arr)
  return arr if arr.length == 1
  merge(merge_sort(arr.slice(0, arr.length/2)), 
        merge_sort(arr.slice(arr.length/2, arr[-1])))
end

def merge(arr1, arr2)
  sorted = []
  begin
    less_than = arr1[0] <=> arr2[0]
    less_than = (arr1[0] == nil ? 1 : -1) if less_than == nil
    case less_than
    when -1  
      sorted << arr1[0]
      arr1 = arr1.drop(1)
    when 0
      sorted << arr1[0]
      sorted << arr2[0]
      arr1 = arr1.drop(1)
      arr2 = arr2.drop(1)
    when 1
      sorted << arr2[0]
      arr2 = arr2.drop(1)
    end
  end until (arr1.length == 0 && arr2.length == 0)
  sorted
end

merge_sort([1,6,3,8,22,3,11,24,54,68,79,80,98,65,46,76,53])

#Returns => [1, 3, 3, 6, 8, 11, 22, 24, 46, 53, 54, 65, 68, 76, 79, 80, 98]

我所拥有的方法实际上正确地排序了列表,但我不完全确定该方法是如何组合每个分支然后返回排序的合并列表的,而不是仅仅返回它组合的前两个数组。

此外,如果有人对我如何使merge方法看起来更像我所喜爱的ruby代码有想法,请告诉我。

共有2个答案

相俊迈
2023-03-14

下面是我的Ruby递归merge_sort方法版本。这与上面的操作完全相同,但略有不同。

    def merge_sort(array)
        array.length <= 1 ? array : merge_helper(merge_sort(array[0...array.length / 2]), merge_sort(array[array.length / 2..-1]))
    end


    def merge_helper(left, right, merged = [])
        left.first <= right.first ? merged << left.shift : merged << right.shift until left.length < 1 || right.length < 1 
        merged + left + right
    end


p merge_sort([]) # => []
p merge_sort([20, 8]) # => [8, 20]
p merge_sort([16, 14, 11]) # => [11, 14, 16]
p merge_sort([18, 4, 7, 19, 17]) # => [4, 7, 17, 18, 19]
p merge_sort([10, 12, 15, 13, 16, 7, 19, 2]) # => [2, 7, 10, 12, 13, 15, 16, 19]
p merge_sort([3, 14, 10, 8, 11, 7, 18, 17, 2, 5, 9, 20, 19]) # => [2, 3, 5, 7, 8, 9, 10, 11, 14, 17, 18, 19, 20]
许曦
2023-03-14

下面是我在Ruby中实现的mergesort

def mergesort(array)
  return array if array.length == 1
  middle = array.length / 2
  merge mergesort(array[0...middle]), mergesort(array[middle..-1])
end


def merge(left, right)
  result = []
  until left.length == 0 || right.length == 0 do
    result << (left.first <= right.first ? left.shift : right.shift)
  end
  result + left + right
end

正如您所看到的,mergeSort方法与您的方法基本相同,这是递归发生的地方,因此我将重点介绍这一点。

首先,您有基本情况:如果array.length==1这是允许递归工作而不是无限期地继续下去的原因。

接下来,在我的实现中,我定义了一个变量middle来表示数组的中间:middle=array.length/2

最后,第三行是所有工作发生的地方:merge mergesort(array[0...medide]),mergesort(array[medide..-1])

您在这里所做的是告诉merge方法将合并后的左半部分与合并后的右半部分合并。

如果假设输入数组是[9,1,5,4],那么您要说的是merge mergesort([9,1]),mergesort([5,4])

为了执行合并,首先必须进行mergesort[9,1]和mergesort[5,4]。然后递归变成

merge((merge mergesort([9]), mergesort([1])), (merge mergesort([5]), mergesort([4])))

当我们再次递归时,mergeSort([9])已到达基本大小写并返回[9]。类似地,mergeSort([1])也已到达基本大小写,并返回[1]。现在可以合并[9][1]。合并的结果为[1,9]

现在是合并的另一边。我们必须计算出合并mergesort([5])、mergesort([4])的结果,然后才能将其与[1,9]合并。按照与左侧相同的过程,我们得到[5][4]的基本情况,并将它们合并得到[4,5]

现在我们需要将[1,9][4,5]合并。

  1. 在第一次传递时,result接收1,因为1<=4。
  2. 在下一个pass中,我们使用result=[1]left=[9]right=[4,5]。当我们看到left.first<=right.first是否为false,因此返回right.shift4。现在结果=[1,4]
  3. 在第三遍中,我们使用result=[1,4]left=[9]right=[5]。当我们看到left.first<=right.first是否为false,因此返回right.shift5。现在结果=[1,4,5]
  4. 在此循环结束,因为正确。length==0
  5. 我们简单地将result+left+right[1,4,5]+[9]+[]串联起来,从而得到一个排序数组。
 类似资料:
  • 我有个小问题。我尝试实现合并排序算法递归。 现在我的问题: 左=合并排序(rrays.copyOfRange(iv_sort_list,0,iv_sort_list.length));右=合并排序(rrays.copyOfRange(iv_sort_list,iv_sort_list.length,iv_sort_list.length)); 如果我尝试分配我的左/右数组“mergeSort(..

  • 我在我的应用程序中有以下合并排序代码。我对递归方法在不满足if条件时从if块中出来后如何再次调用感到非常困惑。 我调试了我的代码,但我仍然没有得到它。调用mergesort(0,号-1)的排序方法首先从mergesort(0,5)开始。低小于高,中间是2,所以接下来运行mergesort(0,2)。这一直持续到我们有mergesort(0,0),在这种情况下,低不小于高,所以它来自if块。但是当我

  • 我正在尝试理解递归排序函数,它是mergesort算法的一部分。下面是我的代码,我几乎可以肯定它是正确的(通过在线课程)。 我理解合并的作用——它将每个子数组分解成两个较小的子数组,重复这个过程,直到子数组的长度为1(根据定义排序),然后合并。然而,这个排序函数用来完成这个任务的实际方法对我来说很难理解。也许是因为我不习惯递归函数,但是我想知道是否有人可以在第一次合并发生时阐明操作的顺序和参数是什

  • 如果在这个程序中,我正在输入一个大小7.so的数组从main()merge_sort(arr,0,6)被传递到相应的函数后,条件被检查,如果(0 但我能够理解合并排序(arr,mid1,high);有人打电话吗?但这个程序运行良好。请解释编译器如何调用merge_sort(arr、mid 1、high)

  • 最后一个函数返回15->20,然后组合为root.next->temp,但是在返回temp的步骤之后,为什么会返回根值。即10->15->20,而我希望只返回temp。 请找到代码,

  • 我试图实现一个递归合并排序算法来排序一个简单的整数数组,但我得到奇怪的值为索引在我的数组的后半部分。前半部分似乎排序精细,这是令人困惑的,因为它是递归实现的。随机整数数组在我的main方法中初始化。 } 这会产生以下输出: 未排序数组={15,9,12,19,49,43,57,70,78,87}对于第1轮:第一个=0中间=4最后=9第1轮中的数组={15,9、12,19、49,43、57,70、7