归并排序
归并排序和基于交换,选择等排序的思想不一样,“归并”的含义是将两个或两个以上的有序表组合成一个新的有序表。假定待排序表含有n个记录,则可以看成是n个有序的子表,每个子表长度为1,然后两两归并,得到⌈n/2⌉个长度为2或1的有序表:再两两归并,……如此重复,直到合成一个长度为n的有序表为止,这种排序方法称为2-路归并排序。下图是一个归并排序的例子:
子表合并
设两段有序表A[low…mid],A[mid+1…high]存放在同一顺序表中相邻的位置上,每次从这两个表中取出最小的元素放到临时数组中去,直到两个表中的元素被全部取完。这样临时数组中存储着A[low…high]的所有元素且有序,然后将临时数组的元素copy回原素组A[low…high],这样就完成了子表合并的问题。
public static void merge(int[] arr, int low, int mid, int high){ int[] tmp = new int[high-low+1]; //分配一个临时数组 int k,i,j; for(i=low,j=mid+1,k=0; i<=mid&&j<=high; k++){ if(arr[i]<=arr[j]) //比较arr中的左右两子表的元素 tmp[k] = arr[i++]; //将较小值复制到临时数组中 else tmp[k] = arr[j++]; } //将有剩余元素的那个子表复制到tmp中 while(i<=mid) tmp[k++] = arr[i++]; while(j<=high) tmp[k++] = arr[j++]; //tmp数组的元素已有序,将其复制回原数组对应的位置 System.arraycopy(tmp, 0, arr, low, tmp.length); }
排序代码
public static void mergeSort(int[] arr, int low, int high){ if(low < high){ int mid = (low + high)/2; mergeSort(arr, low, mid); mergeSort(arr, mid+1, high); merge(arr, low, mid, high); } }