插入排序
算法思路
插入排序:每一趟将一个待排序的记录,按照其关键字的大小插入到有序队列的合适位置里,知道全部插入完成。
详细思路
从第二个元素开始寻找前面是否有比自己小的数,也就是要做到寻找的数的前面的所有数据都已经排好序了
利用类似交换位置的方法,利用 $temp = 待排数字$ ,相当于把这个位置移出去了,这个数字前面的数字可以直接往后依次移动一个位置(占据了带牌数字的位置)
因为待排数字已经记录了,并且比它大的数字向后挪,刚好给他空出一个比他小的数字后面一个的位置,这是就把他放进这个位置,这轮排序就结束了
要排序从第二数字到最后一个数字(第一个数字前面没有数字更没有比它大的数字,所以不用排)
时空间复杂度
时间复杂度
当数据正序时,执行效率最好,每次插入都不用移动前面的元素,时间复杂度为 $O(N)$ 。
当数据反序时,执行效率最差,每次插入都要前面的元素后移,时间复杂度为 $O(N^2)$ 。
==总之,数据越接近正序,直接插入排序的算法性能越好。==
空间复杂度
由直接插入排序算法可知,我们在排序过程中,需要一个临时变量存储要插入的值,所以空间复杂度为 $O(1)$ 。
稳定性
直接插入排序的过程中,不需要改变相等数值元素的位置,所以它是稳定的算法。
动态图像理解
优化
因为在一个有序序列中查找一个插入位置,以保证有序序列的序列不变,所以可以使用二分查找,减少元素比较次数提高效率。
==这里的优化思路和冒泡排序的isswap比较类似,都是是想要减少交换次数,但是插入排序不能那么暴力直接结束,但是也可以用二分查找,找到下一个未排序好序的位置==
例如:当序列排序一轮后为1、2、3、2、4正常情况来说,会拿着这个三和前面比较两次(但实际上3不会先前移动,所以这次的比较是无意义的),所以就可以通过Binary Search来避免这种无意义的排序
==二分查找==是对于有序数组而言的,假设如果数组是升序排序的。那么,二分查找算法就是不断对数组进行对半分割,每次拿中间元素和目标数字进行比较,如果中间元素小于目标数字,则说明目标数字应该在右侧被分割的数组中,如果中间元素大于目标数字,则说明目标数字应该在左侧被分割的数组中。
源文件
未优化源文件
vector 更通用模板
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| #include <iostream> #include <vector> using namespace std; vector<int> insertSort(vector<int> list){ vector<int> result; if (list.empty()){ return result; } result = list; for (int i = 1; i < result.size(); i++){ int temp = result[i]; int j = i - 1; for (j; j >= 0 && result[j] > temp; j--){ result[j + 1] = result[j]; } result[j + 1] = temp; } return result; } int main(){ int arr[] = { 6, 4, 8, 9, 2, 3, 1 }; vector<int> test(arr, arr + sizeof(arr) / sizeof(arr[0])); cout << "排序前" << endl; for (int i = 0; i < test.size(); i++){ cout << test[i] << " "; } cout << endl; vector<int> result; result = insertSort(test); cout << "排序后" << endl; for (int i = 0; i < result.size(); i++){ cout << result[i] << " "; } }
|
数组简单理解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| #include <iostream>
using namespace std;
void insertsort() { int a[] = {10, 8, 11, 7, 4, 12, 9, 6, 5, 3};
int size = sizeof(a) / sizeof(int); for (int i = 1; i < size; i++) { int temp = a[i]; int j = i - 1; while (j >= 0 && a[j] > temp) { a[j + 1] = a[j]; j--; } a[j + 1] = temp; } for (int i = 0; i < size; i++) cout << a[i] << " "; }
int main() { insertsort(); }
|
优化后源代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| #include <iostream> #include <vector> using namespace std;
int BinarySearch(vector<int> list, int n, int value){ int left = -1; int right = n; while (left <= right){ int middle = left + ((right - left) >> 1); if (list[middle] > value){ right = middle; } else{ left = middle; } } return (left < n) ? left : -1; } vector<int> BinaryInsertSort(vector<int> list){ vector<int> result = list; for (int i = 1; i < result.size(); i++){ int insert_index = BinarySearch(result, i, result[i]); if (insert_index != -1){ int temp = result[i]; int j = i - 1; while (j >= insert_index){ result[j + 1] = result[j]; j--; } result[j + 1] = temp; } } return result; } int main(){ int arr[] = { 6, 4, 8, 9, 2, 3, 1 }; vector<int> test(arr, arr + sizeof(arr) / sizeof(arr[0])); cout << "排序前" << endl; for (int i = 0; i < test.size(); i++){ cout << test[i] << " "; } cout << endl; vector<int> result; result = BinaryInsertSort(test); cout << "排序后" << endl; for (int i = 0; i < result.size(); i++){ cout << result[i] << " "; } }
|