1、基本思想:
另外,对代码进行仔细研究,发现merge函数中有if (a[i] < a[j]) 的语句,说明它需要两两比较,不存在跳跃,因此归并排序是一种稳定的排序算法。
归并排序就是利用归并的思想实现的排序方法。而且充分利用了完全二叉树的深度是log2n+1描述的特性,因此效率比较高。其基本原理如下:对于给定的一组记录,利用递归与分治技术将数据序列划分成为越来越小的半子表,在对半子表排序,最后再用递归方法将排好序的半子表合并成为越来越大的有序序列。
2、复杂度分析
一趟归并需要将数组 a[]中相邻的长度为h的有序序列进行两两归并.并将结果放到temp[]中,这需要将待排序列中的所有记录扫描一遍,因此耗费O(n),而又完全二叉树的深度可知,整个归并排序需要进行(log2n)次,因此总的时间复杂度为O(nlogn),而且这是归并排序算法中最好、最坏、平均的时间性能。
由于归并排序在归并过程中需要与原始序列同样数量的存储空间存放归并结果以及递归时深度为log2n的栈空间,因此空间复杂度为O(n+logn).另外,对代码进行仔细研究,发现merge函数中有if (a[i] < a[j]) 的语句,说明它需要两两比较,不存在跳跃,因此归并排序是一种稳定的排序算法。
也就是说,归并排序是一种比较占内存,但却效率高且稳定的算法。
3、工作原理:
(1)申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
(2)设定两个指针,最初位置分别为两个已经排序序列的起始位置
(3)比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
(4)重复步骤3直到某一指针达到序列尾
(5)将另一序列剩下的所有元素直接复制到合并序列尾。
4、归并排序过程如下:
5、归并排序的Java实现
import java.util.Arrays;
public class MergeSort {
//merge()将两个已排序的子表合并成一个有序表的方法
public void merge(int[] a, int low, int mid, int high){
//定义一个临时数组,用来临时保存已经排好序的元素
int[] tmp = new int[high - low + 1];
int i = low;//i指向第一个子表的下标
int j = mid + 1;//j指向第二个子表的下标
int k = 0;//k为用来暂存结果的tmp数组的下标
while(i <= mid && j <= high){
if(a[i] < a[j])
tmp[k++] = a[i++];
else
tmp[k++] = a[j++];
}
//左边的第一个子表还有剩余元素,将其直接复制到tmp中
while(i <= mid)
tmp[k++] = a[i++];
//右边的第二个子表还有剩余元素,将其直接复制到tmp中
while(j <= high)
tmp[k++] = a[j++];
//将tmp中的元素赋值回a
for (k = 0, i = low; i <= high; k++,i++)
a[i] = tmp[k];
}
//mergeSort()方法,先递归合并排序左子表,然后递归合并排序右子表,最后调用merge()方法将两边的有序的子表合并成一个有序表
public void mergeSort(int[] a, int low, int high){
if( low < high){
int mid = (low + high) / 2;
//递归合并排序左子表
mergeSort(a, low, mid);
//递归合并排序右子表
mergeSort(a, mid + 1, high);
//调用merge()方法将两边的有序的子表合并成一个有序表
merge(a,low, mid, high);
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] a = {6,8,7,9,0,1,3,2,4,5};
MergeSort mg = new MergeSort();
mg.mergeSort(a,0,a.length-1);
System.out.println(Arrays.toString(a));
}
}