「@Author:Runsen」

插入排序

插入排序(英语:Insertion Sort)是一种简单直观的排序算法。

一个有序的数组,我们往里面添加一个新的数据后,如何继续保持数据有序呢?很简单,我们只要遍历数组,找到数据应该插入的位置将其插入即可。

插入排序法详细讲解(深入插入排序和选择排序)(1)

图片来自王争算法专栏

通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

插入排序在实现上,在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。

因此,代码编写需要判断插入元素和当前元素的大小关系,遍历时需要从数组的第二个数开始。

如果插入元素大于当前元素,则将待插入元素插入到当前元素的后一位。

如果插入元素小于当前元素,则将当前元素后移一位。直到找到一个当前元素小于插入元素。

因此,在for循环遍历时,又有一个while内循环的条件,条件的内容是插入元素的索引减一和零进行对比。如果插入元素小于当前元素,同时对索引进行减一操作。如果出现了索引等于零的情况,那么表示插入元素等于当前元素。

下面是插入排序的具体Python代码。

definsert_sort(a): length=len(a) iflength<=1: returna #从数组的第二个数开始 foriinrange(1,length): #从后向前扫描 j=i-1 #value指的是插入元素 value=a[i] whilej>=0: ifa[j]<value: #插入元素大于当前元素,则将待插入元素插入到当前元素的后一位 a[j 1]=value break else: #插入元素小于当前元素,则将当前元素后移一位 a[j 1]=a[j] ifj==0: a[j]=value j-=1 returna definsertionSort(arr): #对上面的代码进行简单化 foriinrange(len(arr)): preIndex=i-1 current=arr[i] whilepreIndex>=0andarr[preIndex]>current: arr[preIndex 1]=arr[preIndex] preIndex-=1 arr[preIndex 1]=current returnarr if__name__=='__main__': nums=[54,26,93,17,77,31,44,55,20] insert_sort(nums) print(nums)#[17,20,26,31,44,54,55,77,93]

下面对Python代码改为Java代码。代码来自菜鸟教程。

//Java importjava.util.Arrays; publicclassSolution{ publicstaticvoidmain(String[]args){ InsertSort(newint[]{9,20,10,13,12}); } publicstaticvoidInsertSort(int[]arr){ intvalue;//待插入元素 intindex;//初始值为待插入元素前一个元素的索引 for(inti=1;i<arr.length;i ){ //i从第二个元素开始,默认第一个元素是有序的 //循环条件是小于数组长度,因为也要将最后一个元素插入到前面的序列 value=arr[i]; index=i-1;//初始为前一个元素 while(index>=0&&value<arr[index]){ //需要保证index合法 //每当前面的元素比待插入元素大,就向后移动 arr[index 1]=arr[index]; //不用怕覆盖,因为value保存着待插入的值 index--; } //当退出循环,表明已经找到了待插入位置,即index 1 arr[index 1]=value; } System.out.println(Arrays.toString(arr)); } }

下面对Python代码改为JavaScript代码。代码来自菜鸟教程。

//JavaScript functioninsertionSort(arr){ varlen=arr.length; //JavaScript需要声明变量先 varpreIndex,current; for(vari=1;i<len;i ){ preIndex=i-1; current=arr[i]; while(preIndex>=0&&arr[preIndex]>current){ arr[preIndex 1]=arr[preIndex]; preIndex--; } arr[preIndex 1]=current; } returnarr; }

对于不同的查找插入点方法(从头到尾、从尾到头),元素的比较次数是有区别的。但对于一个给定的初始序列,移动操作的次数总是固定的,就等于逆序度。

在插入排序中,对于值相同的元素,我们可以选择将后面出现的元素,插入到前面出现元素的后面,这样就可以保持原有的前后顺序不变,所以插入排序是稳定的排序算法。

对于插入排序来说,每次插入操作都相当于在数组中插入一个数据,循环执行 n 次插入操作,所以平均时间复杂度为 O(n2)。

如果输入数组已经是排好序的话,插入排序出现最佳情况,其运行时间是输入规模的一个线性函数,其时间代价是O(n)。

如果输入数组是逆序排列的,将出现最坏情况。平均情况与最坏情况一样,其时间代价是 O(n2)。

参考:https://www.runoob.com/w3cnote/insertion-sort.html

选择排序

选择排序(Selection sort)是一种简单直观的排序算法。

选择排序算法的实现思路有点类似插入排序,也分已排序区间和未排序区间。但是选择排序每次会从未排序区间中找到最小的元素,将其放到已排序区间的末尾。

它的工作原理如下。首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

选择排序:首先搜索整个列表,找到最小项的位置,如果该位置不是列表的第1项,就交换这两个位置的元素。然后从列表的第2个元素开始,重复上述过程,直到算法达到整个过程的最后一个位置,图形解释如下

插入排序法详细讲解(深入插入排序和选择排序)(2)

图片来自王争算法专栏

选择排序还有一种代码的形式是将最大值逐一选择到后面,因此遍历的时候需要逆序遍历。

defselection_sort1(nums): #思路是将最小值逐一选择到前面 n=len(nums) #第一层for表示循环选择的遍数 foriinrange(n-1): min_index=i#记录最小值的位置 #第二层for表示最小元素和后面的元素逐个比较 forjinrange(i 1,n): ifnums[j]<nums[min_index]: min_index=j ifmin_index!=i: #查找一遍后将最小元素与起始元素互换 nums[i],nums[min_index]=nums[min_index],nums[i] defselection_sort2(nums): #思路是将最大值逐一选择到后面 n=len(nums) foriinrange(n-1,0,-1): max_index=i#记录最大值的位置 forjinrange(i): ifnums[j]>nums[max_index]: max_index=j ifmax_index!=i: nums[i],nums[max_index]=nums[max_index],nums[i]

下面对Python代码改为Java代码。代码来自菜鸟教程,选择第一种思路。

下面对Python代码改为JavaScript代码。代码来自菜鸟教程。

functionselectionSort(arr){ varlen=arr.length; varminIndex,temp; for(vari=0;i<len-1;i ){ minIndex=i; for(varj=i 1;j<len;j ){ if(arr[j]<arr[minIndex]){//寻找最小的数 minIndex=j;//将最小数的索引保存 } } temp=arr[i]; arr[i]=arr[minIndex]; arr[minIndex]=temp; } returnarr; }

选择排序是一种不稳定的排序算法。选择排序每次都要找剩余未排序元素中的最小值,并和前面的元素交换位置,这样破坏了稳定性。

当出现几个值相同的时候,比如 5,8,5,2,9这样一组数据,使用选择排序算法来排序的话,第一次找到最小元素 2,与第一个 5 交换位置,那第一个 5 和中间的 5 顺序就变了,所以就不稳定了。

选择排序的主要优点与数据移动有关。如果某个元素位于正确的最终位置上,则它不会被移动。选择排序每次交换一对元素。

它们当中至少有一个将被移到其最终位置上,因此对n个元素的表进行排序总共进行至多n-1次交换。在所有的完全依靠交换。

无论数列初始状态怎样,在第 i 趟排序中选出最小关键字的记录,需做n-i次比较,因此,总的比较次数为:n(n-1)/2=O(n2)。

因此直接选择排序的平均时间复杂度为 O(n2)。直接选择排序是一个就地排序,空间复杂度为S(n)=O(1)。

参考:https://www.runoob.com/w3cnote/selection-sort.html

参考:极客时间王争算法专栏

插入排序法详细讲解(深入插入排序和选择排序)(3)

总结 来自极客时间王争算法专栏

本文已收录 GitHub,传送门~[1] ,里面更有大厂面试完整考点,欢迎 Star。

Reference

[1]

传送门~: https://github.com/MaoliRUNsen/runsenlearnpy100

,