2018-04-27
与其临渊羡鱼,不如退而结网
数组高级——多维数组
一、定义
二、初始化和内存分析
以二维数组为例
静态初始化:
int[][] arr = new int[][]{
{1,2,3},
{4,5},
{6}
};
动态初始化:
int[][] arr = new int[3][5]; //创建一个长度为3的二维数组,每一个元素(一维数组)的长度为5
三、java5对数组的新语法支持
增强for循环:foreach
foreach的语句格式:
for(数组元素类型t 数组元素变量x : 遍历对象obj){
引用了x的java语句;
}
需求:定义一个数组使用循环迭代出数组的每一个元素
代码:
1 //增强for循环:foreach
2
3 classForEachDemo4 {5 public static voidmain(String[] args)6 {7 //使用for循环迭代元素
8 int[] arr = new int[]{10,20,30,40,50};9 for(int index = 0 ; index < arr.length; index++){10 System.out.println(arr[index]);11 }12 System.out.println("------------------");13 //使用foreach循环迭代元素
14 for(intele : arr){15 System.out.println(ele);16 }17 }18 }
输出结果:
方法的可变参数 (变的是参数的个数,不是参数类型)
需求:定义一个方法来统计使用数组传递的总和
普通方法:
1 //方法的可变参数
2
3 classVarArgsDemo4 {5 public static voidmain(String[] args)6 {7 double[] ps = new double[]{1.0,2.0,3.0,4.0,5.0};8 double sum =getSum(ps);9 System.out.println(sum);10 }11 //计算商品的总和(普通方法)
12 static double getSum(double[] arr){13 double sum = 0.0;14 for(doubleprice : arr){15 sum = sum +price;16 }17 returnsum;18 }19 }
输出结果:15.0
可变参数方法:
1 //方法的可变参数
2
3 classVarArgsDemo4 {5 public static voidmain(String[] args)6 {7 double[] ps = new double[]{1.0,2.0,3.0,4.0,5.0};8 double sum =getSum(ps);9 System.out.println(sum);10 }11 //计算商品的总和(可变参数方法)12 static double getSum(double... arr){13 double sum = 0.0;14 for(doubleprice : arr){15 sum = sum +price;16 }17 returnsum;18 }19 }
输出结果:15.0
可变参数必须作为方法的最后一个参数,避免参数的歧义
推论:方法最多只有一个可变参数
四、数组算法
数组元素拷贝
学会使用API
2.排序算法
排序:安照指定顺序排列出来
升序:从小到大
降序:从大到小
排序的分类: 选择排序(直接选择排序、堆排序), 交换排序(冒泡排序、快速排序), 插入排序(直接插入排序、二分法插入排序、shell排序), 归并排序等。
冒泡排序
a)原理:比较两个相邻的元素,将值大的元素交换至右端。
b)思路:依次比较相邻的两个数,若大于则交换位置。即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后。然后比较第2个数和第3个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放前,大数放后。重复第一趟步骤,直至全部排序完成。
c)举例说明:要排序数组:int[] arr={6,3,8,2,9,1};
第一趟排序:
第一次排序:6和3比较,6大于3,交换位置: 3 6 8 2 9 1
第二次排序:6和8比较,6小于8,不交换位置:3 6 8 2 9 1
第三次排序:8和2比较,8大于2,交换位置: 3 6 2 8 9 1
第四次排序:8和9比较,8小于9,不交换位置:3 6 2 8 9 1
第五次排序:9和1比较:9大于1,交换位置: 3 6 2 8 1 9
第一趟总共进行了5次比较, 排序结果: 3 6 2 8 1 9
---------------------------------------------------------------------
第二趟排序:
第一次排序:3和6比较,3小于6,不交换位置:3 6 2 8 1 9
第二次排序:6和2比较,6大于2,交换位置: 3 2 6 8 1 9
第三次排序:6和8比较,6大于8,不交换位置:3 2 6 8 1 9
第四次排序:8和1比较,8大于1,交换位置: 3 2 6 1 8 9
第二趟总共进行了4次比较, 排序结果: 3 2 6 1 8 9
---------------------------------------------------------------------
第三趟排序:
第一次排序:3和2比较,3大于2,交换位置: 2 3 6 1 8 9
第二次排序:3和6比较,3小于6,不交换位置:2 3 6 1 8 9
第三次排序:6和1比较,6大于1,交换位置: 2 3 1 6 8 9
第二趟总共进行了3次比较, 排序结果: 2 3 1 6 8 9
---------------------------------------------------------------------
第四趟排序:
第一次排序:2和3比较,2小于3,不交换位置:2 3 1 6 8 9
第二次排序:3和1比较,3大于1,交换位置: 2 1 3 6 8 9
第二趟总共进行了2次比较, 排序结果: 2 1 3 6 8 9
---------------------------------------------------------------------
第五趟排序:
第一次排序:2和1比较,2大于1,交换位置: 1 2 3 6 8 9
第二趟总共进行了1次比较, 排序结果: 1 2 3 6 8 9
---------------------------------------------------------------------
最终结果:1 2 3 6 8 9
---------------------------------------------------------------------
由此可见:N个数字要排序完成,总共进行N-1趟排序,每i趟的排序次数为(N-i)次,所以可以用双重循环语句,外层控制循环多少趟,内层控制每一趟的循环次数。
代码实现:
/** 冒泡排序*/
public classBubbleSort {public static voidmain(String[] args) {int[] arr={6,3,8,2,9,1};
System.out.println("排序前数组为:");for(int num:arr){//for-each循环
System.out.print(num+" ");
}for(int time = 0; i < arr.length-1; i++){//外层循环控制排序趟数
for(int j = 0;j < arr.length-1-time; j++){//内层循环控制每一趟排序多少次
if(arr[j]>arr[j+1]){int temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
System.out.println();
System.out.println("排序后的数组为:");for(intnum:arr){
System.out.print(num+" ");
}
}
}
选择排序
a) 原理:每一趟从待排序的记录中选出最小的元素,顺序放在已排好序的序列最后,直到全部记录排序完毕。也就是:每一趟在n-i+1(i=1,2,…n-1)个记录中选取关键字最小的记录作为有序序列中第i个记录。基于此思想的算法主要有简单选择排序、树型选择排序和堆排序。(这里只介绍常用的简单选择排序)
b)直接选择排序算法的思想比较简单:(假设数据放在一个数组a中,且数组的长度是N)
1:从a[0]-a[N-1]中选出最小的数据,然后与a[0]交换位置
2:从a[1]-a[N-1]中选出最小的数据,然后与a[1]交换位置(第1步结束后a[0]就是N个数的最小值)
3:从a[2]-a[N-1]中选出最小的数据,然后与a[2]交换位置(第2步结束后a[1]就是N-1个数的最小值)
以此类推,N-1次排序后,待排数据就已经按照从小到大的顺序排列了。
c)举例:
//选择排序
public classSelectionSort {public static voidmain(String[] args) {int[] arr={1,3,2,45,65,33,12};
System.out.println("交换之前:");for(intnum:arr){
System.out.print(num+" ");
}//选择排序的优化
for(int i = 0; i < arr.length - 1; i++) {//做第i趟排序
int k =i;for(int j = k + 1; j < arr.length; j++){//选最小的记录
if(arr[j]
k= j; //记下目前找到的最小值所在的位置
}
}//在内层循环结束,也就是找到本轮循环的最小的数以后,再进行交换
if(i != k){ //交换a[i]和a[k]
int temp =arr[i];
arr[i]=arr[k];
arr[k]=temp;
}
}
System.out.println();
System.out.println("交换后:");for(intnum:arr){
System.out.print(num+" ");
}
}
}
3.搜索算法
从指定数组中去搜索某一个元素的索引是多少
线性搜索(从头搜到尾或从尾搜到头)
二分搜索(二分查找)
a)二分查找又称折半查找,它是一种效率较高的查找方法。
折半查找的算法思想是将数列按有序化(递增或递减)排列,查找过程中采用跳跃式方式查找,即先以有序数列的中点位置为比较对象,如果要找的元素值小 于该中点元素,则将待查序列缩小为左半部分,否则为右半部分。通过一次比较,将查找区间缩小一半。 折半查找是一种高效的查找方法。它可以明显减少比较次数,提高查找效率。但是,折半查找的先决条件是查找表中的数据元素必须有序。
b)折半查找法的优点是比较次数少,查找速度快,平均性能好;其缺点是要求待查表为有序表,且插入删除困难。因此,折半查找方法适用于不经常变动而查找频繁的有序列表。
c)二分算法步骤描述
① 首先确定整个查找区间的中间位置 mid = ( left + right )/ 2
② 用待查关键字值与中间位置的关键字值进行比较;
若相等,则查找成功
若大于,则在后(右)半个区域继续进行折半查找
若小于,则在前(左)半个区域继续进行折半查找
③ 对确定的缩小区域再按折半公式,重复上述步骤。
最后,得到结果:要么查找成功, 要么查找失败。折半查找
4.Java自带数组工具类Arrays类
查找API java.util.Arrays