算法简介:希尔插入排序,是在直接插入排序的基础上进行优化
直接插入排序的优点:对于小数量的数据排序较快
算法描述:将待排序数组在逻辑上分成一定步长的子数组,对这些子数组进行直接插入排序。然后在重新划分子数组,再进行直接插入排序,直到整个数组有序(步长为1)
假设数组长度为N
那么排序的轮数n最佳为满足 2^n < N
每轮排序的步长 step = 2^n -1
为什么这样设置,我也不知道
经过实践
当N很大的时候,希尔插入排序数据比直接插入排序所需时间更多,应该是频繁的方法调用耗费时间,所以时间上并不一定有优势,但是数组需要进行移动的次数少了好几个数量级
上代码
package com.ysb;
import java.util.Random;
/**
* @author Administrator 测试各种排序方法 全部按 升序排列
*/
public class Sort {
// 数组长度
public static final int ARRAYLENGTH = 50000;
public static long moveCount = 0;
public static void main(String[] args) {
int[] randomArray = new int[ARRAYLENGTH];
for (int i = 0; i < ARRAYLENGTH; i++) {
randomArray[i] = new Random().nextInt(ARRAYLENGTH);
}
int[] sortArray = new int[ARRAYLENGTH];
for (int i = 0; i < ARRAYLENGTH; i++) {
sortArray[i] = i;
}
System.out.println("使用插入排序对无序数组进行排序");
long startTime1 = System.currentTimeMillis();
insertSort(randomArray,0,randomArray.length-1,1);
long endTime1 = System.currentTimeMillis();
System.out.println("使用插入排序 排序" + ARRAYLENGTH + "个无序数中使用的时间为"
+ (endTime1 - startTime1) + "ms");
System.out.println("移动次数="+moveCount);
moveCount = 0;
long startTime2 = System.currentTimeMillis();
System.out.println("使用插入排序对有序数组进行排序");
insertSort(sortArray,0,sortArray.length-1,1);
long endTime2 = System.currentTimeMillis();
System.out.println("使用插入排序 排序" + ARRAYLENGTH + "个有序数中使用的时间为"
+ (endTime2 - startTime2) + "ms");
System.out.println("移动次数="+moveCount);
long startTime3 = System.currentTimeMillis();
System.out.println("使用希尔插入排序对无序数组进行排序");
for (int i = 0; i < ARRAYLENGTH; i++) {
randomArray[i] = new Random().nextInt(ARRAYLENGTH);
}
insertShellSort(randomArray);
long endTime3 = System.currentTimeMillis();
System.out.println("使用希尔插入排序 排序" + ARRAYLENGTH + "个无序数中使用的时间为"
+ (endTime3 - startTime3) + "ms");
System.out.println("移动次数="+moveCount);
}
/**
* 插入排序的改进 -希尔排序
*/
private static void insertShellSort(int[] array) {
int temp= 1;
//希尔排序的轮数
int index = 0;
// 希尔排序每轮的步长 9 4 2^3 = 8
int step = 0;
while(true ) {
temp = temp*2;
if(temp > ARRAYLENGTH)
break;
index++;
}
for(int i=index;i>0;i-- ) {
//每轮的步长
step = (int)Math.pow(2,i) - 1;
int startIndex = 0;
int endIndex = 0;
//每个子序列进行插入排序
while(true) {
//所有的子序列都排好了
int flag = 0;
while(true) {
//获取每个子序列的endIndex
endIndex = startIndex+endIndex+step;
if(endIndex >= ARRAYLENGTH) {
endIndex = endIndex-(startIndex+step);
break;
}
flag++;
}
//此序列只有1个元素
if(flag == 0)
endIndex = startIndex;
// System.out.println("第"+(index-i+1)+"轮排序"+"第"+(startIndex+1)+"个子序列,步长为"+step);
insertSort(array,startIndex,endIndex,step);
startIndex++;
endIndex = 0;
if(startIndex == step)
break;
}
}
}
/**
* @param array 排序的数组
* @param from 排序起点
* @param to 排序终点
* @parm step 步长
* 为了希尔排序子序列需要的插入排序,改造此方法
*/
private static void insertSort(int[] array,int from ,int to,int step) {
// System.out.print("排序子序列:");
// for(int i=from;i<=to;i+=step)
// System.out.print(" "+array[i]);
// System.out.println();
// 不包括最后1个,因为数组元素是从0开始的
for (int originalArrayIndex= from+step; originalArrayIndex <= to; originalArrayIndex+=step) {
int waitToSort = array[originalArrayIndex];
for (int sortedArrayIndex = from; sortedArrayIndex < originalArrayIndex; sortedArrayIndex+=step) {
if (waitToSort < array[sortedArrayIndex]) {
moveArray(array,sortedArrayIndex,originalArrayIndex,step-1);
array[sortedArrayIndex] = waitToSort;
break;
}
}
}
//验证一下
// System.out.println("有序数组");
// for(int j=from;j<=to;j+=step) {
// if(j>100)
// break;
//System.out.print(array[j]+" ");
//}
//System.out.println();
}
/**
* 移动数组
* @param array
* @param startIndex
* @param endIndex
*/
private static void moveArray(int[] array, int startIndex, int endIndex,int step) {
for(int i=endIndex;i>startIndex;i=i-1-step) {
array[i] = array[i-1-step];
moveCount ++;
}
}
}
运行测试
数组长度为 10W
使用插入排序对无序数组进行排序
使用插入排序 排序100000个无序数中使用的时间为43437ms
移动次数=2501035799
使用插入排序对有序数组进行排序
使用插入排序 排序100000个有序数中使用的时间为33453ms
移动次数=0
使用希尔插入排序对无序数组进行排序
使用希尔插入排序 排序100000个无序数中使用的时间为51078ms
移动次数=2652651
数组长度为1W
使用插入排序对无序数组进行排序
使用插入排序 排序10000个无序数中使用的时间为390ms
移动次数=24875947
使用插入排序对有序数组进行排序
使用插入排序 排序10000个有序数中使用的时间为344ms
移动次数=0
使用希尔插入排序对无序数组进行排序
使用希尔插入排序 排序10000个无序数中使用的时间为360ms
移动次数=145196
分享到:
相关推荐
实现以下常用的内部排序算法并进行性能比较:"直接插入排序"," 折半插入排序"," 2—路插入排序"," 表插入排序"," 希尔排序"," 起泡排序"," 快速排序"," 简单选择排序"," 树形选择排序"," 堆排序"," 归并排序"," 链式...
binary sort,二分法查找,binary search, 二分法排序,merge sort 混合排序,shell sort 希尔排序,insertion sort 插入排序。数据结构 data structure
- 在实际编程中,插入排序也常用于其他算法的组成部分,比如希尔排序中的增量序列排序阶段。 6. **代码测试**: - `main`函数中,创建了一个包含10个元素的数组`nData`,并调用`InsertionSort`对其进行排序,最后...
希尔排序的时间复杂度一般认为是O(n^1.3),优于简单的插入排序的O(n^2),但比其他高级排序算法如快速排序或归并排序的时间复杂度要高。不过,希尔排序在处理部分有序的数组时表现良好,因此在某些特定场景下仍然是一...
希尔排序是一种基于插入排序的算法,由Donald Shell于1959年提出。它的核心思想是将待排序的数据按照一定的间隔(称为增量)分组,对每组进行插入排序,然后逐渐减小增量,直至增量为1,最终完成整个序列的排序。...
Java代码-排序-直接插入排序、希尔排序、直接选择排序、冒泡排序、堆排序、快速排序、归并排序中部分排序以及算法-贪心法,大家可以将源码下载下来进行学习,附带着注释和解释,有不理解的可以找博主一起探讨,共同...
希尔排序的时间复杂度为 O(n^2),但实际上它的性能比插入排序要好得多,特别是在大型列表上。希尔排序的性能取决于间隔序列的选择,但是目前还没有一种最优的间隔序列。 在 Java 中,希尔排序可以使用以下代码实现...
### 希尔排序法(希尔插入排序,希尔交换排序) #### 一、希尔排序法简介 希尔排序法是计算机科学领域中一种重要的排序算法,它由美国计算机科学家Donald Shell于1959年提出,因此得名希尔排序。希尔排序是一种...
(1) 完成5种常用内部排序算法的演示,5种排序算法为:快速排序,直接插入排序,选择排序,堆排序,希尔排序; (2) 待排序元素为整数,排序序列存储在数据文件中,要求排序元素不少于30个; (3) 演示程序开始,...
根据提供的文件信息,我们可以深入探讨几种经典的排序算法:冒泡排序、直接插入排序、快速排序以及希尔排序。这些算法在数据结构与算法课程中是非常重要的基础内容,它们各自有着独特的特性和应用场景。 ### 1. ...
希尔排序的时间复杂度与所选的增量序列有关,最坏情况下可达到O(n^2),但通常情况下其平均时间复杂度为O(n^(3/2)),比原始的插入排序有了显著的提升。由于其不稳定性(即相等元素可能会改变相对顺序),希尔排序在...
4. 希尔排序(Shell Sort):希尔排序是插入排序的一种优化版本,通过间隔序列(也称为增量序列)减少元素间的比较距离,从而提高效率。其平均时间复杂度介于O(n)到O(n^2)之间。 5. 快速排序(Quick Sort):快速...
同时,插入排序也可以用于构建更复杂的排序算法,如希尔排序。 **源码和工具**: 标签中的"源码"指的是上述给出的`InsertionSort.java`文件,这个文件包含了插入排序的Java实现。"工具"可能是指开发环境中使用的...
虽然希尔排序的平均时间复杂度低于插入排序的O(n^2),但具体的时间复杂度依赖于间隔序列的选择,通常介于O(n)和O(n^2)之间。 【冒泡排序】冒泡排序是最基础的排序算法之一,通过不断地交换相邻的逆序元素来逐步使...
下面将详细讲解这7种排序算法:快速排序、归并排序、插入排序、选择排序、冒泡排序、堆排序以及希尔排序。 1. **快速排序**:由C.A.R. Hoare提出的,采用分治策略。基本思想是选取一个基准元素,通过一趟排序将待...
在给定的标题和描述中,我们关注四种经典的排序算法:快速排序、希尔排序、插入排序和折半排序。这些算法各有特点,适用于不同的场景,下面将详细介绍它们的工作原理、性能以及应用场景。 1. **快速排序(Quick ...
希尔排序的时间复杂度在最坏情况下为O(n^2),但在实际应用中通常比插入排序更快。 4. **快速排序(Quick Sort)**: 快速排序是由C.A.R. Hoare提出的,是目前最常用的排序算法之一。它采用分治策略,选取一个基准...
希尔排序是一种基于插入排序的快速排序方法,由美国计算机科学家Donald Shell在1959年提出。它通过将数组中的元素按照一定的间隔分组进行排序,然后逐渐减小间隔,使得整个序列逐步接近有序状态,最终实现整个序列的...
### 直接插入排序与希尔排序的比较 #### 一、概述 本篇文章将通过一组具体的数据集(8个整数)对直接插入排序(Direct Insertion Sort)和希尔排序(Shell Sort)这两种排序方法进行深入分析和比较。这两种排序...