整理了一下Java排序算法,成果如下:
一、冒泡法排序:
分析:
在第一趟:首先比较第1个和第2个数,将小数放前,大数放后。然后比较第2个数和第3个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放前,大数放后。至此第一趟结束,将最大的数放到了最后。
在第二趟:仍从第一对数开始比较(因为可能由于第2个数和第3个数的交换,使得第1个数不再小于第2个数),将小数放前,大数放后,一直比较到倒数第二个数(倒数第一的位置上已经是最大的),第二趟结束,在倒数第二的位置上得到一个新的最大数(其实在整个数列中是第二大的数)。
如此下去,重复以上过程,直至最终完成排序。
public class BubbleSort { public static void main(String args[]){ int array[]={4,3,2,1}; System.out.println("排序前:"); for(int i=0;i<array.length;i++) System.out.print(array[i]+" "); System.out.println(); System.out.println("开始排序:"); bubbleSort(array); } public static void bubbleSort(int array[]){ for(int i=1;i<array.length;i++) for(int j=0;j<array.length-i;j++){ if(array[j]>array[j+1]){ int t=array[j]; array[j]=array[j+1]; array[j+1]=t; } for(int x=0;x<array.length;x++) System.out.print(array[x]+" "); System.out.println(); } } }
输出结果如下:
排序前: 4 3 2 1 开始排序: 3 4 2 1 3 2 4 1 3 2 1 4 2 3 1 4 2 1 3 4 1 2 3 4 |
二、选择排序:
分析:每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。 选择排序是不稳定的排序方法。
代码如下:
public class ChoiceSort { public static void _choiceSort(Integer[] a) { if (a == null || a.length <= 0) { return; } for (int i = 0; i < a.length; i++) { int min = i; /* 将当前下标定义为最小值下标 */ for (int j = i + 1; j < a.length; j++) { if (a[min] > a[j]) { /* 如果有小于当前最小值的关键字 */ min = j; /* 将此关键字的下标赋值给min */ } } if (i != min) {/* 若min不等于i,说明找到最小值,交换 */ int tmp = a[min]; a[min] = a[i]; a[i] = tmp; } } } } public static void main(String[] args) { // TODO Auto-generated method stub Integer[] list={49,38,65,97,76,13,27,14,10}; //快速排序 /* QuicSort qs=new QuicSort(); qs.quick(list);*/ //冒泡排序 /* BubbleSort bs=new BubbleSort(); bs.bubble(list);*/ //选择排序 ChoiceSort._choiceSort(list); for(int i=0;i<list.length;i++){ System.out.print(list[i]+" "); } System.out.println(); }
打印结果:
三、插入排序:
分析:
插入排序算法是一个对少量元素进行排序的有效算法。插入排序的工作原理与打牌时整理手中的牌的做法类似,开始摸牌时,我们的左手是空的,接着一次从桌上摸起一张牌,并将它插入到左手的正确位置。为了找到这张牌的正确位置,要将它与手中已有的牌从右到左进行比较,无论什么时候手中的牌都是排序好的。
public void insertSort(int a[]){ int length=a.length; //数组长度 int j; //当前值的位置 int i; //指向j前的位置 int key; //当前要进行插入排序的值 //从数组的第二个位置开始遍历值 for(j=1;j<length;j++){ key=a[j]; i=j-1; //a[i]比当前值大时,a[i]后移一位,空出i的位置,好让下一次循环的值后移 while(i>=0 && a[i]>key){ a[i+1]=a[i]; //将a[i]值后移 i--; //i前移 }//跳出循环(找到要插入的中间位置或已遍历到0下标) a[i+1]=key; //将当前值插入 } }
如图:
理解:
insertSort在数组A={5,2,4,6,1,3}上的处理过程,数组的下标出现在巨型的上方,黑色框的值即为key=a[j]。
a[i]即为a[j]左边的值,每次循环key与a[i]进行比较,如果key<a[i],则a[i]移到 i+1处,同时i--向左移动,直到找到a[i]<=key或者i<0,此时将 key插入到a[i+1]处。
问题1:a[i]第一次进行右移时覆盖了a[i+1]值,是否造成了数据丢失?
答:不会造成数据丢失,应为第一次右移前的i+1=j,此时a[j]的值存在了key里了。每次右移都为下一次右移或插入留出了位置,这就是插入排序的关键点所在。
四、快速排序
分析:
①以第一个关键字 K 1 为控制字,将 [K 1 ,K 2 ,…,K n ] 分成两个子区,使左区所有关键字小于等于 K 1 ,右区所有关键字大于等于 K 1 ,最后控制字居两个子区中间的适当位置。在子区内数据尚处于无序状态。
②把左区作为一个整体,用①的步骤进行处理,右区进行相同的处理。(即递归)
③重复第①、②步,直到左区处理完毕。
代码如下:
public int getMiddle(Integer[] list, int low, int high) { int tmp = list[low]; //数组的第一个作为中轴 while (low < high) { while (low < high && list[high] > tmp) { high--; } list[low] = list[high]; //比中轴小的记录移到低端 while (low < high && list[low] < tmp) { low++; } list[high] = list[low]; //比中轴大的记录移到高端 } list[low] = tmp; //中轴记录到尾 return low; //返回中轴的位置 }
递归形式的分治排序算法:
public void quick(Integer[] str) { if (str.length > 0) { //查看数组是否为空 _quickSort(str, 0, str.length - 1); } } public void quick(Integer[] str) { if (str.length > 0) { //查看数组是否为空 _quickSort(str, 0, str.length - 1); } }
编写测试方法:
public class TestMain { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Integer[] list={34,3,53,2,23,7,14,10}; QuicSort qs=new QuicSort(); qs.quick(list); for(int i=0;i<list.length;i++){ System.out.print(list[i]+" "); } System.out.println(); } }
打印结果:
2 3 7 10 14 23 34 53
Shell排序没怎么留意。以上够用了。