最近算法课给了一道题:
思路:
对比二路归并算法,这个题的难点在于,根号n每次的子问题个数不定,是上个问题的根号n。但是还是能从二路归并中找到相似的思路。
代码:
package chapter1;
import java.util.Arrays;
public class MergeSort {
static int count = 0;
private static final int MAX_LENGTH = 211;
private static int [] copy = new int[MAX_LENGTH];
private static void createData(int [] a){
for(int i = 0;i< a.length ; i++){
a[i] = (int) (Math.random()*1000);
}
for (int i : a) {
System.out.print(i+" ");
}
System.out.println("\n------------------------------------before sort--------------------------");
}
private static void swap(int [] array,int left,int right){
int temp = array[left];
array[left] = array[right];
array[right] = temp;
}
/**
* 基础排序
* @param array 数组
* */
private static void sort(int [] array,int left,int right){
if(array.length == 2){
if(array[left] > array[right])
swap(array,left,right);
}else{
if(array[left] > array[left+1])
swap(array,left,left+1);
if(array[left] > array[right])
swap(array,left,right);
if(array[left+1] > array[right])
swap(array,left+1,right);
}
System.out.println("in sort:");
for(int i = left; i <= right;i++)
System.out.print(array[i]+" ");
System.out.println();
}
/**
* 算法实现(递归)
* @param Array 待排序的数组
*
* */
private static void mergeSort(int [] array,int left,int right){
if(right == left)
return ;
int len = right - left + 1;
if(len == 2 || len ==3){
sort(array,left,right);
return ;
}
final int SQRT = (int) Math.sqrt(len);//根号n
final int SIZE = (int) (len)/SQRT;//每一个打大小
for(int i=0 ; i < SQRT ;i++ ){
if(i != SQRT - 1)
mergeSort(array, left+i*SIZE, left+i*SIZE+SIZE-1);
else
mergeSort(array, left+i*SIZE,right);//array.length - 1
}
for (int s : array)
System.out.print(s+" ");
System.out.println("\n---------------"+count+++"----------------------");
merge(array, left, right);
}
/**
* 将根号n个数组合并起来,加入一个辅助数组
*
* */
private static void merge(int [] array,int left , int right){
int len = right - left +1;
final int SQRT = (int) Math.sqrt(len);//根号n
final int SIZE = (int) (len)/SQRT;//每一个打大小
int [] [] a = new int[SQRT][];
for(int i=0 ; i < SQRT ;i++ ){
if(i != SQRT - 1)
a[i] = Arrays.copyOfRange(array, left+i*SIZE, left+i*SIZE+SIZE);
else
a[i] = Arrays.copyOfRange(array, left+i*SIZE, right+1);
}
int [] index = new int[SQRT];
for(int j = left;j <= right ;j++){
int min = Integer.MAX_VALUE;
int flag = 0;
for(int i=0 ; i < SQRT ;i++ ){
if(index[i] == a[i].length)
continue;
if(a[i][index[i]] < min){
min = a[i][index[i]];
flag = i;
}
}
index[flag]++;
copy[j] = min;
}
for(int k = left ; k <= right ; k++)
array[k] = copy[k];
}
public static void main(String[] args) {
int[] array = new int[MAX_LENGTH];
createData(array);
mergeSort(array,0,array.length-1);
System.out.println("----------------------after--------------------------");
for (int i : array) {
System.out.print(" "+i);
}
}
}
输出:
ps:(这里我将MAX_LENGTH
改为了17方便显示)
395 449 313 307 486 796 239 820 164 208 860 901 300 728 930 32 881
————————————before sort————————–
in sort:
395 449
in sort:
307 313
395 449 307 313 486 796 239 820 164 208 860 901 300 728 930 32 881
—————0———————-
in sort:
486 796
in sort:
239 820
307 313 395 449 486 796 239 820 164 208 860 901 300 728 930 32 881
—————1———————-
in sort:
164 208
in sort:
860 901
307 313 395 449 239 486 796 820 164 208 860 901 300 728 930 32 881
—————2———————-
in sort:
300 728
in sort:
32 881 930
307 313 395 449 239 486 796 820 164 208 860 901 300 728 32 881 930
—————3———————-
307 313 395 449 239 486 796 820 164 208 860 901 32 300 728 881 930
—————4———————-
———————-after————————–
32 164 208 239 300 307 313 395 449 486 728 796 820 860 881 901 930
结语
没有优化,而且没有仔细去检查,有问题可以评论中指出,谢谢