查找
- 顺序查找法:逐个比较,直到找到为止
- 二分查找法/折半查找法:重视将要查找的数和查找范围中心位置的数进行比较,如果结果只有三种:相等,大于和小于。如果大于,说明应该在后半段查找,否则应该在前半段查找,但是二分查找有一个前提是,数据必须是有序的。
- 查找最大/最小值
- 冒泡排序:相邻的数两两比较,不符合顺序要求则对调,一趟下来可以安排好一个数,重复n-1趟即可将n个数排好序。
- 选择排序法:找出最大数的位置,将该位置的数和最后位置的数对调,重复n-1次即可。
顺序查找法:
案例:
public class Demo {
public static void main(String[] args) {
int[]a={11,33,4,2,5,66};
System.out.println("请输入要找的数:");
Scanner sc = new Scanner(System.in);
int v = sc.nextInt();
int index = -1;
for (int i=0;i<a.length;i++){
if (a[i]==v){
index=i;
break;
}
}
if (-1==index){
System.out.println("不存在");
}else {
System.out.printf("%d在%d号位置",v,index);
}
}
}
结果:
心得体会:
- 顺序查找就是一个遍历加比较,这个算法最简单,但是比较次数较多,平均比较次数是n/2,基于数据量成正比
- 和利时用空行分割不同的逻辑块,使得程序的结构更加清晰,比如此例中划分为数据初始化,接收输入,查找,输出结果四个逻辑块。
- 不在查找的代码中输出结果,还是为了程序结构的清晰和合理,一般一个逻辑块就做一件事,不要糅杂在一起。
- 判断相等时,把常量放在前面,避免混用==和=,照成逻辑错误。
折半查找法/二分查找发
案例:
public class Demo {
public static void main(String[] args) {
int[]a = {1,2,3,4,5,6,7,8,9,10};
System.out.println("请输入要找的数:");
Scanner sc = new Scanner(System.in);
int v = sc.nextInt();
int left = 0;//查找范围的起始下标
int right=a.length-1;//查找范围的终止下标
int index = -1;//找到的位置
while (left<=right){
int mid = (left+right)/2;
if (v==a[mid]){
index = mid;
break;
}else if (v>a[mid]){
left=mid+1;
}else {
right = mid-1;
}
}
if (-1==index){
System.out.println("不存在");
}else {
System.out.printf("%d在%d号位置",v,index);
}
}
}
结果:
心得体会:
- 顺序查找算法简单,代码也简单,而折半查找复杂
- 折半查找的小于远高于顺序查找,它最坏的情况需要找log2^n次。
- 折半查找的高效有前提;有序,为了保证这一点有可能付出的代价远高于查找本身。
查找最大/最小值
案例:
public class Demo {
public static void main(String[] args) {
int[]a={1111,22,33,3444,55,63,77};
int max = a[0];
int min = a[0];
for (int i=1;i<a.length;i++){
if (a[i]>max){
max=a[i];
}
}
for (int i=1;i<a.length;i++){
if (a[i]<min){
min = a[i];
}
}
System.out.printf("最大值=%d\n",max);
System.out.printf("最小值=%d",min);
}
}
结果:
冒泡排序:
案例:
public class Demo {
public static void main(String[] args) {
int[]a={1,34,5,67,4,2,7,3};
for (int b:a) {
System.out.printf("%4d",b);
}
System.out.println();
for (int i=1;i<a.length-1;i++){
for (int j=0;j<a.length-i;j++){
if (a[j]>a[j+1]){
int t = a[j];
a[j] = a[j+1];
a[j+1] = t;
}
}
}
for (int x:a) {
System.out.printf("%4d",x);
}
System.out.println();
}
}
结果:
心得体会:
- 对于复杂问题,可以想办法降低难度,比如此案例可以先写出第一趟冒泡的程序,然后第二趟......,最后总结出规律,将其套在一个循环中即可解决。
- 两两比较时的对调很多时候时没有必要的,所以该方法效率不高。
- 该案例中,输出数组的代码写了两次,其实是有办法只写一次的,那就是函数。
选择排序法:
案例:
public static void main(String[] args) {
int []a = {2,3,5,6,88,4,11,9};
for (int x:a){//遍历出数组
System.out.printf("%4d",x);
}
System.out.println("");
for (int n =1;n<=a.length-1;n++) {
//(1)找最大数的位置
int max_index = 0;
for (int i = 1;i<=a.length-n;i++){
if (a[i]>a[max_index]){
max_index = i;
}
}
//(2)对调
int t = a[max_index];
a[max_index] = a[a.length-n];
a[a.length-n] = t;
}
for (int x:a){//遍历出数组
System.out.printf("%4d",x);
}
}
结果:
心得体会:
- 每一趟选择包含两个动作:找最大位置和对调,这两个功能之前都已经解决了,所以有积累的话,很多问题会越来越简单,反之就会越来越复杂。
- 选择排序法的效率要高于冒泡排序,因为一趟选择只有一次交换操作。
二维数组:
定义:
- double a[][] = new double[3][6];
- int b[][] ={{22,33,44},{33,44,55},{33,55,66}};
案例:求5个班级哪个最优秀?
public class Demo {
public static void main(String[] args) {
int[]arrs=new int [5];
int num=0;
int arr[][]={{12,34,76,45,88,36,87},{5,67,89,36,89,65,98},
{34,67,65,87,90,77,89,87},{67,87,56,98,76,64,34,77,},
{56,76,87,90,65,98,55,44}};
for (int n=0;n<arr.length;n++){
int sum=0;
for (int i=0;i<arr[n].length;i++){
sum +=arr[n][i];
}
int avg = sum/arr[n].length;
arrs[n] = avg;
}
for (int k=0;k<arrs.length;k++){
System.out.println((k+1)+"班的平均分"+arrs[k]);
}
int max = arrs[0];
for (int i=1;i<arrs.length;i++){
if (arrs[i]>max){
max = arrs[i];
num = i;
}
}
System.out.printf("最好的是%d班",(num+1));
}
}
结果: