归并排序,归并排序的重点在于数组的合并,正确理解其中的每一步对于整体的掌握很有帮助。
代码如下:
package com.vgbh;
/*
* 归并排序
*/
public class MergeSorting {
/*
* 两路归并排序算法思路:
* 1.把 n个记录看成 n个长度为1的有序子表;
* 2.进行两两归并使记录关键字有序,得到 n/2 个长度为 2 的有序子表;
* 3.重复第2步直到所有记录归并成一个长度为 n的有序表为止。
*/
/*
* 归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法。
* 该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
* 算法步骤:
* 1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
* 2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置
* 3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
* 4. 重复步骤3直到某一指针达到序列尾
* 5. 将另一序列剩下的所有元素直接复制到合并序列尾
*/
private static int n = 10 ;//数组长度
private static int[] arr = new int[n] ;//数组
static PublicOut pc = null ;//定义外部对象
public static int count = 0;//运行次数
public static void main(String[] args) {
pc = new PublicOut();
pc.data(arr, n);
System.out.println("排序前:");
pc.prin(arr, n);
MergeSorting ms = new MergeSorting();
ms.merge(arr, n);
System.out.println("排序后:");
pc.prin(arr, n);
System.out.println("最后共运行" + count + "次。");
}
public void merge (int arr[],int n) {
int[] temp = new int[n];
mergeSort(arr,0,n-1,temp);
}
/*
* 归并排序,使用递归
*/
public void mergeSort (int arr[],int first,int last,int temp[]) {
if (first < last) {
int bin = (first + last) / 2;
mergeSort(arr,first,bin,temp);//左边
mergeSort(arr,bin+1,last,temp);//右边
mergeArray(arr,first,bin,last,temp);//数组排序
}
}
/*
* 合并数组
* 首先考虑下如何将将二个有序数列合并。这个非常简单,只要从比较二个数列的第一个数,谁小就先取谁,取了后就在对应数列中删除这个数。
* 然后再进行比较,如果有数列为空,那直接将另一个数列的数据依次取出即可
*/
public void mergeArray (int arr[],int first,int bin,int last,int temp[]) {
int i = first;//第一个数组的开始位
int m = bin;//第一个数组的末尾值
int j = bin + 1;//第二个数组的开始位
int n = last;//第二个数组的末尾值
int k = 0;//替补数组长度值
//System.out.println("开始合并数组: i ,m ,j , n , k " + i + m + j + n + k);
//将数组分割为两部分,两部分进行比较,进行排序,排序后放在替补数组中,最终将排序好的数组返回到原数组。
//再比对过程中,会首先将某个分数组中的值比对完后,在进行全部赋值操作。(注意观察赋值完成后i和j的值)
while (i<=m && j<=n) {
if (arr[i] <= arr[j]) {
//temp[k] = arr[i]; k++; i++;
temp[k++] = arr[i++];
//System.out.println("temp[k] " + temp[k-1] + " k " + (k-1) + " i " + i + "这里是i");
count++;
} else {
//temp[k] = arr[j]; k++; j++;
temp[k++] = arr[j++];
//System.out.println("temp[k] " + temp[k-1] + " k " + (k-1) + " j " + j + "这里是j");
count++;
}
}
while (j <= n) {//补偿未排序进数组的数
//temp[k] = arr[j]; k++; j++;
temp[k++] = arr[j++];
//System.out.println("temp[k]" + temp[k-1] + " k" + (k-1) + " j" + j);
count++;
}
while (i <= m) {//补偿未排序进数组的数
//temp[k] = arr[i]; k++; i++;
temp[k++] = arr[i++];
//System.out.println("temp[k] " + temp[k-1] + " k " + (k-1) + " i " + i);
count++;
}
for (int x=0;x<k;x++) {
arr[first+x] = temp[x];
//System.out.println(temp[x] + " 最后的交换值 temp[x]");
}
}
}
注释的有一部分是简化版的代码,不理解的可以看另外一种。
注释的部分是测试用的代码,如果想要测试的话,看清楚每个部分的运行情况。
有问题的可以联系我的邮箱。