在CLRS(《算法导论》)一书中,归并排序的归并操作伪代码里,为了备份左右两个已排好序的数组以防止在归并操作中将原始数据覆盖,开辟了两个数组,空间长度为n。

而在邓俊辉《数据结构(C++语言版)》中,归并操作里只开辟了一个临时数组,只用来备份左半部分已排好序的数组,右半边的数组就地进行操作,难道他不担心在归并操作中右半部分的原始数据被赋值给覆盖了么?下面就简单给出一种证明,说明这种担心是多余的。

记左半部分数组(备份后的)为A,右半部分数组为B,设其长度分别为n1n2,(事实上对于归并排序,要么n1== n2要么n1 == n2+1)。

在归并操作中,从将原数组从左至右进行赋值。我们考虑当赋值操作在左半部分刚好完成这个时候,在此之前,右半部分即B数组都未受到影响,此时一共完成了n1个赋值操作。记这n1个数里面,有a个数来自于数组A,有n1-a个数来自于数组B。也就是说,数组A还剩下n1-a个数未归并,而B数组还剩下n2-n1+a个数未归并。

关键就在于,数组A中还有n1-a个未归并,而数组B中已经有n1-a个数已经归并。

那么在接下来的归并操作中,右半部分的数组也会被一一重新赋值。我们考虑右半部分的前n1-a这一段,这一段对于数组B而言已经不重要,因为它已经被归并,被覆盖与否都无所谓了。所以右半部分至少有n1-a个安全的位置,而数组A中还剩下需要归并的数一共也刚好是n1-a个,所以在极端情况下,A中剩下的所有值都被赋值到右半部分,也全部会落入安全位置中,剩下的就是B数组,自己覆盖自己一遍没有任何影响。

所以,在归并操作中,只备份左半部分的数组就能够保证其安全性了。