1. 问题描述:
插入排序中寻找插入位置的操作可以通过二分查找的方法来实现,设计一个使用二分查找法找插入位置的改进的插入排序算法
2. 思路分析:
① 其实与插入排序没有本质的区别,只是在查找元素的时候查找元素插入的位置的方法不一样而已,我们之前的直接插入排序使用的是从后往前进行扫描进而找到当前元素插入的位置,而现在使用的是二分查找的方法来查找插入的位置,因为在数组中每插入一个元素的时候那么从开始位置到新插入的元素的位置的元素都是有序的,所以可以使用二分查找的方法来找到插入的位置
② 基于上面的想法,我们可以在最外面使用一层for循环,循环遍历从第二个元素开始,这与直接插入排序是一样的,接下来是使用二分查找的方法来找到插入的位置,循环的执行条件是low小于等于high,在循环中判断当前需要插入的元素比中间位置的元素的大小来更新low与high,通过对简单的几个元素的分析我们知道当前元素需要插入的位置是在low这个位置的,所以我们还需要使用一个循环来移动从low 到当前需要插入元素的上一个元素都是需要往后移动的,但是我们在移动的时候需要注意需要从后往前进行移动(从简单例子中分析出当前元素需要插入的位置在low这个位置的
③ 我们可以发现在二分查找的过程中通过改变查找插入的位置即可改变元素是升序排序的还是降序排列的,我们只需要调换更新mid的两条语句即可得到升序或者是降序的序列
3. 下面是具体的C语言代码:
#include<iostream>
using namespace std;
void sort(int arr[], int n){
int low, high, place, temp;
for(int i = 1; i < n; ++i){
low = 0, high = i - 1;
temp = arr[i];
while(low <= high){
int mid = (low + high) / 2;
if(temp <= arr[mid]){
high = mid - 1;
}else{
low = mid + 1;
}
}
//说明关键字应该是插入到low这个位置的所以low这个位置
place = low;
//注意应该是j >= place
for(int j = i - 1; j >= place; --j){
arr[j + 1] = arr[j];
}
arr[place] = temp;
}
}
int main(void){
int arr[9] = {3, 5, 1, 2, 7, 9, 12, 14, 8};
sort(arr, 9);
for(int i = 0; i < 9; ++i){
cout << arr[i] << " ";
}
cout << endl;
return 0;
}