原理都很清楚:
让从1到n-1遍历,将
插入到之前已经排序好的子序列[
]中,用二分法找到插入的位置。
看起来很简单,但是实现的时候,也需要思考一些细节。
二分法的插入排序关键在于插入位置的下标。
void insertsort(int *arr, int n){
/* arr: array, n: size of arr*/
int s, t, mid;
for(int i=1; i<n; i++){
s = 0;
t = i;
while(s < t){
mid = (s + t) / 2;
if(arr[i] < arr[mid]){
t = mid;
} else if(arr[i] >= arr[mid]){
s = mid + 1;
}
}
//insert arr[i] to index t
int tmp = arr[i];
for(int j=i; j>t; j--){
arr[j] = arr[j-1];
}
arr[t] = tmp;
}
}
其中, s为头指针,t为尾指针。s选择指向子序列的第一个元素,t指向最后一个元素的下一个位置(很重要)
对于一个子序列,所有有可能的插入位置有i+1个。也就是每两个元素之间(i-1个)加上序列的头和尾。
所以,我们需要一个指针的值域也是有i+1个值。t正好满足了这个需求。由于,所以可以用t为基准,作为元素的插入点,这也是为什么t需要是指向子序列的最后一个元素的下一个位置。如果t指向的是子序列的最后一个元素,则
,值域只有i个值。那么,当子序列的所有值都小于
的时候,
无法插入到子序列的末尾处。