希尔排序和归并排序

  • 希尔排序
    希尔排序是一种改进的插入排序算法,它的思想是:取一个数作为整个数组的间隔,从第一个数开始按照间隔依次将取出来的新数组进行插入排序,第一个数到第一个间隔间的数都执行该操作。这样就完成了第一次排序,然后将间隔缩小一半,再进行第二次排序,最后按照间隔等于1进行最后一次排序,也就是进行插入排序。
    Knuth序列:(用来确定希尔排序的间隔,最小间隔是1,以后依次按照h * 3 + 1递增)
    h = 1
    h = h * 3 + 1
public class ShellSort {

    public static void main(String[] args){
        int[] arr = {9,6,11,3,5,12,8,7,10,15,14,4,1,13,2};
        sort(arr);
        print(arr);
    }

    private static void print(int[] arr) {
        for (int i = 1; i < arr.length; i++) {
            System.out.print( arr[i] + " ");
        }
    }

    private static void sort(int[] arr) {
        int h = 1;
        while (h <= arr.length/3){
            h = h * 3 + 1;
        }
        for (int gap = h; gap > 0 ; gap = (gap - 1)/3) {
            for (int i = gap;i < arr.length;i++){
                for (int j = i;j > gap - 1;j-=gap){
                    if (arr[j] < arr[j - gap]){
                        swap(arr,j,j - gap);
                    }
                }
            }
        }

    }

    private static void swap(int[] arr,int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}
  • 归并排序
    归并排序是java中默认的对象排序算法,java对象使用的排序算法是Tim Sort,它是归并排序的一种,python对象默认的排序算法也是归并排序。对象排序一般要求稳定,所以归并排序是稳定的。它的时间复杂度是O(n * log₂n),空间复杂度是O(n)

    排序思想:假如一个数组从中间分为两部分,前后两个数组分别都是有序的。那么我们可以创建一个大小等于该数组的新数组,用三个指针 i 指向前面部分数组的开始,j 指向后面部分数组的开始,k 指向新数组的开始。判断arr[i]和arr[j]的大小,将小的一个赋值到新数组newArr[k],同时 i 和 j 中数值小的指针向后移动一位,k也移动一位k++。这样就完成了对一个数组前后分别有序的排序。而没有顺序的数组就是不断将数组分为前后两部分,直到整个数组都变成前后有序的。也就是递归执行上面的排序操作,最后将前后两部分有序数组merge归并完成排序。

public class MergeSort {

    public static void main(String[] args){
        //arr数组已经分为{1,4,7,8}和{3,6,9}两个排好序的数组,进行归并
        int[] arr = {1,4,7,8,3,6,9};
        merge(arr);
        print(arr);


        //数组并不是左边两边已经排好序的就递归调用sort方法,直到左右两边都是有序数组,最后进行merge调用
        int[] arr2 = {2,4,1,6,9,3,8,2,7};
        sort(arr2,0.arr2.length - 1);
        print(arr);
    }

    private static void sort(int[] arr,int left,int right){
        if (left == right) return;
        //将数组分成两半
        int mid = left + (right - left)/2;

        //左边排序
        sort(arr,left,mid);
        //右边排序
        sort(arr,mid + 1,right);

        //merge归并
        merge(arr,left,mid + 1,right);

    }

    private static void merge(int[] arr) {
        //mid取数组中间的数,将数组分为前后两部分
        int mid = arr.length / 2;
        int[] temp = new int[arr.length];

        int i = 0;
        int j = mid + 1;
        int k = 0;

        while (i <= mid && j < arr.length){
            if (arr[i] <= arr[j]){
                temp[k] = arr[i];
                i++;
            }else {
                temp[k] = arr[j];
                j++;
            }
            k++;
        }

        //归并之后如果前半部分的数有剩下的则把剩下的所有数依次添加到数组中
        while (i <= mid){
            temp[k++] = arr[i++];
        }

        //归并之后如果后半部分的数有剩下的则把剩下的所有数依次添加到数组中
        while (j < arr.length){
            temp[k++] = arr[j++];
        }

    }

    //优化的merge方法,可以指定数组的一部分来排序
    // leftPoint:左半部分从哪开始的指针
    // rightPoint:右半部分从哪开始的指针
    // rightBound:右边边界的索引
    private static void merge(int[] arr,int leftPoint,int rightPoint,int rightBound) {
        //mid取数组中间的数,将数组分为前后两部分
        int mid = rightPoint - 1;
        int[] temp = new int[rightBound - leftPoint + 1];

        int i = leftPoint;
        int j = rightPoint;
        int k = 0;

        while (i <= mid && j <= rightBound){
            if (arr[i] <= arr[j]){
                temp[k] = arr[i];
                i++;
            }else {
                temp[k] = arr[j];
                j++;
            }
            k++;
        }

        //归并之后如果前半部分的数有剩下的则把剩下的所有数依次添加到数组中
        while (i <= mid){
            temp[k++] = arr[i++];
        }

        //归并之后如果后半部分的数有剩下的则把剩下的所有数依次添加到数组中
        while (j <= rightBound){
            temp[k++] = arr[j++];
        }

        for (int m = 0; m < temp.length; m++) {
            arr[leftPoint + m] = temp[m];
        }

    }

    private static void print(int[] arr) {
        for (int i = 1; i < arr.length; i++) {
            System.out.print( arr[i] + " ");
        }
    }

}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    蚁前阅读 5,235评论 0 52
  • 1.插入排序—直接插入排序(Straight Insertion Sort) 基本思想: 将一个记录插入到已排序好...
    依依玖玥阅读 1,288评论 0 2
  • 排序算法说明 (1)排序的定义:对一序列对象根据某个关键字进行排序; 输入:n个数:a1,a2,a3,…,an 输...
    code武阅读 683评论 0 0
  • Ba la la la ~ 读者朋友们,你们好啊,又到了冷锋时间,话不多说,发车! 1.冒泡排序(Bub...
    王饱饱阅读 1,819评论 0 7
  • 1 初级排序算法 排序算法关注的主要是重新排列数组元素,其中每个元素都有一个主键。排序算法是将所有元素主键按某种方...
    深度沉迷学习阅读 1,478评论 0 1