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

了解Python中的合并和排序算法

孙梓
2023-03-14

所以我试图理解python中这个简单的合并和排序算法。代码如下:

def merge(left, right, lt):
    """Assumes left and right are sorted lists.

    lt defines an ordering on the elements of the lists.
    Returns a new sorted(by lt) list containing the same elements
    as (left + right) would contain.

    """
    result = []
    i,j = 0, 0
    while i < len(left) and j < len(right):
       if lt(left[i], right[j]):
            result.append(left[i])
            i += 1
        else:
            result.append(right[j])
            j += 1
        while (i < len(left)):
            result.append(left[i])
            i += 1
        while (j < len(right)):
            result.append(right[j])
            j += 1
    return result

def sort(L, lt = lambda x,y: x < y):
    """Returns a new sorted list containing the same elements as L"""
    if len(L) < 2:
        return L[:]
    else:
        middle = int(len(L)/2)
        left = sort(L[:middle], lt)
        right = sort(L[middle:], lt)
        print left, right
        return merge(left, right, lt)

我明白了它的意图,我理解了合并函数中的所有代码,并且对排序函数有了基本的理解。

我不明白的是排序函数的“else”部分实际上是如何工作的。它似乎一直递归调用sort函数,将越来越小的拆分列表分配给左右变量。但是,既然它在每次调用递归函数时都将新列表分配给“左”和“右”,那么最终的结果不就是左和右的最小版本吗?

merge函数似乎位于递归之外,它如何知道需要合并创建的每个拆分列表?

共有2个答案

陈浩
2023-03-14

你应该画出调用堆栈,看看会发生什么。

当else子句再次调用sort函数时,该函数不会退出。每个调用都以一个return语句结束。

所以您是正确的,最初对排序的调用是在越来越小的列表中传递的,但是一旦长度小于2,“排序”就会返回列表本身。然后调用返回到它所在的位置并调用print,最后调用合并

试着用一个小列表记下每个通话。您将看到,最终会在已排序的小列表上调用合并(因为它们很短)。

段宏毅
2023-03-14

sort()是递归的,但在一定程度上是递归的。当列表的长度小于2(或等于1)时,if条件将中断递归:

if len(L) < 2:

维基百科实际上有一个很好的动画,展示了合并排序的工作原理

基本上,merge()组合两个排序列表并返回单个排序列表sort()递归地将列表分成几对,并一步一步地对这些对进行排序,在递归的每一步合并两个排序的对,以形成一个更大的排序列表。只需观看动画。它比我更善于解释。

 类似资料:
  • 我知道合并排序算法的基本概念,但是当涉及到通过递归实现它时,我很难理解它是如何工作的。据我所知,合并排序函数将我们当前的数组分成两半,并使用递归我们一直这样做,直到每边只剩下一个元素。 如果我们的数组是{38、27、43、3、9、82、10},那么我们的递归将从使用子数组(原始数组的左侧)调用自身开始,并每次重复该过程,将数组减半并存储最左侧,直到达到1个元素: 然后在我们的第二个子例程中,我们继

  • 这些是家庭作业问题,但我想了解它们背后的概念,而不仅仅是得到答案。 我知道MergeSort的运行时间是O(nlogn)。似乎合并方法必须运行 n 次(因为它必须合并所有数组,最终会有 n 个数组)。因此,我想我可以推断出 MergeSort() 方法将被称为 logn times。我也认为这是有道理的,因为它正在划分数组,所以它会一直将自己除以 2,所以 logn。 因此,我觉得答案分别是C和A

  • 我在理解合并排序算法的“合并”部分时有点困难,因为我试图在上下文中理解算法的部分,而某些变量/循环对我来说没有意义。我理解递归除法过程和合并的排序方面,但在这个特定的合并算法中: 我不明白最后3个循环: 你能解释一下这3个循环在合并的上下文中是用来做什么的吗?还有什么进一步的建议可以帮助你更好地理解合并排序算法的合并部分吗?

  • 双向合并排序与递归合并排序有何不同? 假设在合并排序中有5个数字需要排序8,9,1,6,4,我们按如下步骤1进行划分:{8,9,1}{6,4} 步骤2:{8,9}{1}{6}{4} 步骤3:{8}{9}{1}{6}{4} 现在合并 步骤4:{8,9}{1}{4,6} 步骤5:{1,8,9}{4,6} 第六步:{1,4,6,8,9} 但在双向合并排序中,我们将数组分为两个元素(但根据维基百科,在合并

  • 问题内容: 我正在尝试使用mergesort-我得到的- 计算列表中拆分反转的数量(也就是说,未排序列表的前半部分中的元素应该出现在列表的后半部分中的给定元素之后未排序的列表;例如[3 2 1 4]将包含分割反转(3,1),但不包含(3,2),因为3和2都在上半部。当我到达最终的打印语句时,我得到了我期望的答案- 在这种情况下为9-但是返回值都是不正确的,因为它通过递归返回分割值。我尝试了各种索引

  • 我在理解外部排序算法中的合并步骤时遇到了一定的困难。我在维基百科上看到了这个例子,但我无法理解。 外部排序的一个例子是外部合并排序算法,它对每个适合RAM的块进行排序,然后将排序后的块合并在一起。例如,对于仅使用100 MB RAM对900 MB数据进行排序:1)读取主内存中的100 MB数据,并通过一些常规方法进行排序,如快速排序。2) 将排序后的数据写入磁盘。3) 重复第1步和第2步,直到所有