【希尔排序】
希尔排序,有两种形式。交换式,移位式。交换式类似希尔+冒泡,移位式类似希尔+插入。其中移位式的排序速度远快于交换式(上图演示的是交换式)
算法分析:
第一次排序分的组数为 数据总量的0.5倍(取整),之后每一轮排序的组数都是上一次组数的0.5倍(取整),直到分到0组停止,如 10位的数据,遵循 5 -> 2 ->1 的分组形式。计组数为group。
分组完成后再进入从 group~length-1 循环每组中的数据,进行判定。接下来就不同了,且听我慢慢道来
交换式:进入循环,该循环从i-group开始,每轮循环i都从group增长到data.length-1,使用这里用i-group可以将j值从0~group-1都遍历一次,同时循环以group为周期,这样每组中元素都可以被比较到,当发现后面的数据小于前面的数据时,进行交换位置
移位式:这里类似插入排序,每一组都要进行小范围的,相邻间隔为group的插入排序,先保存待排序数据的索引与数据本身,当发现存在逆序时,进入while循环进行移位操作
交换式代码实现:
package cn.dataStructureAndAlgorithm.demo.sort;
import java.util.Arrays;
public class 希尔排序_shellSort_交换法 {
public static void main(String[] args) {
int data[]=new int[]{5,9,2,3,6,4,7};
shellSort(data);
System.out.println(Arrays.toString(data));
}
public static void shellSort(int data[]){
int temp=0;
int count=0;
for (int group=data.length/2;group > 0;group/=2){//每一轮组数为上一轮组数/2求整,10->5->2->1,当小于0后停止排序
for (int i=group;i<data.length;i++){//分成group组,每组都要进行交换判定
//每一轮循环i都从group增长到data.length-1,使用这里用i-group可以将j值从0~group-1都遍历一次,同时循环以group为周期,这样每组中元素都可以被比较到
for (int j=i-group;j>=0;j-=group){
//对每组中的元素进行相邻大小比较,逆序就交换位置,类似冒泡排序
if (data[j]>data[j+group]){
temp=data[j];
data[j]=data[j+group];
data[j+group]=temp;
}
}
}
}
}
}
移位式代码实现:
package cn.dataStructureAndAlgorithm.demo.sort;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
public class 希尔排序_shellSort_移位法 {
public static void main(String[] args) {
// int data[]=new int[]{2,3,4,5,6,1};
// shellSort(data);
// System.out.println(Arrays.toString(data));
int data[]=new int[8000000];
for (int i=0;i<8000000;i++){
data[i]=(int)(Math.random()*8000000);
}
Date date1=new Date();
SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd:HH-mm-ss SSS");
System.out.println(dateFormat.format(date1));
shellSort(data);
Date date2=new Date();
System.out.println(dateFormat.format(date2));
}
public static void shellSort(int data[]){
int j;
int temp;
for (int group=data.length/2;group>0;group/=2){//每一轮组数为上一轮组数/2求整,10->5->2->1,当小于0后停止排序
for (int i=group;i<data.length;i++){//分成group组,每组都要进行移位判定
//类似于插入排序,不过相邻间隔不是1,而是group
j=i;
temp=data[j];
while (j-group>=0 && temp<data[j-group]){//满足下标不越界,当前数据<前一个数据,寻找合适位置
data[j]=data[j-group];//覆盖式的向后移位
j-=group;//继续搜寻更前的数据
}
//跳出循环,表示找到合适位置
data[j]=temp;//将数据插入正确位置
//System.out.println(Arrays.toString(data));
}
}
}
}
希尔排序是升级版的插入排序,希尔排序通过将比较的全部元素分为几个区域来提升插入排序的性能。分割待排序记录的目的是减少待排序记录的个数,并使整个序列向基本有序发展。
这样可以让一个元素可以一次性地朝最终位置前进一大步。然后算法再取越来越小的步长进行排序,算法的最后一步就是普通的插入排序,但是到了这步,需排序的数据几乎是已排好的了(此时插入排序较快)。
步长的选择是希尔排序的重要部分。只要最终步长为1任何步长序列都可以工作(且步长要小于数组长度)。算法最开始以一定的步长进行排序。然后会继续以一定步长进行排序,最终算法以步长为1进行排序。当步长为1时,算法变为插入排序,这就保证了数据一定会被排序。
希尔排序速度测试:以80000个【0~80000】的随机整数为数组,进行速度测试(数据以我电脑为准)
交换式耗时:7s 移位式耗时:45ms
其他的排序算法有点复杂难懂,我将其另行整理了,可以点击下面的链接进入查找
排序算法_堆排序,该算法需要学习树的知识,可以在下面的目录链接中,自行查找
【数据结构与算法整理总结目录 :>】<-- 宝藏在此(doge)