【算法拾遗(java描述)】--- 插入排序(直接插入排序、希尔排序)

插入排序基本思想

每次将一个待排序的记录按其关键字大小插入到前面已经拍好序的子文件的适当位置,直到全部记录插入完成为止。

直接插入排序

基本思想

直接插入排序的基本操作是将一个记录插入到已排好序的有序表中,从而得到一个新的有序表。即假设待排序的记录存放在数组R[1······n]中,排序过程中,R被分成两个子区间R[1······i]和R[i+1······n],其中,R[1······i]是已经排好序的有序区;R[i+1······n]是当前未排序的部分。将当前无序区的第一个记录R[i+1]插入到有序区R[1······i]的适当位置,使R[1······i+1]变为新的有序区,每次插入一个数据,直到所有的数据有序为止。

java程序

/*************************
*
* 直接插入排序
*
*************************/
public class InsertSort {

private void insertSort(int[] datas) {
    if (datas == null || datas.length < 2)
        return;
    int i, j, insertData;
    for (i = 1; i < datas.length; i++) {
        insertData = datas[i];// 要插入的变量
        for (j = i - 1; j >= 0 && insertData < datas[j]; j--)
            datas[j + 1] = datas[j];
        datas[j + 1] = insertData;// 将要插入的数据放置到正确的位置
    }
}

public static void main(String[] args) {
    int[] datas = new int[] { 6, 5, 3, 1, 8, 7, 2, 4 };
    System.out.println("********排序前********");
    for (int i = 0; i < datas.length; i++) {
        System.out.print(datas[i] + ",");
    }
    InsertSort insertSort = new InsertSort();
    insertSort.insertSort(datas);
    System.out.println("\n********排序后********");
    for (int i = 0; i < datas.length; i++) {
        System.out.print(datas[i] + ",");
    }
}

}

性能分析

  1. 时间复杂度

  1. 直接插入排序属于就地排序,是一种稳定的排序方法。

希尔排序

基本思想

先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组,所有距离为d1的倍数的记录放在同一个组中,在各组内进行插入排序;然后,取第二个增量d2 < d1,重复上述的分组和排序,直至所取得增量dt = 1(dt < dt-1 < ······ < d2 < d1),即所有记录放在同一个组中进行直接插入排序为止。

java程序

/*************************
*
* 希尔排序
*
*************************/
public class ShellSort {

private void shellSort(int[] datas) {
    if (datas == null || datas.length < 2)
        return;
    int temp;// 暂存变量
    int dataLength;// 步长
    int pointer;// 进行处理的位置
    dataLength = datas.length / 2;// 初始化步长
    while (dataLength != 0) {
        for (int j = dataLength; j < datas.length; j++) {
            temp = datas[j];
            pointer = j - dataLength;
            while (pointer >= 0 && temp < datas[pointer]) {
                datas[pointer + dataLength] = datas[pointer];
                pointer = pointer - dataLength;
            }
            datas[pointer + dataLength] = temp;
        }
        dataLength = dataLength / 2;
    }
}

public static void main(String[] args) {
    int[] datas = new int[] { 6, 5, 3, 1, 8, 7, 2, 4 };
    System.out.println("********排序前********");
    for (int i = 0; i < datas.length; i++) {
        System.out.print(datas[i] + ",");
    }
    ShellSort shellSort = new ShellSort();
    shellSort.shellSort(datas);
    System.out.println("\n********排序后********");
    for (int i = 0; i < datas.length; i++) {
        System.out.print(datas[i] + ",");
    }
}

}

性能分析

希尔排序的执行时间依赖于增量序列(步长)的选取。好的增量序列有如下特点:

  1. 最后一个增量必须为1
  2. 应该尽量避免序列中的值(尤其是相邻的值)互为倍数的情况。

希尔排序的时间性能要由于直接插入排序,原因如下:

  • 当文件初态基本有序时直接插入排序所需的比较和移动次数均较少。
  • 在希尔排序开始时增量较大,分组较多,每组的记录数目少,故各组内直接插入较快,后来增量di逐渐缩小,分组数逐渐减少,而各组的记录数目逐渐增多,但由于已经按di-1作为距离排过序,使文件较接近于有序状态,所以新的一趟排序过程也较快。因此,希尔排序在效率上较直接插入排序有较大的改进。

希尔排序是一种不稳定的排序方法

参考资料:《数据结构与算法分析——java语言描述》、《大话数据结构》

时间: 2025-01-06 00:35:16

【算法拾遗(java描述)】--- 插入排序(直接插入排序、希尔排序)的相关文章

JavaScript 数据结构与算法之美 - 归并排序、快速排序、希尔排序、堆排序

