归并排序
归并排序通俗了讲就是两个单独的元素归并为一个序列,二个包含二个元素的序列再合并成含有四个元素的序列。依次2的冥次递增类推...
也有可能是包含奇数个与包含偶数个元素的两个序列进行合并。
代码是利用递归来实现的。
疑问:如何有序的呢?答:通过合并保证最基本的两个元素之间有序,然后再此基础上,保证两个序列合并后有序。
目标数组的有序则通过工作数组有序后进行回写。
代码及执行分析:
public void mergeSort(){
long[] list = new long[length];
recMergeSort(list, 0, length - 1);
}
public void recMergeSort(long[] list, int lowBound, int upperBound){
//假如下边界与上边界一致的话 证明只有一个元素,则不再递归
if(lowBound == upperBound){
return;
}
//计算分割点
int mid = (lowBound + upperBound) / 2;
//递归调用分割点左右两边的序列
recMergeSort(list, lowBound, mid);
recMergeSort(list, mid + 1; upperBound);
//合并,何时会执行?以上两步都执行完时,最基本的就是只有两个元素时
merge(list, lowBound, mid+1, upperBound);
}
/*workspace该排序必须的一个工作数组,每次归并都是临时存放在这里
*lowPtr,左边序列的下标/左边界
*highPtr,右边序列的下标/左边界
*upperBound,右边序列右边界,也是合并后的右边界
*/
private merge(long[] workspace, int lowPtr, int highPtr, int upperBound){
int j = 0;
int lowBound = lowPtr;//左边界初始化为左指针
int mid = highPtr - 1;//左边序列的右边界,而highPtr本身则为右边序列的左边界
int n = upperBound + 1;//合并后的元素个数
//开始合并
while(lowPtr<=mid && highPtr <= upperBound)
if(theArray[lowPtr] < theArray[highPtr])//如果左边序列的元素小于右边序列的元素,则存放较小元素至工作数组
workspace[j++] = theArray[lowPtr++];//同时左边指针右移一位
else
workspace[j++] = theArray[hightPtr++];//这种情况是右边数组指针右移一位
//合并尚未存入工作数组的左边剩余元素
while(lowPtr <= mid)
workspace[j++] = theArray[lowPtr++];
//合并尚未存入工作数组的右边剩余元素
while(highPtr <= upperBound)
workspace[j++] = theArray[highPtr ++];
//变更目标数组theArray至有序
for(j=0; j<n; j++){
theArray[lowBound+j] = workspace[j];
}
}