java的归并和希尔

201 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

1.希尔排序

希尔排序(Shell's Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。

希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至 1 时,整个文件恰被分成一组,算法便终止。

一般的初次取序列的一半为增量,以后每次减半,直到增量为1。

给定实例的shell排序的排序过程

假设待排序文件有10个记录,其关键字分别是:

49,38,65,97,76,13,27,49,55,04。 增量序列的取值依次为:5,2,1

图片.png

package test1;
import java.util.Arrays;
/**
 * @author 小徐同学
 *
 * 2021年10月30日
 */
public class ShellSort {

	public static void main(String[] args){
	    int[] array={49,38,65,97,76,13,27,49,78,34,12,64,1};
	    System.out.println("排序前"+Arrays.toString(array));
	    //希尔排序
	    int gap = array.length;
	    while (true) {    
	        gap /= 2;   //增量每次减半    
	        for (int i = 0; i < gap; i++) {        
	            for (int j = i + gap; j < array.length; j += gap) {//这个循环里其实就是一个插入排序                       
	                int k = j - gap;            
	                while (k >= 0 && array[k] > array[k+gap]) {
	                    int temp = array[k];
	                    array[k] = array[k+gap];
	                    array[k + gap] = temp;                
	                    k -= gap;            
	                }                
	            }    
	        }    
	        if (gap == 1)        
	            break;
	    }
	 
	    System.out.println();
	    System.out.println("排序后"+Arrays.toString(array));
	}

}

结果

排序前[49, 38, 65, 97, 76, 13, 27, 49, 78, 34, 12, 64, 1] 排序后[1, 12, 13, 27, 34, 38, 49, 49, 64, 65, 76, 78, 97]

2.归并排序

递归式归并排序

归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。 将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并

归并操作(merge),也叫归并算法,指的是将两个已经排序的序列合并成一个序列的操作 如 设有数列{6,202,100,301,38,8,1} 初始状态: [6] [202] [100] [301] [38] [8] [1] 比较次数 i=1 [6 202 ] [ 100 301] [ 8 38] [ 1 ] 3 i=2 [ 6 100 202 301 ] [ 1 8 38 ] 4 i=3 [ 1 6 8 38 100 202 301 ] 4 总计: 11次代码

图片.png

package test1;
import java.util.Arrays;
/**
 * @author 小徐同学
 *
 * 2021年10月30日
 */
public class MergeSort {
	    //测试
	    public static void main(String[] args) {
	        Integer[] I = {5,3,1,4,2,10,6,7};
	        System.out.println("排序前:"+Arrays.toString(I));
	        sort(I);
	        System.out.println("排序后:"+Arrays.toString(I));
	    }

	    //实现归并操作
	    public static void merge(Comparable[] a, int lo, int mid, int hi){
	        //定义三个指针
	        int p1= lo; //p1指向左子组的第一个元素
	        int p2= mid+1;  //p2指向右子组的第一个元素
	        int i = lo;     //i指向辅助数组的第一个元素
	        //定义辅助数组
	        Comparable[] aux = new Comparable[a.length];

	        //实现归并
	        while(p1<=mid || p2<=hi) {
	            if (p1 > mid) aux[i++] = a[p2++];
	            else if (p2 > hi) aux[i++] = a[p1++];
	            else if (a[p1].compareTo(a[p2]) < 0) aux[i++] = a[p1++];
	            else aux[i++] = a[p2++];
	        }
	        //将排序之后的aux数组复制给原来的数组a,这样a中对应的元素便是有序的
	        for (int k = lo; k <= hi; k++) {
	            a[k]=aux[k];
	        }
	    }
	    public static void sort(Comparable[] a){
	        sort(a,0,a.length-1);
	    }
	    public static void sort(Comparable[] a, int lo, int hi){
	        if (hi<=lo) return;
	        //分成两组
	        int mid = lo+(hi-lo)/2;
	        //通过递归进行排序
	        sort(a,lo,mid);
	        sort(a,(mid+1),hi);
	        merge(a,lo,mid,hi);
	    }
	}

结果

排序前:[5, 3, 1, 4, 2, 10, 6, 7] 排序后:[1, 2, 3, 4, 5, 6, 7, 10]