排序算法之插入排序

插入算法的基本思想是:每次将一个待排序的记录,按照其关键字的大小插入到前面
已经排好序的子表中的合适位置,直到全部记录插入完成位置,下面介绍一下直接插
入排序、二分插入排序及希尔排序。
直接插入排序:设待排序的记录存放在数组R[0..n-1]中,排序过程的某一中间时刻,
R被分成两个子区间R[0..i-1]和R[i..n-1],前一个是已经排好顺序的有序区,后面
是无序区。直接插入排序的基本操作是将当前无序区的第一个记录R[i]插入到有序
区  R[0..i-1]的合适位置,使R[0..i]变为新的有序区。代码如下:
public class ZhiJieSort {
    public static void main(String args[]){
        int i ;
        int a[] = {2,1,5,6,8,4,3};
        insertSort(a, a.length);
        System.out.println("排序后:");
        for( i=0;i<a.length;i++){
            System.out.print(a[i]+"  ");
        }   
    }
    public static void insertSort(int a[],int n){
        int i,j,temp;
        for(i=1;i<n;i++){
            temp=a[i];
            j=i-1;       //从右向左在有序去a[0..i-1]中找到a[i]的插入位置
            while(j>=0 && temp<a[j]){   
                a[j+1] = a[j]; //将记录大于a[i]的记录右移
                j--;
            }
            a[j+1] = temp; //在j+1处插入a[i]
        }

    }

}
表出态是正序的时候时间复杂度最小O(n),表初态为反序时,时间复杂度最大O(n2),
直接插入排序中只用到了i,j,temp三个辅助变量,与问题规模无关,所以空间复杂度
是O(1),直接插入排序是稳定的排序方法 。
二分插入排序:由于插入排序是在有序子表中进行查找和插入的,查找方法可以使用
二分查找来提高查找效率。仅查找记录位置的方法不同,其余跟直接插入思想一致。
代码如下:
    public class ErFenSort {
    public static void main(String[] args){
        int i;
        int a[] = {2,8,6,1,4,5,9};
        insertSort(a, a.length);
        for(i=0;i<a.length;i++){
            System.out.print(a[i]+"  ");        
        }   
    }
    public static void insertSort(int a[],int n){
        int i,j,low,mid,high,temp;
        for(i=1;i<n;i++){
            temp=a[i]; //将a[i]存入temp
            low = 0;
            high = i-1;
            while(low<=high){  //在a[low..high]中用二分查找插入的位置
                mid = (low+high)/2;  //取中间位置
             if(temp<a[mid]){
                 high = mid-1;   //插入点在左半边
             } else{
                 low  = mid+1;  //插入点在右半边
             }
            }
            for(j=i-1;j>=high+1;j--){  //记录后移
                a[j+1]= a[j];
            }
            a[high+1] = temp;    //插入
        }           
    }
}
 二分插入排序的空间复杂度为O(1),二分插入排序只是减少了关键字的比较次数,
 记录的移动次数并没有改变,因此时间复杂度仍为O(n2)。
 希尔排序:实际是一种分组插入方法,基本思想是先取一个小于n的整数d1作为第
 一个增量,把表的全部记录分成d1组,所有距离为d1的倍数的被分在同一组,在
 各组内进行直接插入排序;然后取第二个增量d2(<d1)重复上面的分组和排序,
 直至增量为1,即所有记录放在同一组中进行直接插入排序为止。代码如下:
public class ShellInsert {

    public static void main(String[] args){
        int a[] = {2,4,3,6,7,9,1,8};
        shellInsert(a, a.length);
        for(int i =0;i<a.length;i++){
            System.out.print(a[i]+" ");
        }
    }
    public static void shellInsert(int a[],int n){
        int i,j,gap,temp;
        gap = n/2; //增量初值
        while(gap>0){
            for(i =gap;i<n;i++){ //对所有相差gap位置的所有元素组采用直接插入排序
                temp = a[i];
                j = i-gap;
                while(j>=0 && temp<a[j]){ //对相隔gap位置的元素组进行排序
                    a[j+gap]=a[j];
                    j = j-gap;
                }
                a[j+gap] = temp;
            }
            gap = gap/2;  //减小增量
        }
    }

}
希尔排序是不稳定的排序算法,时间复杂度为O(n1.3),空间复杂度为O(1),
通常情况下速度比直接插入排序快。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值