下面是一个方法的代码,该方法可以将两个排序数组合并为第三个数组。该方法假设数组1和数组2已按升序排序,并且数组目标的大小等于两个源数组的组合长度。
Public static void merge(int[] 1, int[] 2, int[] destination) {int I = 0, j = 0, k = 0;//当两个原始数组中仍然有数字需要处理时…当(i < 1)Length && j < two.length){//…将1 [i], 2 [j] //处较小的数字移到合并后的[k]…如果(one[i] <= two[j]) {destination[k] = one[i];k + +;我+ +;} else {destination[k] = 2 [j];k + +;+ +;}} //…然后把剩下的数字移过来。While (i < one.length) {destination[k] = one[i];k + +;我+ +;} while (j < two.length) {destination[k] = two[j];k + +;+ +;}}
该方法通过使用一组三个索引i、j和k来工作。索引i跟踪我们通过第一个源数组的进度,而j跟踪我们通过第二个源数组的进度。索引k跟踪我们在目标数组中的进度。在主循环的每一轮中,该方法选择位于1 [i]或2 [j]的两个数字中较小的一个移动到目标数组。复制完数字后,我们增加索引k以移动到目标数组中的下一个位置,并增加复制数字的数组的索引。
通常,当主循环结束时,两个源数组中的一个仍将保留数字。主循环之后的两个较小循环检查是否还有数字需要从两个源数组复制过来。
也许归并方法最有用的赢博体育是称为归并排序的排序算法。该算法将一个数组分成两部分,对这两部分进行排序,然后再将它们合并在一起,形成一个完整的排序列表。
public static void mergeSort(int[] list){如果(list。长度< 20){selectionSort(list);} else{//复制列表的前半部分到一个新的数组int firstLength = list。长度/ 2;int[] one = new int[firstLength];For (int n = 0;n < firstLength;N ++) {one[N] = list[N];} //复制列表的后半部分到另一个数组int secondLength = list。length - firstLength;int[] 2 = new int[secondLength];for (int n = firstLength;N < list.length;n++) {two[n - firstLength] = list[n];} //对两个较小的数组进行排序mergeSort(1);归并排序(两个);//将排序后的数组合并回原始数组Merge (one, two, list);}}
mergeSort是递归算法的一个例子。它调用自己来帮助对从原始数组复制的两个较小数组进行排序。在Java中,方法调用自己是合法的——唯一需要注意的是,当方法一次又一次地调用自己时,可能会出现无限回归。这里避免这个问题的原因是,mergeSort创建的两个数组比原来的数组小。数组可以细分的次数是有限制的:事实上,当mergeSort生成一个小于20的较小数组时,它将切换到通过selectionSort对小数组进行排序,因为对于这种大小的数组,selectionSort相对有效。最终切换到selectionSort结束了mergeSort调用自身的过程,并防止了无限的回归。
在周一的课上,我展示了两种从数字列表中找到最常见数字的方法。第二种方法是对列表进行排序,然后使用一个简单的算法在排序后的数组中找到最长的连续数字。在周一的例子中,我使用了选择排序对数字进行排序。这并不理想,因为对于长度为N的列表,选择排序的运行时间与N2成正比,归并排序是一种更有效的排序算法,其运行时间与N log N成正比,因此切换到归并排序,然后搜索运行会产生更快的结果。
还有比归并排序更好的排序算法。在java.util.Arrays类中提供了一种这样的排序算法。这个方法Arrays.sort()甚至比归并排序更快,而且也不需要临时数组来完成它的工作。这使得算法的时间和空间效率更高。
上面显示的合并方法本身就很有用。使该方法更有趣的是,它可以作为其他重要算法的基础,也可以修改以解决更广泛的问题。
下面是一个可以通过合并过程的修改版本来解决的程序示例。我们试图编写一个程序,它可以计算存储在文件one.txt和two.txt中的两个整数列表的交集。下面的程序将这两个列表读入数组,对它们进行排序,然后使用合并算法的修改版本来构造这两个列表的交集。
公共类intersectionbymerge{公共静态int[] computeintersectionbymerge (int[] one,int[] two) {int[] temp = new int[one.length];//交点将不大于int n = 0;//其中temp中的下一个数变为int i = 0, j = 0;//当(i < 1)时遍历1和2的索引。& & j长度< two.length){如果(一个[我]= =两个[j]){临时[n] =[我];n + +;我+ +;+ +;} else if(one[i] < two[j]) i++;其他j + +;} //创建一个大小合适的新数组…Int result[] = new Int [n];/ /……把数字复制到上面。For (i = 0;i < n;i++) result[i] = temp[i];返回结果;}公共静态void main(String[] args) {int[] A = readNumbers("one.txt");int[] B = readNumbers("two.txt");Arrays.sort(一个);Arrays.sort (B);int[] C = computeintersectionbymerge (A,B);for(int n = 0;n < C;n++) System.out.println(C[n]);}}