插入排序算法(InsertionSort)
1、引言
在生活中,我们总是需要对一些同类事物进行排序,插入排序便是最常用的一种方法。我举一个大家在学校都使用过插入排序方法的例子。每次下课回宿舍后把书包里的书一本一本的拿出来,然后把书架上面的书左拨拨,右推推,挤出一个缝隙,然后把想插入的书插入其中,这个例子是不是很形象呀, 这下是不是瞬间悟了插入排序算法哈!!
再举一个最经典的例子,我们平常耍的扑克牌游戏。玩家将拿到的每张牌插入手中合适的位置,以便手中的牌按照一定的顺序排列。
以上的例子可以看出来插入排序算法只适合元素较少的事物。如果书桌上所列的书太多,想要挤出一个缝隙插入一本书是相当困难的;如果用两副扑克牌玩游戏,随着手中牌越来越多,插入从牌堆新掀的牌也是相当困难的。
2、InsertionSort算法描述
假设将需要排序的数字列表分成两个子列表:已排序的和未排序的。在每轮,把未排序子列表中的第一个元素转移到已排序子列表中,并且插入合适的置。
未排序子列表中的第一个元素就是插入值(insertion_val),插入值和已排序子列表中的元素从后往前一一比较,如果已排序子列表中的元素大于插入值,则其往后移一个位置,插入值往前移一个位置。按照这样的逻辑,插入值从后往前遍历比较已排序子列表中的每一个元素,直到找到合适的位置插入。
插入值经过层层比较插入到已排序子列表的合适位置,称之为一轮排序, 一个含有N个元素的数字列表至少需要N-1轮排序。为什么是N-1轮排序?因为排序开始时,前两个元素先比较,形成已排序列子表,所以在第一轮排序中就已经用了两个元素,即排序轮数比元素个数小1。
当遍历完未排序子列表中的元素,最后的结果即为已排序的数字列表。
3、用图示的方法描述InsertionSort算法的概念
注:红色墙块左边为已排序元素,右边为未排序元素
4、用代码描述InsertionSort算法的概念
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
//函数声明
void InsertionSort(int* arr, int sz);
//InsertionSort 算法
int main()
{
//将需要排列的一组数存入数组
int arr[] = { 9,3,1,7,5, };
//求数组元素的个数
int sz = sizeof(arr) / sizeof(arr[0]);
//将数组传入函数
InsertionSort(arr,sz);
//打印已排序的数组
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
//插入排序函数
void InsertionSort(int* arr, int sz)
{
//定义插入值变量,未排序子列表的第一个元素
int insertion_val;
//第二层循环变量
int j;
//外层循环控制要插入的值
//开始时前两个值比较
for (int i = 1; i < sz; i++)
{
//取出插入值,用做循环比较
insertion_val = arr[i];
//内层控制已排好序的值后移
for (j = i - 1; j >= 0 && insertion_val < arr[j]; j--)
{
arr[j + 1] = arr[j];
}
//循环结束后确定了要插入的位置,即填入插入值
arr[j + 1] = insertion_val;
}
}
关键代码解释:
① 外层循环代码块:int i = 1
开始时前两个值比较,用数字列表中第二个元素和第一个元素比较,形成已排序列表。
② 内层循环代码块
A: j = i - 1
插入值和已排序元素遍历比较
B: arr[ j + 1 ] = arr[ j ]
确定插入值插入的位置,即已排序的元素后移,为插入值腾出位置。
5、总结
这篇文章写了InsertionSort算法的文字描述、图示描述和代码描述。在这里为了方便实现此算法只输入了5个正整数。算法一般情况下具有通用性,所以这个InsertionSort算法可以对n个整数进行排序。各位看官,也可以拷贝代码试试输入更多的整数(正整数,0和负整数),看看这个算法能不能对数字列表正确排序。今天的分享总结就到这里了,我们下期再见 !!!