数组的算法
1、关于数组元素的统计
(1)求累计和
(2)求平均值
(3)统计偶数的个数
(4)统计素数的个数
(5)统计xx的个数
冒泡排序:是最基础的最经典排序,所有编程人员都要学习的第一个排序算法。
但是不是说它是效率最高。
关键描述:
(1)通过相邻元素的比较,如果相邻的前后元素不符合最终要的顺序,就交换 例如:我们要实现从小到大, {4,5,2,1,6} 相邻元素, 4,5 满足先小后大,不交换 相邻元素, 5,2 不满足先小后大,交换
(2)每一轮只能确定一个元素到达正确的位置 方案一,把大的往后移动,每一轮“大”沉到“底”(本轮参与元素的最后) 方案二,把小的往前移动,每一轮“小”冒到“顶” (本轮参与元素的第一个)
详细描述:arr {4,5,2,1,6} 方案一的过程
第一轮:
第1次,arr[0]<arr[1]比较,就是4<5比较,成立,不交换
第2次,arr[1]<arr[2]比较,就是5<2比较,不成立,交换 {4,2,5,1,6}
第3次,arr[2]<arr[3]比较,就是5<1比较,不成立,交换 {4,2,1,5,6}
第4次,arr[3]<arr[4]比较,就是5<6比较,成立,不交换
第一轮结果:6到达正确位置 {4,2,1,5,6}
第二轮:
第1次,arr[0]<arr[1]比较,就是4<2比较,不成立,交换 {2,4,1,5,6}
第2次,arr[1]<arr[2]比较,就是4<1比较,不成立,交换 {2,1,4,5,6}
第3次,arr[2]<arr[3]比较,就是4<5比较,成立,不交换
第二轮结果:5到达正确位置 {2,1,4,5,6}
第三轮:
第1次,arr[0]<arr[1]比较,就是2<1比较,不成立,交换 {1,2,4,5,6}
第2次,arr[1]<arr[2]比较,就是2<4比较,成立,不交换
第三轮结果:4到达正确位置 {1,2,4,5,6}
第四轮:
第1次,arr[0]<arr[1]比较,就是1<2比较,成立,不交换
5个元素比较4轮,因为每一轮只能确定一个元素的正确位置。
如果m个元素,一共要比较m-1轮。
每一轮比较的次数递减。因为每一轮需要参与比较的元素依次减少。
public class TestBubbleSort {
public static void main(String[] args) {
int[] arr = {4,5,2,1,6};
//冒泡排序,从小到大
//外循环控制一共比较几轮
/*
arr.length是5, i=1,i<arr.length, i<5
i=1,2,3,4
*/
for(int i=1; i<arr.length; i++){
//内循环控制每一轮比较的次数
/*
本题:
当i=1,比较4次,j=0,1,2,3 j<4
arr[0]与arr[1]
arr[1]与arr[2]
arr[2]与arr[3]
arr[3]与arr[4]
arr[j]与arr[j+1]
当i=2,比较3次,j=0,1,2 j<3
arr[0]与arr[1]
arr[1]与arr[2]
arr[2]与arr[3]
当i=3,比较2次,j=0,1 j<2
arr[0]与arr[1]
arr[1]与arr[2]
当i=4,比较1次,j=0 j<1
arr[0]与arr[1]
*/
for(int j=0; j<arr.length - i; j++){
if(arr[j] > arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
//输出结果
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
}
方案二,把小的往前移动,每一轮“小”冒到“顶” (本轮参与元素的第一个)
详细描述:arr {4,5,2,1,6} 方案二的过程
第1轮:
第1次:arr[4]<arr[3]比较,6<1比较,不成立,不换
第2次:arr[3]<arr[2]比较,1<2比较,成立,交换 {4,5,1,2,6}
第3次:arr[2]<arr[1]比较,1<5比较,成立,交换 {4,1,5,2,6}
第4次:arr[1]<arr[0]比较,1<4比较,成立,交换 {1,4,5,2,6}
第一轮的结果,1到达正确位置
第2轮:
第1次:arr[4]<arr[3]比较,6<2比较,不成立,不换
第2次:arr[3]<arr[2]比较,2<5比较,成立,交换 {1,4,2,5,6}
第3次:arr[2]<arr[1]比较,2<4比较,成立,交换 {1,2,4,5,6}
第3轮:
第1次:arr[4]<arr[3]比较,6<5比较,不成立,不换
第2次:arr[3]<arr[2]比较,5<4比较,不成立,不换
第4轮:
第1次:arr[4]<arr[3]比较,6<5比较,不成立,不换
public class TestBubbleSort2 {
public static void main(String[] args) {
int[] arr = {4,5,2,1,6};
//外循环控制轮数
for(int i=1; i<arr.length; i++){
//内循环控制每一轮的次数
/*
当i=1, j=4,3,2,1 j>=i
arr[4]与arr[3]
arr[3]与arr[2]
arr[2]与arr[1]
arr[1]与arr[0]
arr[j]<arr[j-1]
当i=2, j=4,3,2
arr[4]与arr[3]
arr[3]与arr[2]
arr[2]与arr[1]
当i=3, j=4,3
arr[4]与arr[3]
arr[3]与arr[2]
当i=4, j=4
arr[4]与arr[3]
*/
for(int j=arr.length-1; j>=i; j--){
if( arr[j]<arr[j-1]){
int temp = arr[j];
arr[j] = arr[j-1];
arr[j-1] = temp;
}
}
}
//输出结果
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
}
冒泡排序:优化 当我们某一轮比较完,数组已经有序了,考虑后面就可以不再继续比较了。
思路:如何确定数组是有序的? 当我们某一轮比较下来,发现没有任何一次交换,说明数组已经是有序了。
显示一下每一次比较完后的结果?
public class TestBubbleSort3 {
public static void main(String[] args) {
// int[] arr = {5,1,2,3,4};
// int[] arr = {1,2,3,4,5};
int[] arr = {5,4,3,2,1};
//方案一:从前往后比较,大的往右移动
for(int i=1; i<arr.length; i++){
boolean flag = true;//假设数组已经是有序了
System.out.println("第"+ i + "轮:");
for(int j=0; j<arr.length-i; j++){
if(arr[j] > arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1]= temp;
flag = false;//一旦发生交换,说明本轮仍然有元素需要调整位置,说明数组还没有确定顺序
}
//位置①每一次比较完的结果
System.out.print("第" + (j+1) + "次比较:");
for(int k=0; k<arr.length; k++){
System.out.print(arr[k] + " ");
}
System.out.println();
}
//位置②每一轮的结果
if(flag){
break;
}
}
//位置③所有元素排序完的结果
}
}
二维数组
二维数组的声明
package com.atguigu.two;
/*
1、认识二维数组
一维、二维数组,理论上可以有三维、思维数组。但是实际中到二维数组就够了。
一维数组:[] 一组数据
{1,2,5,6,7}
二维数组:[][] 多组数组,
{{1,2,5,6,7}
{11,24,5}
{50,2,55,6,75,78}}
2、如何声明二维数组
元素的数据类型[][] 数组名;
*/
public class TestArray {
public static void main(String[] args) {
//存int的二维数组
int[][] arr;
//存储String的二维数组
String[][] strings;
/*
数组的写法:(了解)
*/
//一维数组
int[] arr1;//标准写法
int arr2[]; //非标准写法
//二维数组
int[][] arr3;//标准写法
int arr4[][];//非标准写法
int[] arr5[];//非标准写法
//面试题
int[] x , y[];
//x和y分别是一维还是二维数组
//答案:x是一维数组,y是二维数组
}
}
二维数组的初始化
package com.atguigu.two;
/*
3、静态初始化:
直接指定行数以及每一行的元素的个数和值。
行数根据{}里面的{}的个数决定。
4、动态初始化
写法一:每一行的列数是相同的,即每一行的元素个数是相同
元素的数据类型[][] 数组名 = new 元素的数据类型[行数][列数];
写法二:每一行的列数是不同的,或不确定
元素的数据类型[][] 数组名 = new 元素的数据类型[行数][];
还需要指定每一行的列数,即每一行元素的个数。
数组名[行下标] = new 元素的数据类型[该行元素的总个数,或行长度];
*/
public class TestInitArray {
public static void main(String[] args) {
int[][] arr1 = {{1,2,3,4,5},{6,7,8},{9,10,11,12,13}};
int[][] arr2 = new int[3][5];
//有3行,每一行有5个元素
/* {
{0,0,0,0,0},
{0,0,0,0,0},
{0,0,0,0,0}
}*/
int[][] arr3 = new int[3][];
//有3行
//每一行有几个元素不清楚
/* {
null,
null,
null
}
如果此时把int[]看成一个整体,即是一维数组类型。 int[]是一个数据类型。
int[][] arr3;就可以看成元素类型是int[]的一维数组。
int[][] arr3 = new int[3][]; 可以看成: int[][] arr3 = new int[][3];
等价于声明了一个一维数组,元素类型是int[],长度是3
如果此时访问第一个元素, arr3[0]
*/
System.out.println(arr3[0]);//null , 此时把int[]看成数据类型,int[]是引用数据类型,arr3这个数组元素的默认值是null
//第1行有5个元素
arr3[0] = new int[5]; //左边的[0]表示行下标,右边[5]表示该行有5个元素
//第2行有3个元素
arr3[1] = new int[3];
//第3行有4个元素
arr3[2] = new int[4];
/*
arr3到这里为止
{
{0,0,0,0,0},
{0,0,0},
{0,0,0,0}
}
*/
}
}
二维数组的使用
package com.atguigu.two;
/*
5、使用数组
(1)获取二维数组的总行数
二维数组名.length
(2)获取二维数组某一行
第1行:二维数组名[0]
第2行:二维数组名[1]
...
总结:二维数组名[行下标]
行下标的范围[0, 二维数组名.length-1]
(3)获取某一行的长度,或者某一行的元素个数
第1行:二维数组名[0].length 把一行看成一个一维数组
第2行:二维数组名[1].length 把一行看成一个一维数组
。。。
总结:二维数组名[行下标].length
(4)获取其中一个元素
int[][] arr = {{1,2,3,4,5},{6,7,8},{9,10,11,12,13}};
假设获取8,先确定它属于{6,7,8},arr[1]行,然后确定它第3个元素,arr[1][2]
总结:二维数组名[行下标][列下标]
*/
public class TestUseArray {
public static void main(String[] args) {
int[][] arr = {{1,2,3,4,5},{6,7,8},{9,10,11,12,13}};
System.out.println("总行数:" + arr.length);
System.out.println("二维数组名:" + arr);//[[I@4554617c
//[[:表示二维数组,I表示int类型,@4554617c本质是对象的hashCode值,可以看成是地址值
System.out.println("第1行:" + arr[0]);//[I@74a14482
//[:一维数组,I表示int类型,@74a14482本质是对象的hashCode值,可以看成是地址值
//arr1[0]存储的是{1,2,3,4,5}组数据的首地址
System.out.println("第2行:" + arr[1]);//[I@1540e19d
System.out.println("第3行:" + arr[2]);//[I@677327b6
System.out.println("--------------------");
System.out.println("第1行的元素个数:" + arr[0].length);
System.out.println("第2行的元素个数:" + arr[1].length);
System.out.println("第3行的元素个数:" + arr[2].length);
System.out.println("使用for循环遍历每一行的长度:");
for (int i=0; i<arr.length; i++){//arr1.length:总行数
System.out.println("第" + (i+1) +"行的长度:" + arr[i].length);//arr1[i].length某一行的长度
}
System.out.println("--------------------");
System.out.println("第1行的第1个元素:" + arr[0][0]);
System.out.println("第1行的第2个元素:" + arr[0][1]);
System.out.println("第3行的第2个元素:" + arr[2][1]);
}
}
二维数组的遍历
package com.atguigu.two;
/*
6、二维数组的遍历
for(int i=0; i<二维数组名.length; i++){
for(int j=0; j<二维数组名[i].length; j++){
元素:二维数组名[i][j]
}
}
*/
public class TestIterate {
public static void main(String[] args) {
int[][] arr = {{1,2,3,4,5},{6,7,8},{9,10,11,12,13}};
//外循环控制行
for (int i=0; i<arr.length; i++){
//内循环遍历每一行的元素
for(int j=0; j<arr[i].length; j++){
System.out.print(arr[i][j]+" ");
}
System.out.println();
}
}
}