Java---插入排序

插入排序

基本思想:
每一排将一个待排序的数,按照大小插入到已经排好序的适当位置上,直到数组排序完成,
根据查找方法的不同,大致分为三种:插入排序、折半插入排序、希尔排序

直接插入排序

基本思想

把一个数插入到已经排好的有序表中。查找插入位置的方法为顺序查找,从而得到一个新的有序表。

过程

在这里插入图片描述
1.第一趟查找15应该插入的位置,15>12,插入12后面
2.第二趟查找9应该插入的位置,9<15,插入15前面,9<12,插入12前面。
3.第三趟查找20应该插入的位置,20>15,插入15后面
4.第四趟查找6应该插入的位置,6<20、15、12、9,插入9前面
5.第五趟查找31应该插入的位置,31>20,插入20后面
6.第六趟查找24应该插入的位置,24<31,24>20,插入31前面,20后面

注意:
如果要排序的数大于有序表的最后一个元素,则跳过
如果要排序的数逐个与有序表的元素比较,如果大于,则往前移动一个元素。

代码实现

package cn.Tedu.ma.suanfa.sort;

import java.util.Arrays;

@SuppressWarnings({"all"})
public class InsertSort {
    public static void main(String[] args) {
        int[] a = {5, 3, 6, 4, 8, 9, 1, 2, 0};
        sort1(a);
        System.out.println(Arrays.toString(a));
    }

    public static void sort1(int[] a) {
        for (int i = 1; i < a.length; i++) {
            int t = a[i];
            int j = i - 1;
            if (t < a[j]) {
                for (; j >= 0 && t < a[j]; j--) {
                    a[j + 1] = a[j];
                }
                a[j + 1] = t;
                System.out.println("第" + i + "轮排序:" + Arrays.toString(a));
            } else {
                continue;
            }
        }
    }

    public static void sort(int[] a) {
        for (int i = 1; i < a.length; i++) {
            int t = a[i];
            int j;
            //t>a[j] 说明后面的值要比前面的任何一个值都要大,没必要进入里层循环
            for (j = i - 1; j >= 0 && t < a[j]; j--) {
                a[j + 1] = a[j];
            }
            a[j + 1] = t;
            System.out.println(Arrays.toString(a));

        }
    }

    public static void Sort(int[] s) {
        for (int i = 1; i < s.length; i++) {//注意i不能等于数组长度,因为数组下标从零开始而不是从1.
            int temp = s[i];//存储待插入数的数值
            int j;//j必须在此声明,如果在for循环内声明,j就不能拿出for循环使用,最后一步插入就无法执行
            for (j = i - 1; j >= 0 && temp < s[j]; j--) {
                s[j + 1] = s[j];//如果大于temp,往前移动一个位置
            }
            s[j + 1] = temp;//将temp插入到适当位置
        }
        System.out.println(Arrays.toString(s));//输出排好序的数组
    }
}

时间复杂度:o(n^2)

空间复杂度:o(1)

算法特点:

 (1):稳定排序。

 (2):算法简便,且容易实现。

 (3):更适合于初始记录基本有序(正序)的情况,初始记录无序,n较大,时间复杂度高,不宜采用。

折半插入排序

基本思想

在直接插入排序的基础上,将查找方法从顺序查找改为折半查找,就是找插入位置的比较次数减少了

    private static void BInsertSort(int[] s){
        for(int i=1;i<s.length;i++){
            int temp=s[i];//保存要插入的数的数值
            int low=0;//设置查找区间初始值 下区间值
            int high=i-1;//上区间值
            while(low<=high){//查找结束条件
                int mid=(high+low)/2;//折半,中间值
                if(s[mid]>temp){//待插入值小于中间值
                    high=mid-1;//上区间值变为中间值-1
                }
                else {//待插入值大于中间值
                    low=mid+1;//下区间值变为中间值+1
                }
            }
            for (int j=i-1;j>=low;j--){
                s[j+1]=s[j];//将low及low之前的数向前移动一位
            }
            s[low]=temp;//low就是待插入值的适当插入点
        }
        System.out.println(Arrays.toString(s));//输出排好序的数组
    }

时间复杂度:o(n^2)

空间复杂度:o(1)

算法特点:

 (1):稳定排序。

 (2):算法简便,且容易实现。

 (3):更适合于初始记录基本有序(正序)的情况,初始记录无序,n较大,时间复杂度高,不宜采用。

希尔排序

基本思想:
又称“缩小增量排序”(Diminishing Increment Sort),因D.LShell于1959年提出而得名。实质上是采用分组插入的方法,先将整个待排序数组分割成几组,在对每组采用直接插入排序,然后再增加每组的数据量,重新分组,再直接插入排序,直到增量为1,再对整体进行一次直接插入排序。

过程:
先来看一张书上的图:
在这里插入图片描述

       增量分别为:5,3,1。

代码实现:


```java
import java.util.Arrays;
 
public class ShellSort {
    public static void main(String[] args) {
        int[] a={2,6,3,8,1,4,2,7};
        Shellsort(a);//调用方法
    }
 
    public static void Shellsort(int[] s){
        int zl=s.length/2;//设置增量为数组长度的1/2
        for (;zl>0;zl=zl/2){//增量依次减少为1/2
            for (int i=zl;i<s.length;i++){//对相应增量的数组分组进行直接插入排序
                int temp=s[i];
                int j;
                for (j=i-zl;j>=0&&temp<s[j];j-=zl){//注意这里必须将j的初值设置为i-zl,否则数组下标会出界(也就是为负数)
                    s[j+zl]=s[j];
                }
                s[j+zl]=temp;
            }
        }
        System.out.println(Arrays.toString(s));//输出排好序的数组
    }}
    时间复杂度:(最好情况) (最坏情况)

    空间复杂度:

    算法特点:

         (1):不稳定排序(数据跳跃式移动)。

         (2):增量有各种取法,最后一个增量值必须为1。

         (3):适合初始记录无序,n较大的情况。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值