插入排序之折半插入排序

 

基本思想:插入排序的基本操作是在一个有序表中进行查找插入,用折半查找实现查找步骤。

复杂度:时间复杂度 O(n2) 空间复杂度O(1)

二分插入排序图示

这里写图片描述

第一行是原始数据,第二行是假设已经排好了前i个数据,在排a[i]时,采用二分搜索(查找)的方法在前i个数据中找到合适的位置插入。下面几行是二分查找的步骤,每次将查找的范围缩小一半儿,直到找到合适位置为止,然后在该位置上插入a[i],其余数据往后移动一个位置。

二分插入排序算法分析

  1. 二分搜索比顺序搜索查找快,所以二分插入排序就平均性能来说比直接插入排序要快
  2. 它所需的排序码比较次数与待排序对象序列的初始排列无关,仅依赖于对象个数。在插入第i个对象时,需要经过log2i+1次排序码比较,才能确定它应插入的位置。 将n个对象用折半插入排序所进行的排序码比较次数比较次数(KCN):n1(log2i+1)nlog2n
  3. 二分插入排序是一个稳定的排序方法。
  4. 当n较大时,总排序码比较次数比直接插入排序的最坏情况要好得多,但比其最好情况要差。
  5. 在对象的初始排列已经按排序码排好序或接近有序时,直接插入排序比折半插入排序执行的排序码比较次数要少。折半插入排序的对象移动次数与直接插入排序相同,依赖于对象的初始排列。

代码实现:二分法插入排序算法原理及JAVA实现

package testSortAlgorithm;

public class BinaryInsertionSort {
    public static void main(String[] args) {
        // 0下标数据用来作为哨兵
        int[] array = { 0, 49, 38, 65, 97, 76, 13, 27 };
        binaryInsertSort(array);
        for (int i = 1; i < array.length; i++) {
            System.out.print(array[i] + " ");
        }
    }

    public static void binaryInsertSort(int[] array) {
        int low, high, mid;
        for (int i = 2; i < array.length; i++) {
//            哨兵位
            array[0] = array[i];
//            要将第i位插入前i-1有序序列
            low = 1;
            high = i - 1;
//            折半查找
            while (low <= high) {
                mid = (low + high) / 2;
                System.out.println("low " + low + " high " +high + " mid " + mid);
                if (array[0] < array[mid]) {
                    high = mid - 1;
                } else {
                    low = mid + 1;
                }
            }
//            要插入high+1位置,需要把high+1——i-1位置上的数据依次后移一位
            for (int j = i - 1; j >= high + 1; j--) {
                array[j + 1] = array[j];
            }
            array[high + 1] = array[0];
        }
    }
}

折半查找算法(前提是数据已经排好序)

package testSortAlgorithm;

public class BinarySearch {
    public static void main(String[] args) {
        int a[] = {1,3,6,8,9,10,12,18,20,34};
        int i = 12;
        System.out.println(binarySearch(a,i));
    }
    public static int binarySearch(int[]a ,int num){
        if (a.length == 0) {
            return -1;
        }
        int startPosition = 0;
        int endPosition = a.length - 1;
        int midPosition = (startPosition + endPosition)/2;
        while (startPosition <= endPosition) {
            if (a[midPosition] == num) {
                return midPosition;
            }
            if (a[midPosition] > num ) {
                endPosition = midPosition - 1;
            }
            if (a[midPosition] < num ) {
                startPosition = midPosition + 1 ;
            }
            midPosition = (startPosition + endPosition)/2;
        }
        return -1;
    }
}

 

参考资料:

1、排序算法二:二分(折半)插入排序算法 c++实现

2、二分法插入排序算法原理及JAVA实现

posted @ 2017-04-10 14:48  milkty  阅读(737)  评论(0)    收藏  举报