1、稳定排序:如果a原本在b的前面,且a==b,排序之后a仍然在b的前面,则为稳定排序。
2、非稳定排序:如果a原本在b的前面,且a==b,排序之后a可能不在b的前面,则为非稳定排序。
3、原地排序:原地排序就是指在排序过程中不申请多余的存储空间,只利用原来存储待排数据的存储空间进行比较和交换的数据排序。
4、非原地排序:需要利用额外的数组来辅助排序。
6、空间复杂度:运行完一个算法所需的内存大小。
为了方便大家查找,我这里弄一个伪目录。
过程简单描述:首先,找到数组中最小的那个元素,其次,将它和数组的第一个元素交换位置(如果第一个元素就是最小元素那么它就和自己交换)。其次,在剩下的元素中找到最小的元素,将它与数组的第二个元素交换位置。如此往复,直到将整个数组排序。这种方法我们称之为选择排序。
为方便理解我还准备了动图:
代码如下:
我们在玩打牌的时候,你是怎么整理那些牌的呢?一种简单的方法就是一张一张的来,将每一张牌插入到其他已经有序的牌中的适当位置。当我们给无序数组做排序的时候,为了要插入元素,我们需要腾出空间,将其余所有元素在插入之前都向右移动一位,这种算法我们称之为插入排序。
过程简单描述:
1、从数组第2个元素开始抽取元素。
2、把它与左边第一个元素比较,如果左边第一个元素比它大,则继续与左边第二个元素比较下去,直到遇到不比它大的元素,然后插到这个元素的右边。
3、继续选取第3,4,….n个元素,重复步骤2,选择适当的位置插入。
1、把第一个元素与第二个元素比较,如果第一个比第二个大,则交换他们的位置。接着继续比较第二个与第三个元素,如果第二个比第三个大,则交换他们的位置….
我们对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样一趟比较交换下来之后,排在最右的元素就会是最大的数。
除去最右的元素,我们对剩余的元素做同样的工作,如此重复下去,直到排序完成。
代码如下
优化一下冒泡排序的算法
假如从开始的第一对到结尾的最后一对,相邻的元素之间都没有发生交换的操作,这意味着右边的元素总是大于等于左边的元素,此时的数组已经是有序的了,我们无需再对剩余的元素重复比较下去了。
希尔排序就是为了加快速度简单地改进了插入排序,交换不相邻的元素以对数组的局部进行排序。
希尔排序的思想是采用插入排序的方法,先让数组中任意间隔为h的元素有序,刚开始h的大小可以是h=n/2,接着让h=n/4,让h一直缩小,当h=1时,也就是此时数组中任意间隔为1的元素有序,此时的数组就是有序的了。
为方便理解我还准备了图片:
1publicclassShellSort{2publicstaticint[]shellSort(intarr[]){3if(arr==null||arr.length<2)returnarr;4intn=arr.length;5//对每组间隔为h的分组进行排序,刚开始h=n/2;6for(inth=n/2;h>0;h/=2){7//对各个局部分组进行插入排序8for(inti=h;i 将一个大的无序数组有序,我们可以把大的数组分成两个,然后对这两个数组分别进行排序,之后在把这两个数组合并成一个有序的数组。由于两个小的数组都是有序的,所以在合并的时候是很快的。 通过递归的方式将大的数组一直分割,直到数组的大小为1,此时只有一个元素,那么该数组就是有序的了,之后再把两个数组大小为1的合并成一个大小为2的,再把两个大小为2的合并成4的…..直到全部小的数组合并起来。 然而面试官要你写个非递归式的归并排序怎么办?别怕,我这还撸了个非递归式的归并排序,代码如下: 1publicclassMergeSort{2//非递归式的归并排序3publicstaticint[]mergeSort(int[]arr){4intn=arr.length;5//子数组的大小分别为1,2,4,8...6//刚开始合并的数组大小是1,接着是2,接着4....7for(inti=1;i 从中轴元素那里开始把大的数组切割成两个小的数组(两个数组都不包含中轴元素),接着我们通过递归的方式,让中轴元素左边的数组和右边的数组也重复同样的操作,直到数组的大小为1,此时每个元素都处于有序的位置。 堆的特点就是堆顶的元素是一个最值,大顶堆的堆顶是最大值,小顶堆则是最小值。 堆排序就是把堆顶的元素与最后一个元素交换,交换之后破坏了堆的特性,我们再把堆中剩余的元素再次构成一个大顶堆,然后再把堆顶元素与最后第二个元素交换….如此往复下去,等到剩余的元素只有一个的时候,此时的数组就是有序的了。 计数排序是一种适合于最大值和最小值的差值不是不是很大的排序。 基本思想:就是把数组元素作为数组的下标,然后用一个临时数组统计该元素出现的次数,例如temp[i]=m,表示元素i一共出现了m次。最后再把临时数组统计的数据从小到大汇总起来,此时汇总起来是数据是有序的。 注:K表示临时数组的大小,下同 优化一下 上面的代码中,我们是根据max的大小来创建对应大小的数组,假如原数组只有10个元素,并且最小值为min=10000,最大值为max=10005,那我们创建10005+1大小的数组不是很吃亏,最大值与最小值的差值为5,所以我们创建大小为6的临时数组就可以了。 也就是说,我们创建的临时数组大小(max-min+1)就可以了,然后在把min作为偏移量。优化之后的代码如下所示: 1publicclassCounting{2publicstaticint[]sort(int[]arr){3if(arr==null||arr.length<2)returnarr;45intn=arr.length;6intmin=arr[0];7intmax=arr[0];8//寻找数组的最大值与最小值9for(inti=1;i 之后每个桶里面的数据就是有序的了,我们在进行合并汇总。 注:k表示桶的个数,下同 基数排序的排序思路是这样的:先以个位数的大小来对数据进行排序,接着以十位数的大小来多数进行排序,接着以百位数的大小…… 排到最后,就是一组有序的元素了。不过,他在以某位数进行排序的时候,是用“桶”来排序的。 由于某位数(个位/十位….,不是一整个数)的大小范围为0-9,所以我们需要10个桶,然后把具有相同数值的数放进同一个桶里,之后再把桶里的数按照0号桶到9号桶的顺序取出来,这样一趟下来,按照某位数的排序就完成了 用一张图汇总了10大排序算法的性质 如果你是复习/学习十大排序算法,一定要自己不看示例代码手动实现一遍,一定要自己不看示例代码手动实现一遍,一定要自己不看示例代码手动实现一遍。