归并排序
代码一
package com.li;
import java.util.ArrayList;
import java.util.Arrays;
public class MergeSort {
public static void main(String[] args) {
int[] array = {4, 2, 8, 9, 5, 7, 6, 1, 3};
//未排序数组顺序为
System.out.println("未排序数组顺序为:");
show(array);
System.out.println("-----------------------");
// array = bubbleSort(array);
// array = insertionSort(array);
array = mergesSort(array);
System.out.println("-----------------------");
System.out.println("经过归并排序后的数组顺序为:");
show(array);
}
public static int[] mergesSort(int[] array) {
if(array.length==1)
return array;
int mid = array.length/2;
//分成左右两边
int left[] = Arrays.copyOfRange(array,0,mid);
int right[] = Arrays.copyOfRange(array,mid,array.length);
//不断分成左右两边
left = mergesSort(left);
right = mergesSort(right);
System.out.println("leftArray:");
show(left);
System.out.println("rightArray:");
show(right);
array = merged(left,right);
return array;
}
//进行数组的合并——>两个有序数组的合并问题
private static int[] merged(int[] left, int[] right) {
int merged[] = new int[left.length+right.length];
int li = 0;
int mi = 0;
int ri = 0;
while(li<left.length && ri<right.length){
if(left[li]<right[ri]){
merged[mi] = left[li];
li++;
mi++;
}else {
merged[mi] = right[ri];
ri++;
mi++;
}
}
while(li<left.length){
merged[mi++] = left[li++];
}
while(ri<right.length) {
merged[mi++] = right[ri++];
}
return merged;
}
private static void show(int[] array) {
for (int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
System.out.println();
}
}
时间复杂度:O(nlogn)
缺点:不是原地排序,空间复杂度:O(n)
代码二
在代码一中,每次都需要开辟数组空间来复制left、right数组,代码二避免这个问题。
package com.li;
import java.util.Arrays;
public class MergeSort2 {
public static void main(String[] args) {
int[] array = {4, 2, 8, 9, 5, 7, 6, 1, 3};
//未排序数组顺序为
System.out.println("未排序数组顺序为:");
show(array);
System.out.println("-----------------------");
array = mergesSort(array,0,array.length-1);
System.out.println("-----------------------");
System.out.println("经过归并排序后的数组顺序为:");
show(array);
}
public static int[] mergesSort(int[] array,int left,int right) {
if(left>=right)
return array;
int mid = (left+right)/2;
//不断分成左右两边
mergesSort(array,left,mid);
mergesSort(array,mid+1,right);
array = merged(array,left,right,mid);
return array;
}
//进行数组的合并——>两个有序数组的合并问题
private static int[] merged(int[] array,int le,int rig,int mid) {
int merged[] = new int[rig-le+1];
int li = le;
int mi = 0;
int ri = mid+1;
while(li<=mid && ri<=rig){
if(array[li]<array[ri]){
merged[mi] = array[li];
li++;
mi++;
}else {
merged[mi] = array[ri];
ri++;
mi++;
}
}
while (li<=mid){
merged[mi++] = array[li++];
}
while (ri<=rig) {
merged[mi++] = array[ri++];
}
int t = 0;
while(le<=rig)
array[le++] = merged[t++];
return array;
}
private static void show(int[] array) {
for (int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
System.out.println();
}
}
代码二与代码一相比,递归函数、合并函数的参数有所变化!!
快速排序
快速排序的递归出口、参数与代码二相似,但两个排序的思想不同。
package com.li;
public class QuickSort {
public static void main(String[] args) {
int[] array = {4, 2, 8, 9, 5, 7, 6, 1, 3};
System.out.println("未排序前数组为:");
show(array);
array = quickSort(array, 0, array.length - 1);
System.out.println("排序后数组为:");
show(array);
}
private static int[] quickSort(int[] array, int l, int r) {
//数组第一个数字为基准
//递归出口
if (l >= r) {
return array;
}
int i = l;
int j = r;
int p =array[l];
while(i<j){
//j从后往前找到第一个小于基准数的数字
while(array[j]>p && i<j)
j--;
if( i<j){
//填坑
array[i] = array[j];
//填坑后,i++,开始找下一个坑
i++;
}
//i从前往后找第一个大于基准数的数字,填入之前的j中
while(i<j && array[i]<p)
i++;
if( i<j){
array[j] = array[i];
j--;
}
}
array[i] =p;
quickSort(array, l, i-1);
quickSort(array, i+1, r);
return array;
}
private static void show(int[] nums){
for (int num : nums) {
System.out.print(num + " ");
}
System.out.println("");
}
}
时间复杂度,同归并排序