归并排序算法误解

mergesort algorithm misunderstanding

Python同学,

我一直在研究基本算法,但在完全理解 MergeSort 时遇到了一些困难。 我相信我理解分而治之的方法,如何在每个循环周期内创建命名空间,以及算法如何拆分元素。我有点困惑的是它如何 reassembles/merges 元素,连续采用排序值。

我想我理解从结果行 21 到 37 的所有内容。即 nlist 如何转换为 [27, 43]。 我的具体问题是关于 results 第 38 行以及结果第 21 行 [43, 27]righthalf 如何取 nlist 的值,即 [27, 43]results 第 38 行).

因为我没有看到 nlistrighthalf,

的任何变量赋值

righthalf = nlist 不在 'results' 第 37 和 38 行之间的代码流中

MergeSort 算法(带有诊断打印语句):

def mergeSort(nlist):
    print("Splitting ", nlist)
    if len(nlist) > 1:
        mid = len(nlist) // 2
        lefthalf = nlist[: mid]
        righthalf = nlist[mid :]
        print('wow', 'lefthalf', lefthalf)
        mergeSort(lefthalf)
        print('this is the right1', righthalf)
        mergeSort(righthalf)
        print('this is the right2', righthalf)
        i = j = k = 0

        print("cool")
        while i < len(lefthalf) and j < len(righthalf):
            if lefthalf[i] < righthalf[j]:
                print('bot', 'k', 'i', 'j', 'lefthalf', 'righthalf', k, i, j, lefthalf, righthalf)
                nlist[k] = lefthalf[i]
                print('nlist[k]', nlist[k], nlist)
                i = i + 1
            else:
                print('me')
                nlist[k] = righthalf[j]
                print('k', 'nlist[k]', k, nlist[k], nlist)
                print(righthalf)
                j = j + 1

            k = k + 1

        while i < len(lefthalf):
            print('cot', 'k', 'i', 'lefthalf', k, i, lefthalf)
            nlist[k] = lefthalf[i]
            print('nlist[k]', nlist[k], nlist)
            i = i + 1
            k = k + 1

        while j < len(righthalf):
            print('dot', 'k', 'j', 'righthalf', k, j, righthalf)
            nlist[k] = righthalf[j]
            print('nlist[k]', nlist[k], nlist)
            j = j + 1
            k = k + 1

    print("Merging ", nlist)

nlist = [14, 46, 43, 27, 57, 41, 45, 21, 70]
mergeSort(nlist)
print(nlist) 

结果

