一、冒泡排序
1、介绍:
冒泡排序和选择排序的思想是蛮力法,冒泡,顾名思义,每次选择后面一个元素(最大或者最小)冒上来,从而得到一个有序的序列。比如对于序列:10、8、5、7、3、1的冒泡第一趟演示图示如图所示
2、代码实现(Java):
/**
* 冒泡排序
*@author DR
* @param args
* @return
*2014年1月14日
*/
public int[] bubbleSort(int...args){ //这里使用JDK提供的可变参数作可变数组
for(int i=0;i<args.length-1;i++){
for(int j=args.length-1;j>i;j--){ //这里从右向左扫描
if(args[j]<args[j-1]){
int temp = args[j];
args[j] = args[j-1];
args[j-1] = temp;
}
}
}
return args;
}
程序中有两个for循环,在args[i]左边的元素是已经沉底的,排序好了的元素;j作为一个扫描指针,从右向左扫描,如果j-1位置的大于j位置的元素,则交换它们,直到把最小的那个元素沉底到i+1位置。
3、代码优化
/**
* 冒泡排序的优化算法
*@author DR
* @param args
* @return
*2014年1月14日
*/
public int[] bubbleSort2(int...args){
boolean flag = true; //是否交换标志位
for(int i=0;i<args.length-1&&flag;i++){
flag = false;
for(int j=args.length-1;j>i;j--){
if(args[j]<args[j-1]){
int temp = args[j];
args[j] = args[j-1];
args[j-1] = temp;
flag = true; //发生交换则让标志位为真
}
}
}
return args;
}
测试一下,对于一个大部分有序的序列,优化后的算法比之前的算法要节省很多步。
测试方法:
public static void main(String[] args) {
TestBubbleSort t = new TestBubbleSort();
//int[] array = t.bubbleSort(1,3,4,7,9,5,23,2);
int[] array = t.bubbleSort2(1,3,4,7,9,5,23,2);
for(int i:array){
System.out.println(i);
}
}
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
二、选择排序
下面以一个整形数组作为待排序列表,描述上述的选择排序过程:
待排序整形数组:6、4、9、1、4、12
第一次:扫描整个列表,找到最小的元素,也就是1,过程如下
扫描第一个元素6,最小元素6,最小元素索引0
扫描第一个元素4,与最小元素6比较,6不小于4,所以,最小元素4,最小元素索引1
扫描第一个元素9,与最小元素4比较,9不小于4,所以,最小元素4,最小元素索引1
扫描第一个元素1,与最小元素4比较,1小于4, 所以,最小元素1,最小元素索引3
扫描第一个元素4,与最小元素1比较,4不小于1, 所以,最小元素1,最小元素索引3
扫描第一个元素12,与最小元素1比较,12不小于1, 所以,最小元素1,最小元素索引3
扫描结束,最小元素1,最小元素索引3,将1与6交换,得到序列:1、4、9、6、4、12
第二次:扫描第2~6位的元素,也就是4、9、6、4、12
扫描第一个元素4,最小元素4,最小元素索引1
扫描第一个元素9,与最小元素4比较,9不小于4,所以,最小元素4,最小元素索引1
扫描第一个元素6,与最小元素4比较,6不小于4,所以,最小元素4,最小元素索引1
扫描第一个元素4,与最小元素4比较,4不小于4, 所以,最小元素4,最小元素索引1
扫描第一个元素12,与最小元素4比较,12不小于4, 所以,最小元素4,最小元素索引1
扫描结束,最小元素4,最小元素索引1,将4与4交换,得到序列:1、4、9、6、4、12
第三次:以此类推,得到1、4、4、6、9、12
第四次:以此类推,得到1、4、4、6、9、12
第五次:以此类推,得到1、4、4、6、9、12
全部扫描结束,排序完成,得到非递减序列:1、4、4、6、9、12
2、代码实现(Java):
/**
* 选择排序的Java代码实现
*@author DR
* @param args
* @return
*2014年1月14日
*/
public int[] selectSort(int...args){ //这里使用JDK提供的可变参数作可变数组
for(int i=0;i<args.length-1;i++){
for(int j=i+1;j<args.length;j++){
if(args[i]>args[j]){
int temp = args[i];
args[i] = args [j];
args[j] = temp;
}
}
}
return args;
}
程序中有两个for循环,j=i+1作为扫描指针,若i位置的元素大于j位置的元素,则把两者交换,并使j+1,这样当 j 扫描到末尾结束后,i位置上的元素就是本次扫描中最小的那一个,然后i+1。最终,可得一个非递减的序列。但是我们发现上述代码做了很多次元素的交换,而交换元素又是费时费力的,所以改良后的代码是在扫描的过程中不急于做元素的交换,而是用一个变量记下最小元素的位置,更新一个变量的值比做一次元素交换要容易的做,最后将最小元素与i位置的元素交换,这样整个过程我们至多做一次交换。
3、优化后的选择排序算法的Java代码实现:
/**
* 优化后的选择排序Java代码实现
*@author DR
* @param args
* @return
*2014年1月14日
*/
public int[] selectSort2(int...args){
int k,num = 0;
for(int i=0;i<args.length-1;i++){
k = i; //设置k变量的目的是为了减少交换的次数,把交换改为对k赋值,每趟循环至多交换1次
for(int j=i;j<args.length;j++){
if(args[k]>args[j]){
k = j;
}
}
if(k != i){
int temp = args[k];
args[k] = args[i];
args[i] = temp;
}
}
return args;
}
测试代码:虽然优化后的代码和之前的代码复杂度一样,但是对于一个大量数据的排序其运行时间比之前的代码要少很多。
public static void main(String[] args) {
TestSelectSort ts = new TestSelectSort();
//TestSelectSort ts = new TestSelectSort2();
int[] array = ts.selectSort(5,3,8,2,15,2,11,0);
for(int i:array){
System.out.println(i);
}
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
三、插入排序
1、介绍:
对于一个含有n个元素的序列,对它的插入排序的过程是这样的,我们区第一个元素,它一定是有序的(因为只有一个元素),将第二个元素插入到这个有序序列中去(也就是和第一个元素比较,然后插入),再将第3个元素插入到前面;两个元素组成的有序序列中去,.......,最后将第n个元素插入到由前面(n-1)个元素组成的有序序列中去,可以发现这是减治思想的一种体现。
2、插入排序代码实现:
/**
* 插入排序的Java代码实现
*@author DR
* @param args
* @return
*2014年1月14日
*/
public int[] insertSort(int...args){ //这里使用JDK提供的可变参数作可变数组
for(int i=1;i<args.length;i++){
if(args[i-1]>args[i]){
int key = args[i];
int j=i-1;
for(;j>=0 && args[j]>key;j--){
args[j+1] = args[j];
}
args[j+1] = key;
}
}
return args;
}
注意一点:事实上,插入排序一共有三种:①我们可以从左向右扫描序列,找到合适的位置插入; ②我们可以从右向左扫描序列,找到合适的位置插入;③对于有序序列我们可以使用折半查找到合适的位置插入。 这里由于不知道序列是否有序,我们采用第②中插入法,事实上,很多像这种对数组的排序都采用第②中方法,因为它可以在比较查找的过程中移动腾空位置,比第一种要少做一次循环,这一点可以去验证一下。总结:之所以是简单排序,因为这三种排序的算法相对简单,最好、最坏、平均情况的时间复杂度都是O(n²)。