傻瓜合并排序的解释

VPN*_*IME 20 python sorting algorithm mergesort

我在网上找到了这个代码:

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

def mergesort(list):
    if len(list) < 2:
        return list
    middle = len(list) / 2
    left = mergesort(list[:middle])
    right = mergesort(list[middle:])
    return merge(left, right)
Run Code Online (Sandbox Code Playgroud)

当我运行它时它100%工作.我只是没有真正了解合并排序的工作原理或递归函数如何正确地排序左右两种.

sen*_*rle 56

我认为理解合并排序的关键是理解以下原则 - 我将其称为合并原则:

给定从最小到最大排序的两个单独的列表A和B,通过重复比较A的最小值和B的最小值来构造列表C,移除较小的值,并将其附加到C.当一个列表用尽时,追加其他列表中的其余项目按顺序排列到C. 列表C也是排序列表.

如果你手工完成这几次,你会发现它是正确的.例如:

A = 1, 3
B = 2, 4
C = 
min(min(A), min(B)) = 1

A = 3
B = 2, 4
C = 1
min(min(A), min(B)) = 2

A = 3
B = 4
C = 1, 2
min(min(A), min(B)) = 3

A = 
B = 4
C = 1, 2, 3
Run Code Online (Sandbox Code Playgroud)

现在A已经用尽了,所以使用B中的剩余值扩展C:

C = 1, 2, 3, 4
Run Code Online (Sandbox Code Playgroud)

合并原则也很容易证明.A的最小值小于A的所有其他值,B的最小值小于B的所有其他值.如果A的最小值小于B的最小值,则它也必须小于比所有B的值都要小.因此它小于A的所有值和B的所有值.

因此,只要您继续将符合这些条件的值附加到C,您就会得到一个排序列表.这就是merge上面的功能.

现在,根据这个原则,很容易理解一种排序技术,它通过将列表分成较小的列表,对这些列表进行排序,然后将这些排序的列表合并在一起来对列表进行排序.该merge_sort函数只是一个函数,它将列表分成两半,对这两个列表进行排序,然后以上述方式将这两个列表合并在一起.

唯一的问题是因为它是递归的,当它对两个子列表进行排序时,它会通过将它们传递给它自己来实现!如果你在这里理解递归有困难,我建议先研究更简单的问题.但是如果你已经掌握了递归的基础知识,那么你必须意识到的是,单项列表已经被排序了.合并两个单项列表会生成一个已排序的两项列表; 合并两个两项目列表会生成一个已排序的四项目列表; 等等.

  • 我已经通过10-20个搜索结果,他们有可怕的图形解释.关于一般分类的文字段落和段落.这正是我想要的.减少追逐.给了我基本上是什么想法的肉.非常感谢.现在我必须谷歌类似的quicksort描述. (5认同)
  • 优秀。合并排序的基本单元的非常好的演练。 (2认同)

ovg*_*vin 15

当我偶然发现难以理解算法是如何工作的时候,我添加了调试输出以检查算法中究竟发生了什么.

这里的代码带有调试输出.尝试通过递归调用mergesort以及merge输出结果来理解所有步骤:

def merge(left, right):
    result = []
    i ,j = 0, 0
    while i < len(left) and j < len(right):
        print('left[i]: {} right[j]: {}'.format(left[i],right[j]))
        if left[i] <= right[j]:
            print('Appending {} to the result'.format(left[i]))           
            result.append(left[i])
            print('result now is {}'.format(result))
            i += 1
            print('i now is {}'.format(i))
        else:
            print('Appending {} to the result'.format(right[j]))
            result.append(right[j])
            print('result now is {}'.format(result))
            j += 1
            print('j now is {}'.format(j))
    print('One of the list is exhausted. Adding the rest of one of the lists.')
    result += left[i:]
    result += right[j:]
    print('result now is {}'.format(result))
    return result

def mergesort(L):
    print('---')
    print('mergesort on {}'.format(L))
    if len(L) < 2:
        print('length is 1: returning the list withouth changing')
        return L
    middle = len(L) / 2
    print('calling mergesort on {}'.format(L[:middle]))
    left = mergesort(L[:middle])
    print('calling mergesort on {}'.format(L[middle:]))
    right = mergesort(L[middle:])
    print('Merging left: {} and right: {}'.format(left,right))
    out = merge(left, right)
    print('exiting mergesort on {}'.format(L))
    print('#---')
    return out


mergesort([6,5,4,3,2,1])
Run Code Online (Sandbox Code Playgroud)

输出:

---
mergesort on [6, 5, 4, 3, 2, 1]
calling mergesort on [6, 5, 4]
---
mergesort on [6, 5, 4]
calling mergesort on [6]
---
mergesort on [6]
length is 1: returning the list withouth changing
calling mergesort on [5, 4]
---
mergesort on [5, 4]
calling mergesort on [5]
---
mergesort on [5]
length is 1: returning the list withouth changing
calling mergesort on [4]
---
mergesort on [4]
length is 1: returning the list withouth changing
Merging left: [5] and right: [4]
left[i]: 5 right[j]: 4
Appending 4 to the result
result now is [4]
j now is 1
One of the list is exhausted. Adding the rest of one of the lists.
result now is [4, 5]
exiting mergesort on [5, 4]
#---
Merging left: [6] and right: [4, 5]
left[i]: 6 right[j]: 4
Appending 4 to the result
result now is [4]
j now is 1
left[i]: 6 right[j]: 5
Appending 5 to the result
result now is [4, 5]
j now is 2
One of the list is exhausted. Adding the rest of one of the lists.
result now is [4, 5, 6]
exiting mergesort on [6, 5, 4]
#---
calling mergesort on [3, 2, 1]
---
mergesort on [3, 2, 1]
calling mergesort on [3]
---
mergesort on [3]
length is 1: returning the list withouth changing
calling mergesort on [2, 1]
---
mergesort on [2, 1]
calling mergesort on [2]
---
mergesort on [2]
length is 1: returning the list withouth changing
calling mergesort on [1]
---
mergesort on [1]
length is 1: returning the list withouth changing
Merging left: [2] and right: [1]
left[i]: 2 right[j]: 1
Appending 1 to the result
result now is [1]
j now is 1
One of the list is exhausted. Adding the rest of one of the lists.
result now is [1, 2]
exiting mergesort on [2, 1]
#---
Merging left: [3] and right: [1, 2]
left[i]: 3 right[j]: 1
Appending 1 to the result
result now is [1]
j now is 1
left[i]: 3 right[j]: 2
Appending 2 to the result
result now is [1, 2]
j now is 2
One of the list is exhausted. Adding the rest of one of the lists.
result now is [1, 2, 3]
exiting mergesort on [3, 2, 1]
#---
Merging left: [4, 5, 6] and right: [1, 2, 3]
left[i]: 4 right[j]: 1
Appending 1 to the result
result now is [1]
j now is 1
left[i]: 4 right[j]: 2
Appending 2 to the result
result now is [1, 2]
j now is 2
left[i]: 4 right[j]: 3
Appending 3 to the result
result now is [1, 2, 3]
j now is 3
One of the list is exhausted. Adding the rest of one of the lists.
result now is [1, 2, 3, 4, 5, 6]
exiting mergesort on [6, 5, 4, 3, 2, 1]
#---
Run Code Online (Sandbox Code Playgroud)

  • 精彩的解释方式..没有@senderle答案,我无法理解你的答案,没有你的答案就无法理解发送者! (2认同)