算法概述:插入排序是稳定排序,具体流程如下:
1、从第一元素开始,认为第一个元素已经被排序;
2、取出下一个元素,在已经排序的元素序列中从后向前进行比较
3、如果取出的元素小于被比较的元素,则向前移;
4、如果取出的元素大于或等于比较的元素,则直接插入当前位置;
5、重复取出下一个元素进行2-4步骤;
流程图如下:
算法分析时间复杂度:O(n²)
最坏情况时间复杂度:O(n²);
(是该序列已经反向排序,即:{5, 4, 3, 2, 1}。需要比较的次数是 1 + 2 + 3 + 4 即:n(n + 1) / 2。关注最大增长量级,所以时间复杂度是:O(n²);
最好情况是:O(n);(正向排序,每个元素只需比较一次,总共n-1次比较,0次交换);
平均情况是:O(n²);
空间复杂度是O(1);
c#代码实现:
public class InsertionSort { public int[] a = { 12, 15, 9, 20, 6, 31, 24 }; public void Sort() { for (int i = 1; i < a.Length; i++) // 从第2个元素开始,跟自己前面的进行比较 { for (int j = i; j > 0; j--) // 从后往前,每一个元素进行比较 { if (a[j - 1] > a[j]) // 如果前面的元素大,则交换位置,并拿交换后的位置继续往前比较 { int t = a[j]; a[j] = a[j - 1]; a[j - 1] = t; } else // 如果前面的比我小,则不再向前比较,跳出该元素 { break; } } } foreach (int i in a) { Console.WriteLine("{0} ", i); } } }
erlang 代码实现:目前没有找到好的实现方式,采用了性能很差的列表实现,有大量reverse与++操作
insertion_sort() -> [H | T] = [12, 15, 9, 20, 6, 31, 24], insertion_sort(T, [H]). %% 默认第一个元素已经排好序 insertion_sort([], List) -> lists:reverse(List); insertion_sort([H1 | T1], [H2 | T2]) when H1 >= H2 -> %% 比前一个元素大,直接跳出该元素比较循环 insertion_sort(T1, [H1, H2 | T2]); insertion_sort([H1 | T1], [H2 | T2]) -> %% 比前一个元素小,与再前面的元素进行比较 L = insertion_replace(H1, [H2 | T2], []), insertion_sort(T1, L). insertion_replace(H1, [], Acc) -> lists:reverse([H1 | Acc]); insertion_replace(H1, [H2 | T2], Acc) when H1 >= H2 -> %% 比前面的元素大,跳出该元素循环 lists:reverse(Acc) ++ [H1, H2 | T2]; insertion_replace(H1, [H2 | T2], Acc) -> %% 比前面的元素小,继续往前进行比较 insertion_replace(H1, T2, [H2 | Acc]).