一、直接插入排序(Insertion Sort)的基本思想是:每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子序列中的适当位置,直到全部记录插入完成为止
这里需要注意的地方是:红色部分字体 可以类比于抓牌插入的方法 不同点是:在两个相邻点插入数值后,插入点后面的数据需要一次向后移动一个单位
二、算法描述
比如对1 5 4 7 8 进行直接插入排序
⒈ 从第一个元素开始,该元素可以认为已经被排序
⒉ 取出下一个元素,在已经排序的元素序列中从后向前扫描
⒊ 如果该元素(已排序)大于新元素,将该元素移到下一位置
⒋ 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
⒌ 将新元素插入到下一位置中
⒍ 重复步骤2~5
三、代码描述
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace InsertSort { class Program { static void Main(string[] args) { Insertsort(); } private static void Insertsort() { //假设从第一个起,前面的已经排好序 Console.WriteLine("插入排序法"); int temp =0; int[] arr = { 23, 44, 66, 76, 98, 11, 3, 9, 7 }; //先打印出来看看 Console.WriteLine("排序前的数组"); foreach(int item in arr) { Console.Write(item+" "); } Console.WriteLine(); for (int i = 1; i < arr.Length; i++) { for (int j = i; j > 0;j-- ) //关键:从已经排好序列的插入点,后往前进行比较 { if(arr[j]<arr[j-1]) //如果改为arr[j]>arr[j+1],则为大到小的直接插入排序 { temp = arr[j]; arr[j] = arr[j - 1]; arr[j - 1] = temp; } } //打印每次排序的结果 Console.WriteLine("排序后的数组"); PrintStr(arr); } Console.ReadKey(); } private static void PrintStr(IEnumerable<int>arr) { foreach(int item in arr) { Console.Write(item + " "); } Console.WriteLine(); } } }
排序法 |
最差时间分析 | 平均时间复杂度 | 稳定度 | 空间复杂度 |
冒泡排序 | O(n2) | O(n2) | 稳定 | O(1) |
快速排序 | O(n2) | O(n*log2n) | 不稳定 | O(log2n)~O(n) |
选择排序 | O(n2) | O(n2) | 稳定 | O(1) |
二叉树排序 | O(n2) | O(n*log2n) | 不一顶 | O(n) |
插入排序 |
O(n2) | O(n2) | 稳定 | O(1) |
堆排序 | O(n*log2n) | O(n*log2n) | 不稳定 | O(1) |
希尔排序 | O | O | 不稳定 | O(1) |
常见算法时间复杂度:
O(1): 表示算法的运行时间为常量
O(n): 表示该算法是线性算法
O(㏒2n): 二分查找算法
O(n2): 对数组进行排序的各种简单算法,例如直接插入排序的算法。
O(n3): 做两个n阶矩阵的乘法运算
O(2n): 求具有n个元素集合的所有子集的算法
O(n!): 求具有N个元素的全排列的算法
优<---------------------------<劣
O(1)<O(㏒2n)<O(n)<O(n2)<O(2n)
时间复杂度按数量级递增排列依次为:常数阶O(1)、对数阶O(log2n)、线性阶O(n)、线性对数阶O(nlog2n)、平方阶O(n2)、立方阶O(n3)、……k次方阶O(nk)、指数阶O(2n)。