大学时候学过数据结构和少量算法,但毕业这么多年也就着饭吃进去了。一直做的都是业务,涉及到的算法少之又少。最近觉得这样真没劲,作为一个码农,如果对算法一点欲望都没有的话,真的还是早点转行回家吧。
从初级算法学起,虽然什么选择排序、快速排序、冒泡排序一类的,真的只能算编程基础,算不上算法这么高深的level,但是还是要拿出来重温一下。很多东西都忘光光,更不晓得会不会理解有误。先学习再说吧。
希尔排序:(下面简称Sell)插入排序的升级优化版,插入排序需要对每一个元素进行挨个比对,根据大小往前插入到指定位置。对于比较大的数据集,sell通过分组排序的方式进行优化,提高了效率。
那么到底什么是希尔排序呢?
Sell,通过首先进行“宏观”调整的方式,进行大致排序,逐渐缩小增量,进行“微调”,直到增量为1的时候,彻底变成基本的插入排序。而这时候,序列已经基本成型,需要交换的位置已经不多。
基本实现方式:选取一个合适的增量step,集合中所有下标相差step的元素为一组,如a[0], a[0 + step], a[0 + step*2] 为第一组,a[1], a[1 + step], a[1 + step*2] 为第二组,以此类推。分别对每一小组进行基本的插入排序,排序之后,缩小增量step, 继续重复上面的动作,直到step = 1 为止,直接整体进行插入排序。
wiki上对Shell性能优于直接插入排序的理解:把全部元素通过划分几个区域来提升插入的性能,这样可以让一个元素朝最终位置迈进一大步,而不是一小步一小步的前进。
/**
* 希尔排序
* @author sala
*
*/
public class Shell {
public static void main(String[] args) {
int[] a = {13,14,94,33,82,25,59,94,65,23,45,27,73,25,39,10}; //length=16
int N = a.length;
int step = 1;
while (step < N){
step = step * 3 + 1; //选取最大的增量步数,这里为13
}
while (step >= 1){
for (int i = step;i < N;i++){
for (int j = i; j >= step && a[j] < a[j-step]; j -= step){
int temp = a[j];
a[j] = a[j-step];
a[j-step] = temp;
}
}
step = step/3;
}
}
}
备注: step增量的减少不一定是每次减1