1. 前言 算法为王. 想学好前端,先练好内功,只有内功深厚者,前端之路才会走得更远. 笔者写的 JavaScript 数据结构与算法之美 系列用的语言是 JavaScript ,旨在入门数据结构与算法和方便以后复习. 之所以把归并排序.快速排序.希尔排序.堆排序放在一起比较,是因为它们的平均时间复杂度都为 O(nlogn). 请大家带着问题:快排和归并用的都是分治思想,递推公式和递归代码也非常相似,那它们的区别在哪里呢 ? 来阅读下文. 2. 归并排序(Merge Sort) 思想 排序一个数

排序系列 之 希尔排序算法 —— Java实现

基本思想: 希尔排序的实质就是分组插入排序,又称缩小增量法. 将整个无序序列分割成若干个子序列(由相隔某个"增量"的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序时,再对全体元素进行一次直接插入排序. 因为直接插入排序在元素基本有序的情况下,效率是很高的,因此希尔排序在时间效率上有很大提高. 实例: 无序序列:int a[] = {3,1,5,7,2,4,9,6}; 第一趟时: n=8; gap=n/2=4; 把整个序列共分成了4个子序列{3,

希尔排序(插入排序)-八大排序三大查找汇总(5)

基本思想 该方法的基本思想是:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序. 稳定性 由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱,所以shell排序是不稳定的. 时间复杂度 希尔排序的时间复杂度取决于步长的选择. 平均情况下,

从直接插入排序到希尔排序

目录 从直接插入排序到希尔排序 希尔算法的流程 希尔算法的性能分析 Code 应试知识点 从直接插入排序到希尔排序 直接插入排序,它的原理就是把前i个长度的序列变成有序序列,然后循环迭代,直至整个序列都变为有序的.但是说来说去它还是一个时间复杂度为(n^2)的算法,难道就不能再进一步把时间复杂度降低一阶么? 希尔排序是希尔(Donald Shell)于1959年提出的一种排序算法.希尔排序也是一种插入排序,它是直接插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序,同时该算法是冲破O(n

php实现的冒泡,插入排序,希尔排序,归并排序

<?php/***选择排序也就是冒泡排序,就是基于各个数据之间的对比来排序**/$arr = array(2,1,7,5,8,9,3,4,10,30,28,24);function bubbleSort($arr) {    $len = count($arr);    $k = 0;    for($i=0;$i<$len;$i++){    $k++;        for($j=$i+1;$j<$len;$j++) {            if($arr[$i] > $ar

算法学习之排序算法(四)(希尔排序)

1.算法思想 先将整个待排元素序列分割成若干个子序列(由相隔某个"增量"的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序.因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率上比前两种方法有较大提高. 希尔(Shell)排序又称为缩小增量排序,它是一种插入排序.它是直接插入排序算法的一种威力加强版. 希尔排序的基本思想是 把记录按步长 gap 分组,对每组

数据结构和算法之排序六:希尔排序

经过前面五篇排序方法的介绍,我们了解到了递归思想以及分而治之的归并和快速排序,当然也涉及到了比较简单易懂的数据值传递冒泡,选择,以及插入排序.可以说每一种排序方式都各有千秋,都适合在不同的环境下进行使用,但是我们有时会不会思考一个问题,那就是我们在学习插入排序的时候的主题思想是将每一个数据取出来,然后和后边的前边的数据逐一进行比较,那么,我们是不是要进行N-1次的循环,或者说我们是不是要进行大约N的平方次比较,我们知道,在进行值的交换和比较是非常消耗时间的,那么是不是违背了我们算法的发展.有没有

死磕算法之希尔排序

学习更多算法系列请参考文章:死磕算法之汇总篇 今天讲一下希尔排序,希尔排序呢,其实可以理解为插入算法排序的一个升级版了,不了解插入排序的小伙伴可以先看一下这篇文章:死磕算法之插入排序 我们知道,插入排序在进行排序时如果当数据量很大的时候,有一个很小的数据出现在了数组的最后,那么我们就要移动了这个数据前面所有的元素给它放置到合适的元素.例如: 我们要排序的数组为[1,2,3,4,5,6,7,...此处省略一百万...,0].详细大家肯定不喜欢这个0往前移动一百万此吧. 希尔排序的出现其实就是为了解

树结构的自定义及基本算法(Java数据结构学习笔记)

数据结构可以归类两大类型:线性结构与非线性结构,本文的内容关于非线性结构:树的基本定义及相关算法.关于树的一些基本概念定义可参考:维基百科 树的ADT模型: 根据树的定义,每个节点的后代均构成一棵树树,称为子树.因此从数据类型来讲,树.子树.树节点是等同地位,可将其看作为一个节点,用通类:Tree表示.如下图所示: 图:Tree ADT模型示意图 可采用"父亲-儿子-兄弟"模型来表示树的ADT.如图所示,除数据项外,分别用三个引用表示指向该节点的父亲,儿子,兄弟. 图:"父亲