每日一题(算法:希尔排序 及其优化)

希尔排序思路
标题

希尔排序算法图解

 

package com.athangzhou.springcloud.service.impl;

import com.alibaba.fastjson.JSON;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 希尔排序   8万条数据,希尔算法
 * 位移法 用时1秒 性能高
 * 交换法 用时6秒 性能低
 */
public class ShellSort {


    public static void main(String[] args) {
        int arr[] = {0, 9, 2, 4, 5, 6, 8, 1, 3, 7};

        int[] testArr = new int[80000];
        for (int i = 1; i < 80000; i++) {
            testArr[i] = (int) (Math.random() * 80000);
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String format = simpleDateFormat.format(new Date());
        System.out.println("希尔算法:移位法计算开始时间" + format);

        shellSort(testArr);

        String formatEnd = simpleDateFormat.format(new Date());
        System.out.println("希尔算法:位移法 计算结束时间" + formatEnd);

        System.out.println("");
        System.out.println("");
        System.out.println("");
        System.out.println("");

        String exchangeSortStart = simpleDateFormat.format(new Date());
        System.out.println("希尔算法:交换法计算开始时间" + exchangeSortStart);
        exchangeSort(testArr);
        String exchangeSortEnd = simpleDateFormat.format(new Date());
        System.out.println("希尔算法:交换法计算结束时间" + exchangeSortEnd);

    }

    //希尔排序算法 移位法
    public static void shellSort(int[] arr) {
        int count = 0;
        //分组思想
        for (int group = arr.length / 2; group > 0; group /= 2) {
            //第二步 分为2组  即5/2=2  {0,1,5,9,4},{8,3,6,2,7} 最后结果:{0,2,1,3,4,6,5,7,9,8}
            //从第group个元素依次对其所在的组进行直接插入排序
            for (int i = group; i < arr.length; i++) {
                //要插入数的索引  0
                int j = i;
                //要插入数的值  arr[5]=6
                //{0,9,2,4,5,6,8,1,3,7}
                //{0,6},{9,8},{2,1},{4,3},{5,7}
                //{0,9,2,4,5,6,8,1,3,7}
                int insertValue = arr[j];
                //比较 arr[5]与arr[0]的值  如果小于 则移位插入
                //步长
                if (arr[j] < arr[j - group]) {
                    while (j - group >= 0 && insertValue < arr[j - group]) {
                        arr[j] = arr[j - group];
                        j -= group;
                    }
                }
                //退出while循环说明temp找到了位置
                arr[j] = insertValue;
            }
            //   System.out.println("第" + (++count) + "次插入结果: " + JSON.toJSONString(arr));
        }
        //  System.out.println("JSON.toJSONString(arr) = " + JSON.toJSONString(arr));
    }

    /**
     * 希尔排序交换算法  从小到大排序
     * <p>
     * 如果从大到小排序,>改为<即可
     *
     * @param arr arr
     */
    public static void exchangeSort(int arr[]) {
        int temp = 0;
        int count = 0;
        for (int group = arr.length / 2; group > 0; group /= 2) {
            //因为第一次分为了5组,所以从索引下标=5开始
            for (int i = group; i < arr.length; i++) {
                //只遍历两次  从0开始
                for (int j = i - group; j >= 0; j -= group) {
                    if (arr[j] > arr[j + group]) {
                        temp = arr[j];
                        arr[j] = arr[j + group];
                        arr[j + group] = temp;
                    }
                }
            }
            //    System.out.println("第" + (++count) + "次排序结果:" + JSON.toJSONString(arr));
        }
      /*  int groupTest = arr.length / 2;
        while (groupTest > 0) {
            //因为第一次分为了5组,所以从索引下标=5开始
            for (int i = groupTest; i < arr.length; i++) {
                //只遍历两次  从0开始
                for (int j = i - groupTest; j >= 0; j -= groupTest) {
                    if (arr[j] > arr[j + groupTest]) {
                        temp = arr[j];
                        arr[j] = arr[j + groupTest];
                        arr[j + groupTest] = temp;
                    }
                }
            }
            System.out.println("第" + groupTest + "次排序结果:" + JSON.toJSONString(arr));
            groupTest = groupTest / 2;
        }*/
    }

    /**
     * 希尔排序思路:
     * {0,9,2,4,5,6,8,1,3,7}
     * <p>
     * 第一步: 分为5组 即length/2  10/2=5  {0,6},{9,8},{2,1},{4,3},{5,7}  各自比较大小 小数放前面,大数放后面替换位置
     * 最后结果: {0,8,1,3,5,6,9,2,4,7}
     * <p>
     * 第二步 分为2组  即5/2=2  {0,1,5,9,4},{8,3,6,2,7}
     * 最后结果:{0,2,1,3,4,6,5,7,9,8}
     * <p>
     * 第三步: 分为1组  即2/2    {0,2,1,3,4,6,5,7,9,8}
     * 最后结果:{0,1,2,3,4,5,6,7,8,9}
     */
    public static void test(int arr[]) {


        int temp = 0;
        //因为第一次分为了5组,所以从索引下标=5开始
        for (int i = 5; i < arr.length; i++) {
            //只遍历两次  从0开始
            for (int j = i - 5; j >= 0; j -= 5) {
                if (arr[j] < arr[j + 5]) {
                    temp = arr[j];
                    arr[j] = arr[j + 5];
                    arr[j + 5] = temp;
                }
            }
        }
        System.out.println("第一次排序结果:" + JSON.toJSONString(arr));

        //因为第二次分为了5/2=2组,所以从索引下标=2开始  [0,8,1,3,5,6,9,2,4,7]
        //第二步 分为2组  即5/2=2  {0,1,5,9,4},{8,3,6,2,7}
        // 最后结果:{0,2,1,3,4,6,5,7,9,8}
        for (int i = 2; i < arr.length; i++) {
            //只遍历两次  从0开始
            for (int j = i - 2; j >= 0; j -= 2) {
                if (arr[j + 2] < arr[j]) {
                    temp = arr[j];
                    arr[j] = arr[j + 2];
                    arr[j + 2] = temp;
                }
            }
        }
        System.out.println("第二次排序结果:" + JSON.toJSONString(arr));


        //因为第二次分为了5/2=2组,所以从索引下标=2开始  [0,8,1,3,5,6,9,2,4,7]
        //第二步 分为2组  即5/2=2  {0,1,5,9,4},{8,3,6,2,7}
        // 最后结果:{0,2,1,3,4,6,5,7,9,8}
        for (int i = 1; i < arr.length; i++) {
            //只遍历两次  从0开始
            for (int j = i - 1; j >= 0; j -= 1) {
                if (arr[j + 1] < arr[j]) {
                    temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
        System.out.println("第三次排序结果:" + JSON.toJSONString(arr));
    }


}

打印结果:

希尔算法:移位法计算开始时间2020-04-22 23:56:24
希尔算法:位移法 计算结束时间2020-04-22 23:56:24


希尔算法:交换法计算开始时间2020-04-22 23:56:24
希尔算法:交换法计算结束时间2020-04-22 23:56:30

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章