插入排序(算法导论):对于少量元素排序,它是一个有效的算法。插入排序的工作方式像许多人排序一手扑克牌一样。开始时,我们的左手为空并且桌子上的牌面向下。然后,我们每次从桌子上拿走一张牌并将它插入左手正确的位置。为了找到一张牌的正确位置,我们从右到左将它与已在手中的每张牌进行比较。如图,左手的牌是排序好的,右手的牌是将要进行排序的。
给算法的为代码:
INSERTION-SORT(A) //假设输入一个有n个元素数组A[0....n-1]
for j = 1 to A.length //找到A[1...n-1]个元素的正确位置
key = A[j] //key 为要插入的元素
i = j - 1 // i 为要插入的元素的前一个元素位置
while i > -1 and A[i] > key // 前面有序的元素都比key大插在第一个,或者找到
A[i+1] = A[i] //比key小的插在其后面
i = i -1
A[i+1] = key
该算法像是在要匹配的元素位置挖一个坑,把前面比它大的元素往后填,最后把key放在正确的坑位。
我们先假设一个混乱序列:
A[2]的插入方式跟上面情况相同,我们直接开始A[3]的排序
后面同理,直接上代码
#include<iostream>
using namespace std;
void INSERTION_SORT(int A[],int size)
{
for (int j = 1; j < size; ++j)
{
int key = A[j];
int i = j - 1;
while (i > -1 && A[i] > key)
{
A[i + 1] = A[i];
--i;
}
A[i + 1] = key;
}
}
void Print(int A[],int size)
{
for (int j = 0; j<size; ++j)
{
cout << A[j] << " ";
}
cout << endl;
}
int main()
{
int A[] = { -2,3,5,1,7,3,11,14 };
int size = sizeof(A) / sizeof(int); //我们在传递一个数组名作为函数实参时,我们还应该传入这个数组的长度,因为在函数内我们无法获取数组的长度(正确的字符串数组除外,因为正确的字符串数组最后一个总是'\0')
Print(A,size);
INSERTION_SORT(A,size);
Print(A,size);
}
-2 3 5 1 7 3 11 14
-2 1 3 3 5 7 11 14
算法分析
假设A[0...n-1]第 i 行的每次执行需要的时间为 ci,是对A[j]值插入时while循环执行的次数
循环语句要判断结束,所以总要多执行一次
INSERTION-SORT(A) 代价 次数
0 for j = 1 to A.length c0 n
1 key = A[j] c1 n-1
2 i = j - 1 c2 n-1
3 while i > -1 and A[i] > key c3
4 A[i+1] = A[i] c4
5 i = i -1 c5
6 A[i+1] = key c6 n-1
综上
总的运行时间为:T(n)=
最好的情况是输入的数组是有序的,此时每次插入只判断一次while不进入
则最佳的运行时间为:
T(n)=
=
最坏的情况是输入的数组是逆序的,此时是对A[j]值插入时while循环执行的次数=j+1
while循环内
则最坏的运行时间为:
T(n)=
=
插入排序的稳定性:
由于排完序后相同元素的前后位置没有发生改变,所以插入排序是稳定的排序