闲来无事自己写的冒泡排序,感觉几分钟就可以写完的,结果不熟练Java用法花了半个多小时,最开始写的:
package testjson;
import org.junit.Test;
public class maopao {
private int i;
private int j;
@Test
public void mp() {
int temp;
int[] score = {11,8,0,4, 2, 6, 3, 7, 1,33,22,24,14,16,15 };
for(int str1 : score){
System.out.print(str1+",");
}
for (i = 0; i < score.length; i++) {
for(j = 0; j < score.length-1 ; j++){
if(score[j]<score[j+1]){
temp = score[j];
score[j] = score[j+1];
score[j+1] = temp;
//System.out.println(j);
}
}
}
System.out.println("排序完成后的结果:");
for(i=0;i<score.length;i++){
System.out.print(score[i]+",");
}
}
}
结果是对的;但是感觉有点太简单了,于是改成下边的:
package testjson;
import org.junit.Test;
public class maopao {
private int i;
private int j;
@Test
public void mp() {
int temp;
int[] score = {11,8,0,4, 2, 6, 3, 7, 1,33,22,24,14,16,15 };
for(int str1 : score){
System.out.print(str1+",");
}
for (i = 0; i < score.length-1; i++) {
for(j = i+1; j < score.length ; j++){ //这是小梅帮忙改进之后 ,我之前写的那个是i=0;循环,j=0,再全体循环是效率最差的
if(score[j]<score[i]){
temp = score[j];
score[j] = score[i];
score[i] = temp;
//System.out.println(j);
}
}
}
System.out.println("排序完成后的结果:");
for(i=0;i<score.length;i++){
System.out.print(score[i]+",");
}
}
}
立马感觉效率提高了不少,时间复杂度好像提高了,BUT,这个算法并不是冒泡排序,而是直接选择排序,它们的时间复杂度一样都是O(n^2)
以下是百度找出来的内容对理解很有帮助:
1,简单排序和直接选择排序的区别:
冒泡是从第一个数开始,往下每两个数进行比较,如果后面闭前面小,就调换位置,这样一趟下来就将最大的放到最后,如排序:8 5 2 7 第一趟结果:5 2 7 8(注意没相邻的两个数都有进行比较,符合后面比前面小的都有交换) 选择排序是将第一个数和后面的每个数进行比较,如果后面的比前面小,就两个数调换位置,最后就将最小的数放在最前面 如排序:8 5 2 7 第一趟结果 2 5 8 7(注意,它是后面的每个数和第一个数比较)
2,时间复杂度的求法:
对于这些算法 (1) for(i=1;i<=n;i++) for(j=1;j<=n;j++) s++; (2) for(i=1;i<=n;i++) for(j=i;j<=n;j++) s++; (3) for(i=1;i<=n;i++) for(j=1;j<=i;j++) s++; (4) i=1;k=0; while(i<=n-1){ k+=10*i; i++; } (5) for(i=1;i<=n;i++) for(j=1;j<=i;j++) for(k=1;k<=j;k++) x=x+1; 对应的时间复杂度为: 1.时间复杂度O(n^2) 2.时间复杂度O(n^2) 3.时间复杂度O(n^2) 4.时间复杂度O(n) 5.时间复杂度O(n^3) 一般来说,时间复杂度是总运算次数表达式中受n的变化影响最大的那一项(不含系数) 比如:一般总运算次数表达式类似于这样: a*2^n+b*n^3+c*n^2+d*n*lg(n)+e*n+f a<>0时,时间复杂度就是O(2^n); a=0,b<>0 =>O(n^3); a,b=0,c<>0 =>O(n^2)依此类推 那么,总运算次数又是如何计算出的呢? 一般来说,我们经常使用for循环,就像刚才五个题,我们就以它们为例 1.循环了n*n次,当然是O(n^2) 2.循环了(n+n-1+n-2+...+1)≈(n^2)/2,因为时间复杂度是不考虑系数的,所以也是O(n^2) 3.循环了(1+2+3+...+n)≈(n^2)/2,当然也是O(n^2) 4.循环了n-1≈n次,所以是O(n) 5.循环了(1^2+2^2+3^2+...+n^2)=n(n+1)(2n+1)/6(这个公式要记住哦)≈(n^3)/3,不考虑系数,自然是O(n^3)
看到这应该就彻底明白了另外,在时间复杂度中,log(2,n)(以2为底)与lg(n)(以10为底)是等价的,因为对数换底公式: log(a,b)=log(c,b)/log(c,a) 所以,log(2,n)=log(2,10)*lg(n),忽略掉系数,二者当然是等价的
下边来个辅助资料,也是百度来的
时间复杂度 时间频度 一个算法执行所耗费的时间,从理论上是不能算出来的,必须上机运行测试才能知道。但我们不可能也没有必要对每个算法都上机测试,只需知道哪个算法花费的时间多,哪个算法花费的时间少就可以了。并且一个算法花费的时间与算法中语句的执行次数成正比例,哪个算法中语句执行次数多,它花费时间就多。一个算法中的语句执行次数称为语句频度或时间频度。记为T(n)。 计算方法 1. 一般情况下,算法的基本操作重复执行的次数是模块n的某一个函数f(n),因此,算法的时间复杂度记做:T(n)=O(f(n)) 分析:随着模块n的增大,算法执行的时间的增长率和f(n)的增长率成正比,所以f(n)越小,算法的时间复杂度越低,算法的效率越高。 2. 在计算时间复杂度的时候,先找出算法的基本操作,然后根据相应的各语句确定它的执行次数,再找出T(n)的同数量级(它的同数量级有以下:1,Log2n ,n ,nLog2n ,n的平方,n的三次方,2的n次方,n!),找出后,f(n)=该数量级,若T(n)/f(n)求极限可得到一常数c,则时间复杂度T(n)=O(f(n)) 例:算法: for(i=1;i<=n;++i) { for(j=1;j<=n;++j) { c[ i ][ j ]=0; //该步骤属于基本操作 ,执行次数:n的平方 次 for(k=1;k<=n;++k) c[ i ][ j ]+=a[ i ][ k ]*b[ k ][ j ]; //该步骤属于基本操作 ,执行次数:n的三次方 次 } } 则有 T(n)= n的平方+n的三次方,根据上面括号里的同数量级,我们可以确定 n的三次方 为T(n)的同数量级 则有f(n)= n的三次方,然后根据T(n)/f(n)求极限可得到常数c 则该算法的 时间复杂度:T(n)=O(n^3) 注:n^3即是n的3次方。 3.在pascal中比较容易理解,容易计算的方法是:看看有几重for循环,只有一重则时间复杂度为O(n),二重则为O(n^2),依此类推,如果有二分则为O(logn),二分例如快速幂、二分查找,如果一个for循环套一个二分,那么时间复杂度则为O(nlogn)。 分类 按数量级递增排列,常见的时间复杂度有: 常数阶O(1),对数阶O(log2n),线性阶O(n), 线性对数阶O(nlog2n),平方阶O(n^2),立方阶O(n^3),..., k次方阶O(n^k), 指数阶O(2^n) 。随着问题规模n的不断增大,上述时间复杂度不断增大,算法的执行效率越低