版权声明:本文为博主原创文章,未经博主允许不得转载 https://blog.csdn.net/weixin_43629719/article/details/88375353
一、二分查找简述
在直接插入排序过程中,对有序的序列或者是数据进行排序,算法复杂度可以降低到O(n),然而大部分情况下算法复杂度都在O(N^2)左右,算法执行时间长,效率不高,由于插入排序是通过单独和前面已经排序好的序列一一进行比较的特性,故可以引入二分查找,从而实现算法 的优化,降低算法的时间复杂度,从而提高运行效率。二分查找只适用于对已经排好序的序列或者是数组进行查找。
二、代码实现
import java.util.Arrays;
public class InsertSort_BinarySearch {
public static void main(String[] args) {
int arr[] = { 3, 41, 52, 4, 38, 57, 9, 49 };
InsertSort_divide(arr, 0, arr.length - 1);
System.out.println(Arrays.toString(arr));
}
public static int Binarysearch(int[] arr, int num, int start, int end) {
/*
* 二分查找代码
*/
int mid = start + (end - start) / 2; // 查找需要进行比较的数字的位置。
if (start >= end) {
return num >= arr[start] ? start + 1 : start; // 如果数字比最后查找的数字大,返回这个位置+1,否则返回这个位置。
}
if (num == arr[mid]) {
return mid;
} else if (num > arr[mid]) {
return Binarysearch(arr, num, mid + 1, end); // 递归进行查找
} else {
return Binarysearch(arr, num, start, mid - 1); // 递归进行查找
}
}
public static void InsertSort_divide(int a[], int start, int end) {
if (start < end) {
InsertSort_divide(a, start, --end); // 递归实现插入排序。
int key;
for (int t = end + 1; t < end + 2; t++) { // 从第二个元素进行遍历排序,默认第一个数字为有序序列。
key = a[t];
int[] arr = Arrays.copyOfRange(a, 0, end + 1); // 获取当前已经排序好的序列
int binarysearch = Binarysearch(arr, key, 0, arr.length - 1); // 获取将当前的key需要放入的位置。
int length = arr.length - binarysearch; // 获取受影响的数组的数字的长度。
a[binarysearch] = key; // 把key放入数组中
System.arraycopy(arr, binarysearch, a, binarysearch + 1, length); // 把key值后面的数字全部后移一个位置,放入数组a中。
}
}
}
}
结果如下:
[3, 4, 9, 38, 41, 49, 52, 57]
三、算法分析
传统的直接插入排序方式,是通过将后面的数字与前面已经排序好的序列进行一一比较然后进行插入,这样实现起来就执行了太多的步骤,因为每一次插入排序过程中,都是在之前排序好的序列上进行操作,这样的话,我们借助于二分查找的特性,将每一个数据进行比较的次数进行减少,单个数字插入过程中最多进行比较的次数为log2n,所以直接插入+二分查找的算法复杂度在O(nlog2n),从而达到降低程序运算次数,提高排序速度的目的。