插入排序和归并排序

插入排序

一共有三种:直接插入排序、希尔排序和折半插入排序。最后一个折半插入排序,感觉用在数组上面不太方便,就没写出来。

递归实现没有思路,使用的非递归算法。

直接插入排序

这个算法默认前n个数是已经排好序的,n随着你的插入逐渐变大,最开始是1。

然后从后往前逐渐查找应该插入的位置;我的算法是从小到大,那就依次对比当前位置的值是否比要插入的值大,如果大就往后移动一个位置,小于等于当前位置的值就进行插入结束这一次的插入操作,进入下一次。

希尔排序

这个排序算法的思路就是将数组分为好多组,然后逐渐减少,最终只剩下一组,就是最终的结果。

最开始将数组根据初始增量分为两两一组,在每一组内进行排序;逐渐缩短增量,直到增量为一,就是排好序的数组。

在组内排序的算法其实可以是别的算法。

折半插入排序

和直接插入排序思路相同,但是在查询插入点的时候,是从已经排好序的数组中间查询要插入的点,查询到之后将插入点之后的数依次后移,将数插入。

归并排序

数组从大依次切开,分为n组,然后再将相邻的两组进行合并,并排序,最后只剩下一组就是结果。这个算法使用递归会比较简单点。非递归实现,没思路。

代码

package 算法设计与分析;

public class Work3 {

    public Work3(){
        int[] nums = { 2, 3, 8, 4, 5, 7, 1, 9, 6 };

        insertSort1( nums );

        for ( int i : nums )
            System.out.println( i );
    }

    //插入排序--直接插入排序
    public void insertSort1( int[] array ){

        //从第2个数开始,依次将数插在已经排序过的数组中,前i+1个数为已经排序的
        for ( int i = 1; i < array.length; i++ ){

            //存储将要插入的数,以及索引
            int temp = array[i], j;

            //依次比较,如果要插入的数小于当前位置的数了,就将前面的值依次向后移动一位
            for ( j = i-1; j >= 0 && temp < array[j]; j-- ){
                array[j+1] = array[j];
            }
            //将要插入的数存储在,最后查询到的位置上
            array[j+1] = temp;
        }
    }

    //插入排序--希尔排序
    public void insertSort2( int[] array ){

        //初始增量为数组长度的一半,之后依次减半,直到1停止
        for ( int len = array.length/2; len >= 1; len/=2 ){

            //对每组进行组内排序
            for ( int i = 0; i < len; i++ ){

                //进行组内排序,其实这就是一个直接插入排序
                for ( int j = i+len; j < array.length; j+= len ){

                    int temp = array[j], k;
                    for ( k = j-len; k >= 0 && temp < array[k]; k-=len ){
                        array[k+len] = array[k];
                    }
                    array[k+len] = temp;
                }
            }
        }

    }

    //归并排序--递归算法
    public void mergeSort( int[] array ){
        devideArray( 0, array.length-1, array );
    }

    //先对数组进行分割,然后进行合并,递归
    public void devideArray( int start, int end, int[] array ){


        //最小长度为1
        if ( start < end ){

            //对数组进行分割
            int middle = (start+end)/2;
            devideArray( start, middle, array);
            devideArray( middle+1, end, array );

            //合并
            mergeArray( start, middle, end, array );
        }

    }

    //对数组进行合并
    public void mergeArray( int start, int middle, int end, int[] array ){

        //用于临时存储合并后的排序数组
        int[] tmp = new int[end-start+1];
        int len = 0;

        //标记在合并的两个数组中的位置
        int left = start;
        int right = middle+1;

        while ( true ){

            //当循环均在在两个部分的范围之内时,进行排序
            if ( left <= middle && right <= end ){

                if ( array[left] < array[right] ){
                    tmp[len++] = array[left++];
                }else{
                    tmp[len++] = array[right++];
                }

                //只有左部在范围之内,直接添加上去,不需要再进行排序
            }else if ( left <= middle && right > end ){
                tmp[len++] = array[left++];

                //只有右部在范围之内时,同样直接添加
            }else if ( left > middle && right <= end ){
                tmp[len++] = array[right++];

                //结束循环
            }else
                break;
        }

        //将归并好的部分重新添加在原数组的位置
        for ( int i = start; i <= end; i++ ){
            array[i] = tmp[i-start];
        }
    }


    public static void main(String[] args) {
        Work3 work3 = new Work3();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值