插入排序:
1.直接插入排序是一种最简单的排序方法,它的基本操作就是将一个记录插入到已排序好的有序表中,从而得到一个新的、记录数增1的有序表。
直接插入排序算法描述:
插入排序的算法其实就和每次摸扑克牌类似的,现在假设你面前有5张依次倒扣的扑克牌,这5张扑克牌分别从
左到右分别为{4, 2, 5, 7, 1},但是在摸牌之前你是不知道点数的;
现在开始摸牌:
1.从左边第一张开始摸牌,摸起来发现点数为4,此时你手里只有一张点数为4的扑克牌{ 4 },默认第一张已经被排序;
2.再摸第二张牌,点数为2,比较之后发现比第一次摸到的点数为4的牌小,那么现在就把2放在4前面此时就为{ 2, 4};
3.再摸第三张牌,点数为5,比较之后发现这张牌比已经排序好的最后一张4要大,那么就可以直接插入到4的后边{ 2, 4, 5};
4.重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
5.将新元素插入到该位置后
6.重复步骤2~5
空间复杂度和时间复杂度:
由于每次在实现算法的时候都会临时的存一个变量,所以直接插入的空间复杂度为O(1);
当数据是正序的时候,只需遍历一遍就好,时间复杂度就为O(n);
当数据是逆序的时候,数据都必须交换,时间复杂度就为O(n^2);
其平均时间复杂度为O(n^2);
算法的稳定性:
由于排序前后两个相等的数相对位置不变,则算法稳定。
举例说明:{4, 7, 2(a), 2(b), 8},
上述排序后顺序为{2(a), 2(b), 4, 7, 8};相同的数字2,在排序完成后a与b的位置没有发生变化,a还是在b的前面,所以
插入排序是一种稳定的排序。
稳定性的好处:
从一个键上排序,然后再从另一个键上排序,第一个键排序的结果可以为第二个键排序所用。
代码实现:
//插入排序
void insertion_sort(int arr[], int len){
int i, j, key;
for (i = 1; i<len; i++){ //从取出的第二张牌开始,每次取一张牌插入到有序数列中
key = arr[i]; //将取出的牌,先保存起来
j = i - 1;
while ((j >= 0) && (arr[j]>key)) { //将取出的牌,与有序的数列进行比较,这是从小到大排列
arr[j + 1] = arr[j]; //如果比前面的数字小,那么就将此时取出的牌插入到前面,将前面的点数牌向后移动一位
j--;
}
arr[j + 1] = key; //如果取出的牌比前面的有序牌都大,只要将此时取出的牌放在后边就好
}
}
//打印数组
void Print(int arr[], int len){
for (int i = 0; i < len; i++){
printf("%d ", arr[i]);
}
printf("\n");
}
void Test(){
int arr[] = {4, 2, 5, 7, 1};
int len = sizeof(arr) / sizeof(int);
Print(arr, len);
selection_sort(arr, len);
Print(arr, len);
}
int main(){
Test();
return 0;
}
代码效果: