X5-1、java数据结构---插入排序算法【2020-12-8】

总目录:地址如下看总纲

https://www.jianshu.com/p/929ca9e209e8

一、简单插入排序

1、插入排序概要

插入式排序属于内部排序法,是对于欲排序的元素以插入的方式找寻该元素的适当位置,以达到排序的目的。

2、基本思想

把n个待排序的元素看成为一个有序表和一个无序表,开始时有序表中只包含一个元素,无序表中包含有n-1个元素,排序过程中每次从无序表中取出第一个元素,把它的排序码依次与有序表元素的排序码进行比较,将它插入到有序表中的适当位置,使之成为新的有序表。


image.png

3、代码

/**
 * title: 简单插入排序
 * @author 阿K
 * 2020年12月8日 下午10:38:05 
 */
public class InsertSort {

    public static void main(String[] args) {
//      int[] arr = {101, 34, 119, 1, -1, 89}; 
//      insertSort(arr);
//      System.out.println(Arrays.toString(arr));

        // 创建要给80000个的随机的数组
        int[] arr = new int[80000];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = (int) (Math.random() * 8000000);
        }
        new InsertSort(arr);
    }

    //
    public InsertSort(int[] arr) {
        long time = new Date().getTime();
        insertSort(arr);
        long time2 = new Date().getTime();
        System.out.println("使用了:" + (time2 - time) + "毫秒");
    }

    // 直接插入排序 Api
    public static void insertSort(int[] arr) {
        int insertVal = 0;
        int insertIndex = 0;
        for (int i = 1; i < arr.length; i++) {
            // 定义待插入的数
            insertVal = arr[i];
            // 即arr[1]的前面这个数的下标
            insertIndex = i - 1;

            // 给insertVal 寻找到插入的位置
            // 说明
            // 1. insertIndex >= 0 保证在给insertVal 找插入位置,不越界
            // 2. insertVal < arr[insertIndex] 待插入的数,还没有找到插入位置
            // 3. 就需要将 arr[insertIndex] 后移
            while (insertIndex >= 0 && insertVal < arr[insertIndex]) {
                arr[insertIndex + 1] = arr[insertIndex];
                insertIndex--;
            }

            // 当退出while循环时,说明插入的位置找到, insertIndex + 1
            // 判断是否需要赋值
            if (insertIndex + 1 != i) {
                arr[insertIndex + 1] = insertVal;
            }
        }
    }
}

4、八万数据测试

image.png

二、希尔排序(简单插入的增强)

1、基本介绍

希尔排序是希尔(Donald Shell)于1959年提出的一种排序算法。希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序。

2、思想

image.png

image.png

1、希尔排序时, 对有序序列在插入时采用交换法
2、希尔排序时, 对有序序列在插入时采用移动法(交换法的增强)

3、逐轮分析代码

/**
 * title: 希尔排序
 * @author 阿K
 * 2020年12月10日 下午11:01:23 
 */
public class ShellSort {

    public static void main(String[] args) {
        int[] arr = { 8, 9, 1, 7, 2, 3, 5, 4, 6, 0 };
        shellSort(arr);
        System.out.println(Arrays.toString(arr));
    }

