插入排序,C语言实现
插入排序是稳定排序,时间复杂度最低为O(n),最高为O(n^2),平均为O(n^2)。
插入排序是将数组分为两部分,一部分已经排好序,另一部分未排好序,每次从未排好序的部分取第一个元素插入到已经排好序的部分正确的位置,如此循环n-1次。
就好像你手里有十张牌,左手有一张,右手有九张。每次从右手的牌中取最左边的一张插入到左手的牌里,右手的牌插完了,排序也完成了。
编写代码要点:
- 时间复杂度是O(n^2),意味着有双重循环。外面大循环代表插入的轮次,因为一开始左手有一张牌,所以只需要插入n-1次即可,也就是每次插入都从左手牌末尾元素的下标+1开始。
- 内层循环是从后方前反向遍历,因为要插入到正确的位置,需要给这个待插入的元素挪一个位置,所以在待插入的位置后面的所有元素都要整体后移一个位置,覆盖掉待插入元素初始的位置,然后把待插入的元素放置在空出来的位置即可。因为在元素整体后移给待插入元素挪位置的时候会覆盖掉待插入元素原本的位置,所以需要用一个元素来保存待插入的元素。
插入排序代码如下:
#include <stdio.h> void insertSort(int arr[], int n) { int i, j; int currentElement; // 前i个元素有序,初始情况只有一个有序组,也就是数组的第一个元素,故i=1 for (i = 1; i < n; ++i) { currentElement = arr[i]; // 保存当前要插入的元素,因为之后移动数组元素的时候会覆盖掉当前的元素 // 从后向前遍历,找到插入位置,也就是最后一个比待插入的元素小的元素 // 从待插入的前一个元素开始遍历,所以j=i-1,遍历到末尾,也就是数组开头,i=0 for (j = i - 1; j >= 0; --j) { if (arr[j] > currentElement) { arr[j + 1] = arr[j]; } else { break; // 找到了插入元素的位置,结束循环 } } // 此时arr[j]是<currentElement的,它并没有被移动,也没有留出空缺,空缺在它身后 // 故把currentElement赋值给arr[j]身后的空缺,也就是arr[j+1] arr[j + 1] = currentElement; } } int main() { int i = 0; int arr[10] = {5, 2, 3, 8, 1, 2, 6, 9, 3, 7}; insertSort(arr, 10); for (i = 0; i < 10; ++i) { printf("%d ", arr[i]); } return 0; }