1、简单的冒泡排序
1 //冒泡算法一共两种 2 // -----冒泡算法(1) 3 int a[]={23,69,4,58,1,20}; 4 for (int i = 0; i < a.length-1; i++) { 5 for (int j = i+1; j < a.length; j++) { 6 if(a[i]>a[j]){ 7 a[i]=a[i]+a[j]; 8 a[j]=a[i]-a[j]; 9 a[i]=a[i]-a[j]; 10 } 11 } 12 } 13 for (int i = 0; i < a.length; i++) { 14 System.out.println(a[i]); 15 } 16 // -----冒泡算法(2) 17 int b[]={23,69,4,58,1,20}; 18 for (int i = 0; i < b.length-1; i++) { 19 for (int j = b.length-1; j>i; j--) { 20 if(a[j-1]>a[j]){ 21 a[j]=a[j]+a[j-1]; 22 a[j-1]=a[j]-a[j-1]; 23 a[j]=a[j]-a[j-1]; 24 } 25 } 26 } 27 System.out.println("-----------2----------"); 28 for (int i = 0; i < b.length; i++) { 29 System.out.println(a[i]); 30 } 31
2、对冒泡算法的小小优化
1 //冒泡算法的改进 2 //利用flag来,主要是解决如果出现排序交换多次后出现排序好后,无需再进行检测排序 3 int c[]={23,69,4,58,1,20}; 4 boolean flag=true; 5 for (int i = 0; (i < (c.length-1)) && flag; i++) { 6 flag=false; 7 for (int j = c.length-1; j>i ; j--) { 8 if(c[j-1]>c[j]){ 9 c[j]=c[j]+c[j-1]; 10 c[j-1]=c[j]-c[j-1]; 11 c[j]=c[j]-c[j-1]; 12 flag=true; 13 } 14 } 15 } 16 17 for (int i = 0; i < c.length; i++) { 18 System.out.println(c[i]); 19 }
3、选择排序算法,算是比较好的算法了,主要是减少交换次数
思想: 一开始先把数组中最小数值的下标找出来,如果这个下标不是第一个数的下标,才在最后交换,不然不交换
下一次就是从第二个位置到最后一个位置的数组中进行选择最小值,之后记录下来,如果不是第二个数,才交换,不然不交换
以此类推!
1 //-----选择排序-----算是比较好的算法 2 int d[]={23,69,4,58,1,20}; 3 int min; 4 for (int i = 0; i < d.length-1; i++) { 5 min=i; 6 for (int j = i+1; j < d.length; j++) { 7 if(d[min]>d[j]){ 8 min=j; 9 } 10 } 11 if(min!=i){ 12 d[min]=d[min]+d[i]; 13 d[i]=d[min]-d[i]; 14 d[min]=d[min]-d[i]; 15 } 16 } 17 18 for (int i = 0; i < d.length; i++) { 19 System.out.println(d[i]); 20 }
4、插入排序算法
插入排序的主要思想:将一组无序数分成两个区,一个为有序区,另一个为无序区。从无序区中每次抽取一个数插入到有序中合适的位置。直至所有数全部有序
演示:(从小到大)
原始数列: 5 2 4 8 6
将数列分为有序区和无序区: 5 为有序区(红色), 2 4 8 6 为无序区(绿色)
即 5 2 4 8 6
开始:
每一次都由无序区中从左至右逐个抽取并放置到有序区的合适位置
首先抽取2
第一次插入结果为: 2 5 4 8 6 (2由于比5小,当然插入到其前面的位置上)
继续抽取4
第二次插入结果为:2 4 5 8 6 (4比5小,但比2大,就插入到其两者之间)
继续抽取8
第三次插入结果为:2 4 5 8 6 (8比5大,所以不用移动,从这里可以看出,无序区的数插入有序中的比较条件就是与有序区最尾的数进行比较即可)
继续抽取6
第四次插入结果为:2 4 5 6 8 (到这里,整个数列已经是一个有序的数列)
注意:插入数据的时候,位于插入数据右侧的数都需要向后移动一位,因为这样才能有位置进行插入。属于这种情况的数列是存储在一段连续的内存空间(例如数组)。但如果不是一段连续的内存空间(例如链表)就会简单和高效些。
按照这种排序思路,可以明显看出这个排序的好处就是增量排序
什么是增量排序?其实很简单:向一个已有序的数列中添加元素,并且要保证添加元素后的数列仍保持其原来的有序性
可见,这种插入排序算法在添加元素的时候,最多只需要遍历一次即可。即O(n) 注意:这个不是最坏情况和平均情况的时间复杂度
插入排序最坏情况和平均情况的时间复杂度都是:O(n²)
1 /* 2 * 插入排序算法,使用场景,在于如果数列中有一部分已经排好序的 3 * 那么所用时间就会减少很多,如果数列有元素打散得很厉害, 4 * 那么建议使用 选择排序 , 减少交换次数! 5 */ 6 int [] f ={2,4,22,33,5,45,23};//我设置比较打散! 7 8 for (int i = 1; i < f.length; i++) { 9 for (int j = i; j>0 ; j--) {//这样做是从后往前进行比较和交换,所以对于比较打散的数组排序不利! 10 if(f[j-1]>f[j]){//从小到大排序 11 //交换 12 f[j]=f[j]+f[j-1]; 13 f[j-1]=f[j]-f[j-1]; 14 f[j]=f[j]-f[j-1]; 15 }else{ 16 //这个数是比有序数列中最大的大的话,就不用交换了!节省时间就在这里,这也是为何对于比较打散的数组排序不利! 17 break; 18 } 19 } 20 }