通俗理解插入排序(直接插入排序,折半插入排序,希尔排序)

来源:互联网 发布:制作淘宝优惠券网站 编辑:程序博客网 时间:2024/05/16 08:58

直接插入排序

直接插入排序就是将待排序的值,逐一按元素的大小插入前面的有序序列
例如对-23,45,2,-45,9,5,3,65,-24进行直接插入排序,我们可以看成将45,2,-45,9,5,3,65,-24逐步插入-23的序列
这里写图片描述

package sort;public class Demo6 {    public static void main(String[] args) {        int[] num = new int[]{-23,45,2,-45,9,5,3,65,-24};        sort(num);        for (int i = 0; i < num.length; i++) {            System.out.print(num[i]+" ");        }    }    public static void sort(int[] data){        int tmp;//暂时保存待插入的值        //从第2个开始,进行n-1的插入操作        for (int i = 1; i < data.length; i++) {            //若待插入的值比前面有序序列的最大值都大,则说明现在就是有序的            if(data[i]<data[i-1]){                tmp = data[i];                int j = i-1;                for (; j >=0&&data[j]>tmp; j--) {                    data[j+1] = data[j];//把数据往后移动                }                data[j+1] = tmp;//退出循环时候,j指向的数值比tmp小,或者j<0            }        }    }}

这里写图片描述

折半插入排序

折半插入排序是对直接插入排序的一种改进,直接插入排序中0到i-1有序的,折半插入排序就是用折半查找迅速找到需要插入的地方,而不用从i-1开始逐一向前比较。

这里写图片描述
使用折半查找查找3应该插入的位置,
1. low=0 hight=6 mid=(low+hight)/2=3
因为data[3]<=data[7],说明应该插入的位置在4-6之间
这里写图片描述
2. low=mid+1=3+1=4 hight=6 mid=(low+hight)/2=5
这里写图片描述
因为data[5]>data[7]说明应该插入的位置在4到5间

3 low=4 hight=mid-1=5 mid=(4+5)/2=4
这里写图片描述
因为data[4]>data[7]所以插入的位置是4,但是此时折半查找并没有结束
4 low=4 hight=mid-1=3 因为此时low>hight所以折半折半查找结束
这里写图片描述
low的位置便是应该插入的位置(该位置满足data[low]>待插入的值,data[hight]<=待插入的值,或者hight为-1,也就是插入的位置为0)
5 将low到i-1的数字都往后移动腾出low的位置将插入值插入,注意备份i位置的值避免被覆盖后找不回待插入值。
这里写图片描述

package sort;public class Demo7 {    public static void main(String[] args) {        int[] data = new int[]{-23,45,2,-45,9,5,3,65,-24};        sort(data);        for (int i = 0; i < data.length; i++) {            System.out.print(data[i]+" ");        }    }    public static void sort(int[] data){        int low,hight,mid;        int tmp;//备份存储待插入的值        for (int i = 1; i < data.length; i++) {            if(data[i]<data[i-1]){                tmp = data[i];                low = 0;                hight = i-1;                while(low<=hight){                    mid = (low+hight)/2;                    if(data[mid]<=tmp){  //当中间值小于等于待插入的值,搜索[mid+1,hight]区间                        low = mid +1;                    }else{                        hight = mid - 1; //当中间值小于等于待插入的值,搜索[low,mid-1]区间                    }                }                //将[low,i-1]区间的值后移动                for (int j = i-1; j >= low; j--) {                    data[j+1] = data[j];                }                //待插入的值插入                data[low] =tmp;            }        }    }}

这里写图片描述

希尔排序(Shell排序)

Shell排序是对直接插入排序的改进,它通过加大插入排序中元素之间的间隔,并在这些有间隔的元素进行插入排序,使得数据项跨度移动,不用一步一步往前比较和移动。
Shell排序算法的关键就在于确定h序列的值,h就是间隔多少,序列最小值为1(这时就是直接插入排序),它们存在h=3*h+1的关系。当对一个数列进行Shell排序时,h的值为多少开始比较合适?h刚好大于数列长度除于3。

int h=1;while(h<=arrayLength/3){  h = 3*h+1;}//得到的h的值就是Shell排序的增量

得到了Shell排序的增量h序列值后,就从第h个后面数字开始对前面间隔h的值进行插入排序。
例如对-23,45,2,-45,9,5,3,65,-24进行Shell排序
1.长度为9,则可以计算出增量为4
2.从第4个后面数字(这里就是9)开始对前面间隔4的值进行插入排序
这里写图片描述

package sort;public class Demo5 {    public static void main(String[] args) {        int[] num = new int[]{-23,45,2,-45,9,5,3,65,-24};        sort(num);    }    public static void sort(int[] data){        int h = 1;//增量最小为1        int tmp;//存储待插入的值        while(h<=data.length/3){ //计算Shell的最大增量            h = h * 3 + 1;        }        while(h>=1){            //从第h后面的数字开始对前面的间隔为h的数字进行插入排序,也就是从第h+1个开始,下标为h            for(int i = h; i<data.length; i++){                tmp = data[i];                if(data[i-h]>tmp){                    int j = i-h;                    //对前面的间隔为h的数字进行插入排序,,,当为1时就是直接插入排序了                    for (; j>=0&&data[j]>tmp; j=j-h) {                        data[j+h] = data[j];//数据往后移动,间隔为h                    }                    data[j+h] = tmp;//这里加上h是因为循环最后还减多了一个h                }            }            h = (h-1)/3;//重新计算h的值,寻找小一点的增量            //打印出来看看,每一趟的Shell排序            for (int j = 0; j < data.length; j++) {                System.out.print(data[j]+" ");            }            System.out.println();        }    }}

这里写图片描述

三种插入排序的时间复杂度和空间复杂度

插入排序 时间复杂度 空间复杂度 直接插入排序 O(n^2) O(1) 折半插入排序 O(n^2) O(1) 希尔排序 O(n^3/2)~O(n^7/6) O(1)

个人博客:http://www.javaknowledge.cn/?p=21

1 0
原创粉丝点击