您的位置:首页 > 编程语言 > Java开发

我在北京找工作(二):java实现算法<1> 冒泡排序+直接选择排序

2013-09-01 19:42 676 查看
工作、工作、找工作。经过1个多星期的思想斗争还是决定了找JAVA方面的工作,因为好像能比PHP的工资高点。呵呵 :-) (其实我这是笑脸,什么QQ输入法,模拟表情都没有,忒不人性化了。)

言归正传,既然决定了。就得抓紧时间回顾一下之前的知识,毕竟是我找工作而不是工作找我哈……

排序显然是笔试、面试过程中必定需要掌握的东西。

假定所有排序默认为从小到大排序


1、冒泡排序

设数组长度为N。

第一步:比较相邻的两个元素的大小,如果前面的元素大于后面的元素的值,就将这两个元素的位子进行交换。
第二步:对数组的第0个元素(0是下标)到第N-1个元素 使用第一步的方法顺序进行一次遍历后,最大的一个元素也就像大泡泡会更容易浮出水面一样,“冒”到了最上面。
第三步:对区间范围进行缩减操作,即N=N-1,如果N不为0就重复第二步操作,否则排序就已经完成。

下面按照我们所说的步骤 可以很容易的写出下面代码:

public void bubbleSort(int[] arr){
//外层for循环定义最大数组搜索区间
for(int i=0;i<arr.length;i++) {
//内层for循环定义当前一轮所需要搜索的元素区间,而且从1开始与前一个元素比较,到已经排过序的位子结束
for(int j=1;j<arr.length-i;j++) {
if(arr[j-1]>arr[j]) {
//如果前面一个元素大于当前元素,则对两个元素的位子进行交换
int temp = arr[j-1] ;
arr[j-1] = arr[j] ;
arr[j] = temp ;
}
}//end of for(j)
}//end of for(i)
}


代码中的交换两个元素,其实也是一个小小小考点,如果是写一个swap(int num1,int num2)方法,则据我所知java全都是值传递,根本就达不到预期的结果。到底还是可以传递整个数组,再传递要交换的两个下标值,可以实现写出交换的swap方法,但是未免有些绕弯的感觉,所以最好还是直接在排序function中直接交换。

另外,就算是交换两个元素的值,也还是有多种方法的!!

最常见的就是像我所写的代码这样:新建一个中间临时变量temp,用于周转,3步可以简单实现交换。

int temp = num1;
num1= num2;
num2= temp ;

还有一种方法,不需要新建中间变量,可能会比第一种稍微有点绕,不过也是很简单就能理解的。如果觉得不太好记住,就画个图吧,保证你能够很快的记住并使用上的。

num1=num1+num2;
num2=num1-num2;
num1=num1-num2;

其他的,还有很多小方法。各种各样的都能够达到这样交换的目的。自己去尝试吧~~~ (用^符号等等都行@!)

总结:再值得一提的是,冒泡排序想哪个看过代码,知道原理的人都应该知道,它的效率是非常低的。

还有2种优化的方法,第一个就是在内循环开始的时候设置一个标志位,如果某一次内循环没有进行一次交换,则说明排序完成,就不需要完整的遍历完2层for循环才结束了。

第二个就是设置一个记录器变量,记录上一次内循环时,最后进行交换的元素的下标,这个记录器变量的意义是,某一次循环的最后一次进行元素交换的位子说明,该位子之后的元素肯定是有序的。下一轮就只需要对记录器变量标识的下标的前段进行排序就行了,以此类推,应该可以减少一些不必要的操作吧。

代码就先不给了,一定要自己实现出来,明白了原理的代码才是自己的代码。千万不可故作装懂,逞一时之快!

2、直接选择排序

数组长度依然为N。

没有原理,我说个毛线!别的不说,先上原理:将数组分为有序区和无序区,在无序区中选择一个最小的元素直接放在有序区的最后。直到无序区没有一个元素或者只剩下一个元素。

第一步:初始化时,默认数组全为无序区。
第二步:在无序区中选取一个值最小的元素,将其与有序区的后一个元素的位子进行交换。交换之后,有序区就像后扩展了一个。
第三步:一直重复第二步的操作,直到无序区元素个数为0或者为1,排序完成。

小二,给客官上代码喽!!!

//直接选择排序算法
public void selectSort(int[] arr) {
int minIndex = -1 ;
for(int i=0;i<arr.length;i++) {
minIndex = i;//默认最小元素的小标为当前无需区间的第一个元素
for(int j=i+1;j<arr.length;j++) {
//在寻找过程中,只记录下标
if(arr[j]<arr[minIndex]) {
minIndex = j ;
}
}
//内循环完毕后即可进行交换,交换小标为i和minIndex的元素
int temp = arr[i] ;
arr[i] = arr[minIndex] ;
arr[minIndex] = temp ;
}
}

重新回到前面的交换两个元素的问题。代码是这样的:

num1=num1+num2;
num2=num1-num2;
num1=num1-num2;

前面 所说的第二种方法还是有些许BUG的,可能是因为代码在虚拟机里的运行顺序问题,还是会导致BUG的产生。读者们可以自己去实验一下。我们人为的原理理论是成立的!但是 代码在机器里的运行顺序不一样就会导致问题了, 这就叫同步的问题了。。。。

提供第三种交换方法:

if(num1 != num2) {
num1 ^= num2;
num2 ^= num1;
num1 ^= num2;
}
采用位运算的方法也可以实现这简单的交换问题。 有人问为什么要加个判断,当两个数不相等的时候才进行位运算。

这个熟悉位运算法则的童鞋都应该明白的!相等或相同的两个数位运算可是为0的。这不就是隐患么,而且,退一万步来说,相等了干嘛还换位子啊。神经呀!嫌运行太快?呵呵............. 0.0

今天就写到这里吧,每天都要不断的提高自己。下次整一点面试题来分析分析~~~ 顺便再讲讲其他排序算法。尤其是直接插入排序和直接选择排序的相同和不同。

记住一点:只有懂原理的程序员才是好程序员,而且也更轻松的说。不懂,就要死记硬背。何必呢~~ 你说是吧? 何必呢.......必呢..........呢..........
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