前言
排序算法分为很多种,方法包括插入、交换、选择、合并等等。在本文中,主要归纳几种比较常见的。
文中包括定义、代码、复杂度以及稳定度的分析。
设定我们的排序目的:按照从小到大的顺序;设定排序对象:一个数组。
复杂度:按最坏情况来算。
使用语言:Java
正文
1.选择算法
①定义
选择算法,就是在每一次的遍历中选择出一个最小的数值出来排在最前面的位置。使用的方法是比较与交换。
第一轮:将所有数据进行比较,从第一位数据开始遍历,选择出最小的那一个数据,然后将最小一位数据与第一位数据的位置进行交换。第二轮:除了第一位,将剩下的数据进行比较,选出最小的那一个数据,将其与数组中的第二个数据进行位置交换。后面步骤以此类推。
举个例子:
数组 sort[7 8 9 4 5 2 1]
第一轮(选出所有数据中最小的那一个并与第一个位置的数据进行交换):1 8 9 4 5 2 7
第二轮(除了第一位,选出剩下数据中最小一位并与第二个位置的数据进行交换):1 2 9 4 5 8 7
第三轮:1 2 4 9 5 8 7
第四轮:1 2 4 5 9 8 7
第五轮:1 2 4 5 7 8 9
第六轮:1 2 4 5 7 8 9
第七轮:1 2 4 5 7 8 9
②代码
public class ChooseSort { ChooseSort(int[] array){ for(int i=0;i<array.length;i++) { int key=i; for(int j=i;j<array.length;j++) { if(array[j]<array[key]) key=j; } //当最小的数值不是原来设定的值,从进行交换 if(i!=key) { int exch=array[i]; array[i]=array[key]; array[key]=exch; } } } }
③复杂度分析
此算法中我们主要包括了进行比较和交换的过程。我们按最差的情况来进行计算。
其中,比较的次数为(数据总个数为n):第一轮所有数据进行比较,也就是需要比较(n-1)次,第二轮将除了第一个数据剩下的数据进行比较,也就是进行(n-2)次比较,一次类推。也就是总共进行比较的次数是:(n-1)+(n-2)+...+2+1,即(n^2)/2,时间复杂度为O(n^2)。而交换次数为n次,就是如果原来排列顺序为从大到小排序,则每次比较后,我们都要进行交换。
④稳定度分析
选择排序是不稳定的,在交换过程中有可能发生不稳定的情况。
举个例子:数组 sort[7(1) 8 9 4 5 7(2) 2 1]
第一轮比较之后:数组 sort[1 8 9 4 5 7(2) 2 7(1)]
原来第一个“7”就排到了第二个“7”后面了。
⑤选择算法的改进
在寻找最小值的同时,寻找最大值。不过复杂度还是一样的。
2.插入算法
①定义
可以这么理解:
现在有一堆数据,和一个空的数组,我们可以向这个数组中添加数据。
在这堆数据中取一个数据放在数组中,再取一个数据,将它放在恰当的位置,再取一个数据,将这个数据再放到恰当位置,以此类推。
举个例子:一堆数据(3 5 2 7 4 9 1 10)数组[]
第一轮:[3]
第二轮:[3 5]
第三轮:[2 3 5]
...
[1 2 3 4 5 7 9 10]
而在实际代码中,我们的操作是在一个数组内进行操作的,所以所用方法是:比较和移动。
②代码
public class InsertSort { InsertSort(int[] array){ int a; a=array.length; for(int i=1;i<a;i++) { int key; key=array[i]; int j=i-1; while(j>=0&&array[j]>key) { array[j+1]=array[j]; array[j]=key; --j; } } }
③复杂度分析
比较次数:1+2+....+(n-1),故时间复杂度为O(n^2)
移动次数:(n-1)+...+2+1,故时间复杂度为O(n^2)
④稳定度分析
插入算法是稳定的,举个例子[8 3 7(1) 6 7(2) 1 2]
当排到“7(2)”进行比较排序时,7(1)已经排好了,而稳定度和代码中比较大小相关的代码有关系,当两个数值比较相等时,不用进行交换位置。这样就能保证稳定性了。
3.冒泡算法
冒泡算法真的是我面试的时候最常见的了。确实是很基础的东西,但是一到要我回答,我老是回答不出个条理来,每次回答老是说一堆前提,我们按从小到大排,我们从最后一个数开始遍历,我们...讲得很不好。所以在此一定自己总结归纳把思路整理好来。
①定义
冒泡算法用的方法是比较和交换。
从最后一个数值开始遍历,比较相邻两个数的大小,如果后面的数小于前面的数,那就进行交换。
举个例子 [7 3 8 4 2 5 9]
第一轮 [2 7 3 8 4 5 9]
第二轮 [2 3 7 8 4 5 9]
...
可以看到,每一轮的最小的那一个数会一直跟与其相邻的数进行交换,换到最后到了第一位,跟泡泡一样不停往上冒。
感觉和选择算法有点像吼,就是每一次遍历都会把最小的数值放到了第一位,但是冒泡算法是每次比较的同时进行交换,选择算法是比较之后再进行交换。
②代码
public class bubbleSort { bubbleSort(int[] array){ int n=array.length; int head=0; while(head<(n-1)) { for(int i=n-1;i>head;i--) { if(array[i]<array[i-1]) {int key=array[i-1];array[i-1]=array[i];array[i]=key;} } ++head; } } }
③复杂度分析
比较次数:(n-1)+(n-2)+...+1,复杂度O(n^2)
交换次数:(n-1)+(n-2)+...+1,复杂度O(n^2)
④稳定度分析
冒泡算法也是稳定的,因为只有后面的数大于前面的数的时候,才进行交换。
**鸡尾酒算法
在查阅资料的时候,才发现有这么一种算法,名字还蛮好听的。
不过这不是一种新的算法,这是冒泡算法的改进,也就是双向的冒泡算法。
好啦,就到这啦,明天继续hiahia~~