    // 希尔排序 api
    public static void shellSort(int[] arr) {

        int temp = 0;// 辅助变量
        int count = 0;

        // 希尔排序的第1轮排序
        // 因为第1轮排序,是将10个数据分成了 5组
        // [3, 5, 1, 6, 0, 8, 9, 4, 7, 2]
        for (int i = 5; i < arr.length; i++) {
            // 遍历各组中所有的元素(共5组,每组有2个元素), 步长5
            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;
                }
            }
        }

        // 希尔排序的第2轮排序
        // 因为第2轮排序,是将10个数据分成了 2组
        // [0, 2, 1, 4, 3, 5, 7, 6, 9, 8]
        for (int i = 2; i < arr.length; i++) {
            // 遍历各组中所有的元素(共5组,每组有2个元素), 步长5
            for (int j = i - 2; j >= 0; j -= 2) {
                // 如果当前元素大于加上步长后的那个元素,说明交换
                if (arr[j] > arr[j + 2]) {
                    temp = arr[j];
                    arr[j] = arr[j + 2];
                    arr[j + 2] = temp;
                }
            }
        }

        // 希尔排序的第3轮排序
        // 因为第3轮排序,是将10个数据分成了 2/2= 1 组
        // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
        for (int i = 1; i < arr.length; i++) {
            // 遍历各组中所有的元素(共5组,每组有2个元素), 步长5
            for (int j = i - 1; j >= 0; j -= 1) {
                // 如果当前元素大于加上步长后的那个元素,说明交换
                if (arr[j] > arr[j + 1]) {
                    temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }
}

4、代码(交换法)

// 希尔排序 api
    public static void shellSort2(int[] arr) {
        int temp = 0;// 辅助变量
        int count = 0;
        
        // 根据前面的逐步分析,使用循环处理
        // gap 控制组数
        for(int gap = arr.length/2;gap>0;gap/=2) {
            for(int i=gap;i<arr.length;i++) {
                // 遍历各组中所有的元素(共gap组,每组有 (arr.length/gap) 个元素), 步长gap
                for(int j=i-gap;j>=0;j-=gap) {
                    // 如果当前元素大于加上步长后的那个元素,说明交换
                    if(arr[j]>arr[j+gap]) {
                        temp = arr[j];
                        arr[j] = arr[j+gap];
                        arr[j+gap] = temp;
                    }
                }
            }
        }
    }

5、代码(移位法)

    // 希尔排序 api 移位法
    public static void shellSort3(int[] arr) {

        // 增量gap, 并逐步的缩小增量
        for (int gap = arr.length / 2; gap > 0; gap /= 2) {
            // 从第gap个元素,逐个对其所在的组进行直接插入排序
            for (int i = gap; i < arr.length; i++) {
                int j = i;// 保存待插入的索引
                int temp = arr[j];// 记录待插入的值
                if (arr[j] < arr[j - gap]) {// 记住 gap是步长值
                    while (j - gap >= 0 && temp < arr[j - gap]) {
                        // 找到了适当位置,插入(移动)
                        arr[j] = arr[j - gap];
                        j -= gap;
                    }
                    // 当退出while后,就给temp找到插入的位置
                    arr[j] = temp;
                }
            }
        }
    }

6、八万数据效率

image.png

7、最终完整代码

package com.kk.datastructure.sort;

import java.util.Arrays;
import java.util.Date;


/**
 * title: 希尔排序
 * @author 阿K
 * 2020年12月10日 下午11:25:31 
 */
public class ShellSort {

    public static void main(String[] args) {
//      int[] arr = { 8, 9, 1, 7, 2, 3, 5, 4, 6, 0 };
//      shellSort3(arr);
//      System.out.println(Arrays.toString(arr));

        // 创建80000个的随机的数组
        int[] arr = new int[80000];
        for (int i = 0; i < 80000; i++) {
            arr[i] = (int) (Math.random() * 8000000); // 生成一个[0, 8000000) 数
        }
        new ShellSort(arr, "2");
        new ShellSort(arr, "3");
    }

    public ShellSort(int[] arr, String zhiling) {
        long time = new Date().getTime();
        if ("2".equals(zhiling)) {
            shellSort2(arr);
            long time2 = new Date().getTime();
            System.out.println("希尔排序(交换法运行):" + (time2 - time) + "毫秒");
        } else {
            shellSort3(arr);
            long time2 = new Date().getTime();
            System.out.println("希尔排序(移位法运行):" + (time2 - time) + "毫秒");
        }

    }

    // 希尔排序 api
    public static void shellSort(int[] arr) {

        int temp = 0;// 辅助变量

        // 希尔排序的第1轮排序
        // 因为第1轮排序,是将10个数据分成了 5组
        // [3, 5, 1, 6, 0, 8, 9, 4, 7, 2]
        for (int i = 5; i < arr.length; i++) {
            // 遍历各组中所有的元素(共5组,每组有2个元素), 步长5
            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;
                }
            }
        }

        // 希尔排序的第2轮排序
        // 因为第2轮排序,是将10个数据分成了 2组
        // [0, 2, 1, 4, 3, 5, 7, 6, 9, 8]
        for (int i = 2; i < arr.length; i++) {
            // 遍历各组中所有的元素(共5组,每组有2个元素), 步长5
            for (int j = i - 2; j >= 0; j -= 2) {
                // 如果当前元素大于加上步长后的那个元素,说明交换
                if (arr[j] > arr[j + 2]) {
                    temp = arr[j];
                    arr[j] = arr[j + 2];
                    arr[j + 2] = temp;
                }
            }
        }

        // 希尔排序的第3轮排序
        // 因为第3轮排序,是将10个数据分成了 2/2= 1 组
        // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
        for (int i = 1; i < arr.length; i++) {
            // 遍历各组中所有的元素(共5组,每组有2个元素), 步长5
            for (int j = i - 1; j >= 0; j -= 1) {
                // 如果当前元素大于加上步长后的那个元素,说明交换
                if (arr[j] > arr[j + 1]) {
                    temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }

    // 希尔排序 api 交换法
    public static void shellSort2(int[] arr) {
        int temp = 0;// 辅助变量

        // 根据前面的逐步分析,使用循环处理
        // gap 控制组数
        for (int gap = arr.length / 2; gap > 0; gap /= 2) {
            for (int i = gap; i < arr.length; i++) {
                // 遍历各组中所有的元素(共gap组,每组有 (arr.length/gap) 个元素), 步长gap
                for (int j = i - gap; j >= 0; j -= gap) {
                    // 如果当前元素大于加上步长后的那个元素,说明交换
                    if (arr[j] > arr[j + gap]) {
                        temp = arr[j];
                        arr[j] = arr[j + gap];
                        arr[j + gap] = temp;
                    }
                }
            }
        }
    }

    // 希尔排序 api 移位法
    public static void shellSort3(int[] arr) {

        // 增量gap, 并逐步的缩小增量
        for (int gap = arr.length / 2; gap > 0; gap /= 2) {
            // 从第gap个元素,逐个对其所在的组进行直接插入排序
            for (int i = gap; i < arr.length; i++) {
                int j = i;// 保存待插入的索引
                int temp = arr[j];// 记录待插入的值
                if (arr[j] < arr[j - gap]) {// 记住 gap是步长值
                    while (j - gap >= 0 && temp < arr[j - gap]) {
                        // 找到了适当位置,插入(移动)
                        arr[j] = arr[j - gap];
                        j -= gap;
                    }
                    // 当退出while后,就给temp找到插入的位置
                    arr[j] = temp;
                }
            }
        }
    }
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容