1     Splitting  [14, 46, 43, 27, 57, 41, 45, 21, 70]
2     wow lefthalf [14, 46, 43, 27]
3     Splitting  [14, 46, 43, 27]
4     wow lefthalf [14, 46]
5     Splitting  [14, 46]
6     wow lefthalf [14]
7     Splitting  [14]
8     Merging  [14]
9     yah righthalf [46]
10    this is the right1 [46]
11    Splitting  [46]
12    Merging  [46]
13    this is the right2 [46]
14    cool
15    bot k i j lefthalf righthalf 0 0 0 [14] [46]
16    nlist[k] 14 [14, 46]
17    dot k j righthalf 1 0 [46]
18    nlist[k] 46 [14, 46]
19    Merging  [14, 46]
20    yah righthalf [43, 27]
21    this is the right1 [43, 27]
22    Splitting  [43, 27]
23    wow lefthalf [43]
24    Splitting  [43]
25    Merging  [43]
26    yah righthalf [27]
27    this is the right1 [27]
28    Splitting  [27]
29    Merging  [27]
30    this is the right2 [27]
31    cool
32    me
33    k nlist[k] 0 27 [27, 27]
34    [27]
35    cot k i lefthalf 1 0 [43]
36    nlist[k] 43 [27, 43]
37    Merging  [27, 43]
38    this is the right2 [27, 43]
39    cool
40    bot k i j lefthalf righthalf 0 0 0 [14, 46] [27, 43]
41    nlist[k] 14 [14, 46, 43, 27]
42    me
43    k nlist[k] 1 27 [14, 27, 43, 27]
44    [27, 43]
45    me
46    k nlist[k] 2 43 [14, 27, 43, 27]
47    [27, 43]
48    cot k i lefthalf 3 1 [14, 46]
49    nlist[k] 46 [14, 27, 43, 46]
50    Merging  [14, 27, 43, 46]
51    yah righthalf [57, 41, 45, 21, 70]
52    this is the right1 [57, 41, 45, 21, 70]
53    Splitting  [57, 41, 45, 21, 70]
54    wow lefthalf [57, 41]
55    Splitting  [57, 41]
56    wow lefthalf [57]
57    Splitting  [57]
58    Merging  [57]
59    yah righthalf [41]
60    this is the right1 [41]
61    Splitting  [41]
62    Merging  [41]
63    this is the right2 [41]
64    cool
65    me
66    k nlist[k] 0 41 [41, 41]
67    [41]
68    cot k i lefthalf 1 0 [57]
69    nlist[k] 57 [41, 57]
70    Merging  [41, 57]
71    yah righthalf [45, 21, 70]
72    this is the right1 [45, 21, 70]
73    Splitting  [45, 21, 70]
74    wow lefthalf [45]
75    Splitting  [45]
76    Merging  [45]
77    yah righthalf [21, 70]
78    this is the right1 [21, 70]
79    Splitting  [21, 70]
80    wow lefthalf [21]
81    Splitting  [21]
82    Merging  [21]
83    yah righthalf [70]
84    this is the right1 [70]
85    Splitting  [70]
86    Merging  [70]
87    this is the right2 [70]
88    cool
89    bot k i j lefthalf righthalf 0 0 0 [21] [70]
90    nlist[k] 21 [21, 70]
91    dot k j righthalf 1 0 [70]
92    nlist[k] 70 [21, 70]
93    Merging  [21, 70]
94    this is the right2 [21, 70]
95    cool
96    me
97    k nlist[k] 0 21 [21, 21, 70]
98    [21, 70]
99    bot k i j lefthalf righthalf 1 0 1 [45] [21, 70]
100   nlist[k] 45 [21, 45, 70]
101   dot k j righthalf 2 1 [21, 70]
102   nlist[k] 70 [21, 45, 70]
103   Merging  [21, 45, 70]
104   this is the right2 [21, 45, 70]
105   cool
106   me
107   k nlist[k] 0 21 [21, 41, 45, 21, 70]
108   [21, 45, 70]
109   bot k i j lefthalf righthalf 1 0 1 [41, 57] [21, 45, 70]
110   nlist[k] 41 [21, 41, 45, 21, 70]
111   me
112   k nlist[k] 2 45 [21, 41, 45, 21, 70]
113   [21, 45, 70]
114   bot k i j lefthalf righthalf 3 1 2 [41, 57] [21, 45, 70]
115   nlist[k] 57 [21, 41, 45, 57, 70]
116   dot k j righthalf 4 2 [21, 45, 70]
117   nlist[k] 70 [21, 41, 45, 57, 70]
118   Merging  [21, 41, 45, 57, 70]
119   this is the right2 [21, 41, 45, 57, 70]
120   cool
121   bot k i j lefthalf righthalf 0 0 0 [14, 27, 43, 46] [21, 41, 45, 57, 70]
122   nlist[k] 14 [14, 46, 43, 27, 57, 41, 45, 21, 70]
123   me
124   k nlist[k] 1 21 [14, 21, 43, 27, 57, 41, 45, 21, 70]
125   [21, 41, 45, 57, 70]
126   bot k i j lefthalf righthalf 2 1 1 [14, 27, 43, 46] [21, 41, 45, 57, 70]
127   nlist[k] 27 [14, 21, 27, 27, 57, 41, 45, 21, 70]
128   me
129   k nlist[k] 3 41 [14, 21, 27, 41, 57, 41, 45, 21, 70]
130   [21, 41, 45, 57, 70]
131   bot k i j lefthalf righthalf 4 2 2 [14, 27, 43, 46] [21, 41, 45, 57, 70]
132   nlist[k] 43 [14, 21, 27, 41, 43, 41, 45, 21, 70]
133   me
134   k nlist[k] 5 45 [14, 21, 27, 41, 43, 45, 45, 21, 70]
135   [21, 41, 45, 57, 70]
136   bot k i j lefthalf righthalf 6 3 3 [14, 27, 43, 46] [21, 41, 45, 57, 70]
137   nlist[k] 46 [14, 21, 27, 41, 43, 45, 46, 21, 70]
138   dot k j righthalf 7 3 [21, 41, 45, 57, 70]
139   nlist[k] 57 [14, 21, 27, 41, 43, 45, 46, 57, 70]
140   dot k j righthalf 8 4 [21, 41, 45, 57, 70]
141   nlist[k] 70 [14, 21, 27, 41, 43, 45, 46, 57, 70]
142   Merging  [14, 21, 27, 41, 43, 45, 46, 57, 70]
143   [14, 21, 27, 41, 43, 45, 46, 57, 70]

假设您面前有两个排序列表。要获得合并列表,您需要在两个列表的头部取最小的两个元素,并重复直到用完两个列表。

[*14, 27, 43, 46]
[ 21, 41, 45, 57, 70]

[ 27, 43, 46]
[*21, 41, 45, 57, 70]

[*27, 43, 46]
[ 41, 45, 57, 70]

[ 43, 46]
[*41, 45, 57, 70]

[*43, 46]
[ 45, 57, 70]

[ 46]
[*45, 57, 70]

[*46]
[ 57, 70]

[]
[*57, 70]

[]
[*70]

[]
[]

尤里卡!在花费了大量时间之后...我找到了它。

当可变对象(在本例中为列表)作为参数传递给函数时 ('righthalf'),并且该参数被递归变异 ('nlist'),该参数也是突变,这种变化反映在函数之外。这表示 python 的“通过对象引用调用”属性。 https://www.geeksforgeeks.org/is-python-call-by-reference-or-call-by-value/

在这种特定情况下

  • 'righthalf' - [43, 27] 作为参数传递给合并排序函数,
  • 递归函数将其接收为 'nlist'
  • 'nlist' 在递归函数中被变异为 [27, 43],
  • 由于两者都指向内存中的相同引用位置,'righthalf' 也发生了变异,不需要传统的赋值
    righthalf = nlist

谢谢大家!