文章参考:
https://www.geeksforgeeks.org/insertion-sort/
B站视频1
B站视频2
1. 算法描述
Description:
Insertion sort is a simple sorting algorithm that works similar to the way you sort playing cards in your hands. The array is virtually split into a sorted and an unsorted part. Values from the unsorted part are picked and placed at the correct position in the sorted part.
Uses:
Insertion sort is used when number of elements is small. It can also be useful when input array is almost sorted, only few elements are misplaced in complete big array.
2. 实现思路
To sort an array of size n in ascending order:
- Iterate from arr[1] to arr[n] over the array.
- Compare the current element (key) to its predecessor.
- If the key element is smaller than its predecessor, compare it to the elements before.
Move the greater elements one position up to make space for the swapped element
.
Example:
3. 动图演示
4. 代码实现
// C program for insertion sort
#include <math.h>
#include <stdio.h>
void InsertionSort(int arr[], int n);
void PrintArray(int arr[], int n, int nth);
/* Function to sort an array using insertion sort*/
void InsertionSort(int arr[], int n)
{
int i, key, j;
for (i = 1; i < n; i++)
{
key = arr[i];
j = i - 1;
/* Move elements of arr[0..i-1], that are
greater than key, to one position ahead
of their current position */
while (j >= 0 && key < arr[j])
{
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = key;
PrintArray(arr, n, i);
}
}
// A utility function to print an array of size n
void PrintArray(int arr[], int n, int nth)
{
int i;
if(nth)
{
printf("第%dth轮插入排序结果如下:\n", nth);
}
else
{
printf("未排序之前初始状态如下:\n");
}
for (i = 0; i < n; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
/* Driver program to test insertion sort */
int main()
{
int arr[] = { 4, 3, 2, 10, 12, 1, 5, 6 };
int n = sizeof(arr) / sizeof(arr[0]);
PrintArray(arr, n, 0);
InsertionSort(arr, n);
return 0;
}
程序输出:
未排序之前初始状态如下:
4 3 2 10 12 1 5 6
第1th轮插入排序结果如下:
3 4 2 10 12 1 5 6
第2th轮插入排序结果如下:
2 3 4 10 12 1 5 6
第3th轮插入排序结果如下:
2 3 4 10 12 1 5 6
第4th轮插入排序结果如下:
2 3 4 10 12 1 5 6
第5th轮插入排序结果如下:
1 2 3 4 10 12 5 6
第6th轮插入排序结果如下:
1 2 3 4 5 10 12 6
第7th轮插入排序结果如下:
1 2 3 4 5 6 10 12
5. 性能分析
5.1. 算法性能
5.2. 时间复杂度 O(n^2)
当数据正序时,执行效率最好,每次插入都不用移动前面的元素,时间复杂度为O(N)。
当数据反序时,执行效率最差,每次插入都要前面的元素后移,时间复杂度为O(N^2)。
所以,数据越接近正序,直接插入排序的算法性能越好。
5.3. 空间复杂度 O(1)
由直接插入排序算法可知,我们在排序过程中,需要一个临时变量存储要插入的值,所以空间复杂度为 O(1) 。
5.4. 算法稳定性
直接插入排序的过程中,不需要改变相等数值元素的位置,所以它是稳定的算法。
6. 算法优化
因为是在一个有序序列中查找一个插入位置,所以可以使用二分查找,以减少元素比较次数提高效率。
二分查找是对于有序数组而言的,假设如果数组是升序排序的。那么,二分查找算法就是不断对数组进行对半分割,每次拿中间元素和目标数字进行比较,如果中间元素小于目标数字,则说明目标数字应该在右侧被分割的数组中,如果中间元素大于目标数字,则说明目标数字应该在左侧被分割的数组中。
// C program for implementation of
// binary insertion sort
#include <stdio.h>
int BinarySearch(int a[], int item, int low, int high);
void BinaryInsertionSort(int a[], int n);
void PrintArray(int arr[], int n, int nth);
// A binary search based function
// to find the position
// where item should be inserted
// in a[low..high]
int BinarySearch(int a[], int item, int low, int high)
{
if (high <= low)
return (item > a[low]) ? (low + 1) : low;
int mid = (low + high) / 2;
if (item == a[mid])
{
return mid + 1;
}
if (item > a[mid])
{
return BinarySearch(a, item, mid + 1, high);
}
return BinarySearch(a, item, low, mid - 1);
}
// Function to sort an array a[] of size 'n'
void BinaryInsertionSort(int a[], int n)
{
int i, loc, j, selected;
for (i = 1; i < n; ++i)
{
j = i - 1;
selected = a[i];
// find location where selected should be inseretd
loc = BinarySearch(a, selected, 0, j);
// Move all elements after location to create space
while (j >= loc)
{
a[j + 1] = a[j];
j--;
}
a[j + 1] = selected;
PrintArray(a, n, i);
}
}
// A utility function to print an array of size n
void PrintArray(int arr[], int n, int nth)
{
int i;
if(nth)
{
printf("第%dth轮插入排序结果如下:\n", nth);
}
else
{
printf("未排序之前初始状态如下:\n");
}
for (i = 0; i < n; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
// Driver Code
int main()
{
int a[] = { 37, 23, 0, 17, 12, 72, 31, 46, 100, 88, 54 };
int n = sizeof(a) / sizeof(a[0]);
PrintArray(a, n, 0);
BinaryInsertionSort(a, n);
return 0;
}
程序输出:
未排序之前初始状态如下:
37 23 0 17 12 72 31 46 100 88 54
第1th轮插入排序结果如下:
23 37 0 17 12 72 31 46 100 88 54
第2th轮插入排序结果如下:
0 23 37 17 12 72 31 46 100 88 54
第3th轮插入排序结果如下:
0 17 23 37 12 72 31 46 100 88 54
第4th轮插入排序结果如下:
0 12 17 23 37 72 31 46 100 88 54
第5th轮插入排序结果如下:
0 12 17 23 37 72 31 46 100 88 54
0 12 17 23 31 37 46 72 100 88 54
第8th轮插入排序结果如下:
0 12 17 23 31 37 46 72 100 88 54
第9th轮插入排序结果如下:
0 12 17 23 31 37 46 72 88 100 54
第10th轮插入排序结果如下:
0 12 17 23 31 37 46 54 72 88 100