归并排序
一、归:递归
将数组分成二组A、B,然后再以A、B各自再分成二组,依次类推,直到小组只有一个数据,这时我们可以认为这个小组组内已经达到了有序。
二、并:合并算法
//将有序数组a[]和b[]合并到c[]中
void MemeryArray(int a[], int n, int b[], int m, int c[])
{
int i, j, k;
i = j = k = 0;
while (i < n && j < m) // 取大值放入c[],直到有一个数组全部取完。
{
if (a[i] < b[j])
c[k++] = a[i++];
else
c[k++] = b[j++];
}
// 将没有取完的数组内元素直接加入c[]中
while (i < n)
c[k++] = a[i++];
while (j < m)
c[k++] = b[j++];
}
}
三、时间复杂度
设数列长为N,将数列分开成小数列一共要logN步,合并有序数列的过程为O(N),故一共为O(N*logN)。
DEMO
public class MergeSort {
private static int[] array;
public static void main(String[] args) {
input();
sort(array, 0, array.length-1);
output();
}
public static void sort(int array[], int left, int right){
int mid = (right+left)/2; // 2/3=0
if(left<right){ //当只有一个元素时停止划分
sort(array, left, mid); // 递归划分左区间
sort(array, mid+1, right); // 递归划分右区间
merge(array,left, mid, right); // 合并
}
}
public static void merge(int[] array, int left, int mid ,int right){ // 相当于left~mid区间与mid+1~right区间的合并
int i = left; // 左区间初始下标
int j = mid +1; // 右区间初始下标
int k=0;
int[] temp = new int[right-left+1]; // 定义临时数组,用于存放已经排序好的中间序列。
while(i<=mid && j<=right){ // 取大值放入temp[],直到有一个区间全部取完。
if(array[i]<array[j]){
temp[k++] = array[i++];
}else{
temp[k++] = array[j++];
}
}
// 将没有取完的数组内元素直接加入temp[]中
while(i<=mid){
temp[k++] = array[i++];
}
while(j<=right){
temp[k++] = array[j++];
}
// 将排序好的temp[]放入array[]中的对应位置
for(int l=0;l<temp.length;l++){
array[l+left] = temp[l];
}
}
static void input(){
System.out.println("请输入一个数组,数字之间以英文逗号分隔:");
Scanner scanner = new Scanner(System.in);
String string = scanner.next().toString(); //读取输入,直到遇到空格或换行,并转化为字符串。
String arrayString[] = string.split(","); // 分割为字符串数组
array = new int[arrayString.length]; // 定义数组长度
for(int i=0;i<array.length;i++){
array[i] = Integer.parseInt(arrayString[i]); // 整型化
}
}
static void output() {
System.out.println("经过归并排序后,结果如下:");
for(int i=0;i<array.length;i++)
System.out.print(array[i] + " ");
}
}