20*:排序算法3:插入排序(从未排序区间依次取出元素插入到排序区间的适当位置。稳定)
问题
-(void)insertSequence:(NSMutableArray *)arr { for (int i = 1; i<arr.count; i++) { int a=[arr[i] intValue]; int k = i; while (k>0&&[arr[k] intValue]>a) { arr[k + 1] = arr[k]; k--; } arr[k+1] = [NSString stringWithFormat:@"%d",a]; NSLog(@"%@",arr); } }
目录
预备
正文
插入排序
1:算法描述
插入排序类似于大多数人安排扑克牌的方式。
- 从你手中的一张牌开始,
- 选择下一张卡并将其插入到正确的排序顺序中,
- 对所有的卡重复上一步。
2:算法思想
插入排序和选择排序一样,都分已排序区和位排序区。
将第一个元素标记为已排序 遍历每个没有排序过的元素 “提取” 元素 X i = 最后排序过元素的指数 到 0 的遍历 如果现在排序过的元素 > 提取的元素 将排序过的元素向右移一格 否则:插入提取的元素
3:动图演示
- 红色代表选中的需要排序的。
-
黄色的条代表已经排好序的元素;
-
绿色的代表此算法正在操作,进行比较交换的元素
-
蓝色代表还没有排序的
4:代码实现
public class InsertSort { public static int[] insertSort(int[] arr) { if(arr == null || arr.length < 2) return arr; int n = arr.length; // 下标为0的数默认是有序的,从下标为1的数开始遍历,将其放入他该去的地方 for (int i = 1; i < n; i++) { // 申请一个变量记录要插入的数据,也就是动图中红色的元素 int tmp = arr[i]; // 从已经排序的序列最右边的开始比较,找到比其小的数,即动图中绿色的元素序号 int j = i; // 红色元素下标大于0,要插入元素与遍历到的元素满足大小关系,遍历到的元素往后挪位腾位置
// 继续遍历,直到不满足大小关系停止,这个地方就是它的位置 // 即红色元素小于绿色元素时,绿色元素挪位 while (j > 0 && tmp < arr[j - 1]) { // 绿色元素往后挪一位 arr[j] = arr[j - 1]; j--; } // 存在比其小的数,插入 if (j != i) { arr[j] = tmp; } } return arr; } }
-
稳定性分析
稳定。在插入排序中,对于值相同的元素,我们可以选择将后面出现的元素,插入到前面出现元素的后面,这样就可以保持原有的前后顺序不变,所以插入排序是稳定的排序算法。
-
时间复杂度分析
如果要排序的数据已经是有序的,我们并不需要搬移任何数据。如果我们从尾到头在有序数据组里面查找插入位置,每次只需要比较一个数据就能确定插入的位置。所以这种情况下,最好是时间复杂度为O(n)。注意,这里是从尾到头遍历已经有序的数据。
如果数组是倒序的,每次插入都相当于在数组的第一个位置插入新的数据,所以需要移动大量的数据,所以最坏情况时间复杂度为O(n2)。
OC语言
原理:由数组的第2个位置开始比较,若果前方位置的元素比较大,则交换位置,若自己元素较大,而继续下一个元素,如此排列,那么被操作的那个元素前方位置的所有元素皆为有序。最坏情况下需要~ N^2/2 次比较和~ N^2/2 次交换,最好情况下需要 N-1次比较和 0 次交换
时间空间复杂度与冒泡排序一致
-(void)insertSequence:(NSMutableArray *)arr { for (int i = 1; i<arr.count; i++) { int a=[arr[i] intValue]; int k = i-1; while (k>=0&&[arr[k] intValue]>a) { arr[k + 1] = arr[k]; k-=1; } arr[k+1] = [NSString stringWithFormat:@"%d",a]; NSLog(@"%@",arr); } } // 或者 NSMutableArray *InsetSort(NSMutableArray *mArray, NSInteger start) { if (start == mArray.count) { return mArray; } for (NSInteger i = start; i > 0; i --) { if ([mArray[i] intValue] < [mArray[i-1] intValue]) { int temp = [mArray[i] intValue]; int k = (int)(i - 1); while (k >= 0 && [mArray[k] intValue] > temp) { mArray[k + 1] = mArray[k]; k -= 1; } mArray[k+1] = [NSString stringWithFormat:@"%d",temp]; } } InsetSort(mArray, start + 1); return mArray; }
插入排序优势:对于有序数组或部分有序数组,此排序方法是十分高效的,很适合小规模的数组,很多高级的排序算法都会利用到插入排序。
插入排序劣势:若果最少的元素都在最后部分的位置,那么该排序方法就会变得非常费劲了,最后的元素都要比较该元素位置减一次。
注意