从顺序查找到直接插入排序
无论从抽象过程还是具体实现代码来看,顺序查找是直接插入查找的基本组成元素。为什么这么说:
- 排序要遍历所有元素
- 从“未排序“数列中取出一个元素,插入到“已排序“数列中。需要在“已排序“数列中遍历到一个i,使得arr[i-1]<arr[i]<arr[i+1]。
需要两个基本的遍历过程。下面讨论算法的流程
直接插入排序的流程
首先脑海中要有一个基本模型:
【 {有序子序列} {当前待排序元素} {剩余待排序元素} 】
排序过程:
整个排序过程为n-1趟插入,即先将序列中第1个记录看成是一个有序子序列,然后从第2个记录开始,逐个进行插入,直至整个序列有序
注意:
有序子序列插入时,遍历不是从下标0开始,而是待排序元素的左边元素。
直接插入排序的性能
- Space Complexity: S(n)=O(1)
- Time Complexity: T(n)=O(\({n^2}\))
- 一种稳定排序方法
设对象个数为n,则执行n-1趟最坏情况下:第 i 趟比较i次,移动i次
最大比较次数:\(\frac{n(n-1)}{2}\)
最大移动次数:\(\frac{n(n-1)}{2}\)
最好情况下:每趟只需比较 1 次,不移动 总比较次数为 n-1次。
code
code 1(C++ Iterative)
void insertionSort(int arr[], int n) { int i, key, j; for (i = 1; i < n; i++) //从下标为1的位置开始遍历 { key = arr[i]; //保存待排序元素的值 j = i - 1; //从待排序元素的前一个开始 //找寻插入位置 while (j >= 0 && arr[j] > key) //循环条件1.不越界2.比key大 { arr[j + 1] = arr[j]; --j; } arr[j + 1] = key; //移动key到待插入位置 } }
code 2(C++ Recursive)
如果熟悉了直接插入排序,与递归技巧,不难发现如下关系:
\1. Base Case: If array size is 1 or smaller, return.
\2. Recursively sort first n-1 elements.
\3. Insert last element at its correct position in sorted array.
void insertionSortRecursive(int arr[], int n) { // Base case if (n <= 1) return; // Sort first n-1 elements insertionSortRecursive( arr, n-1 ); // Insert last element at its correct position // in sorted array. int last = arr[n-1]; int j = n-2; /* Move elements of arr[0..i-1], that are greater than key, to one position ahead of their current position */ while (j >= 0 && arr[j] > last) { arr[j+1] = arr[j]; j--; } arr[j+1] = last; }