1.冒泡排序
这里讲得是顺序排序,逆序做法类似,大差不差。
冒泡排序的本质就是,从索引号相邻的两个元素(i,i+1)开始比较,如果i比i+1大,那么互换位置。
冒泡排序的特点:每比较一轮,就有一个元素被确定在最终的位置上。也就是说,每一轮的比较次数都比前一轮要少1次。
好了,代码上见吧!!!
static void maopao_1(int[] arr){
//冒泡排序
//记录比较的轮数
int count = 0;
for (int i = 0; i < arr.length-1 ; i++) {
for (int j = 0 ; j < arr.length -i-1 ; j++){
if(arr[j] > arr[j+1]){
int temp = 0;
temp = arr[j+1];
arr[j+1] = arr[j];
arr[j] = temp;
}
count++;
}
}
System.out.println("总共比较了"+count+"轮");
}
-----------------------
总共比较了171轮
2 3 4 5 6 7 7 22 34 34 43 44 45 45 55 65 66 67 78
这里引用一张大神的图片
这里要特别说明三点:
1.同前面说的一样,每轮的比较都要比前一轮少1次,所以内层循环的总次数为 arr.length -i-1 即为元素总个数减去i
2.每轮比较都是从第一个元素开始,而且比较的两个元素都有内层循环变量控制。
3.优化。
说到优化,见过一个国内大厂的面试问题,就是冒泡排序怎么优化。
个人觉得,冒泡排序实在是太过基础,优化只能出现在特殊数据排序的情况。如:9,1,2,3,5这样的例子。可见,只需比较一轮即可确定顺序,一轮之后算法是不会停止的,那么我们怎么解决这个问题。我想到的办法是,利用一个布尔变量记录一下,如果在某轮比较中没有元素改变位置,那么就认为排序已经成功,后面的轮数就无需进行。
优化一:
改进代码如下:
static void maopao_2(int[] arr){
//冒泡排序
//记录比较轮数
int count = 0;
for (int i = 0; i < arr.length-1 ; i++) {
//记录元素位置是否改变
boolean flag = false;
for (int j = 0 ; j < arr.length -i-1 ; j++){
if(arr[j] > arr[j+1]){
int temp = 0;
flag = true;
temp = arr[j+1];
arr[j+1] = arr[j];
arr[j] = temp;
}
count++;
}
if(flag == false){
System.out.println("总共比较了"+count+"轮");
return;
}
}
System.out.println("总共比较了"+count+"轮");
}
------------------------------------------------------------
总共比较了126轮
2 3 4 5 6 7 7 22 34 34 43 44 45 45 55 65 66 67 78
优化二:
通过前面分析可知,再每一轮比较结束之后,必将确定一个元素的最终位置。那么我们可以通过一个变量来记录上一次最后一次发生换位的位置,当下一轮比较的时候,比较到该位置即可。
代码如下:
static void maopao_3(int[] arr){
//冒泡排序
//记录比较轮数
int count = 0;
int i = arr.length - 1 ;
while(i > 0){
int pos = 0;
for(int j = 0 ; j < i ; j++){
if (arr[j] > arr[j+1]) {
count++;
pos = j;
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
i = pos;
}
System.out.println("总共交换了"+count+"次");
}
---------------------------------------
总共交换了55次
2 3 4 5 6 7 7 22 34 34 43 44 45 45 55 65 66 67 78
这里说明一下,外层循环变成有while控制,由于每一轮比较后确定了一个元素,所以理论上来讲i的值会减1。与前面的算法其实也大差不差。
优化三:
传统冒泡排序中每一趟排序操作只能找到一个最大值或最小值,我们考虑利用在每趟排序中进行正向和反向两遍冒泡的方法一次可以得到两个最终值(最大者和最小者) , 从而使排序趟数几乎减少了一半。
代码如下:
static void maopao_4(int[] arr){
//冒泡排序
int high = arr.length - 1;
int low = 0;
int temp ;
int count = 0;
while(low < high){
//确定最大值
for (int i = low; i < high; ++i) {
if(arr[i] > arr[i+1]){
temp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
}
}
--high;
//确定最小值
for (int i = high; i > low ; --i) {
if(arr[i] < arr[i-1]){
temp = arr[i];
arr[i] = arr[i-1];
arr[i-1] = temp;
}
}
++low;
count++;
}
System.out.println("总共循环了"+count+"次");
}
--------------------------------------
总共循环了9次
2 3 4 5 6 7 7 22 34 34 43 44 45 45 55 65 66 67 78