Java学习第三章——数组

目录

数组的概述

一维数组的使用

 多维数组的使用

数组中涉及到的常见算法

Arrays工具类的使用

数组使用中的常见异常


数组的概述

数组 (Array),是多个相同类型数据一定顺序排列的集合 ,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理 。

数组的常见概念
  数组名
  下标 (或索引 )
  元素
  数组的长度

数组本身是引用数据类型,而数组中的元素可以是任何数据类型 ,包括基本数据类型和引用数据类型。

创建数组对象会在内存中开辟一整块连续的空间 ,而数组名中引用的是这块连续空间的首地址 。

数组的长度一旦确定,就不能修改

我们可以直接通过下标 (或索引 )的方式调用指定位置元素 ,速度很快 。

数组的分类
   按照维度:一维数组、二维数组、三维数组 、…
   按照元素的数据类型分:基本数据类型元素的数组、引用数据类型元素的数组(即对象数组 )

一维数组的使用

声明

一维数组的声明方式
type var[] 或 type[] var
  例如:

  int a[] ;
  int[] a1;
  double b[] ;
  String[] c;// 引用类型变量数组

Java 语言中声明数组时不能指定其长度 (数组中元素的个数), 例如: int a[5 ]; // 非法

初始化

动态初始化:数组声明且为元素分配空间,与赋值的操作分开进行

int[] arr = new int[3];
arr[0] = 3;
arr[1] = 4;
arr[2] = 5;

String names[];
names = new String[3];
names[0] = “钱学森”;
names[1] = “邓稼先”;
names[2] = “袁隆平”;

静态初始化:在定义数组的同时就为数组元素分配空间并赋值

int arr[] = new int[]{3,4,5};
或
int[] arr = {3,4,5};

String names[] = {"李四光","茅以升","华罗庚"}

数组元素的引用

   定义并用运算符new为之分配空间后,才可以引用数组中的每个元素;
   数组元素的引用方式:数组名[数组元素下标]
   数组元素下标可以是整型常量或表达式。如 a[3],b[i] , c[6* ],c[6*i];
   数组元素下标从0开始;长度为n的数组合法下标取值范围 : 0—>n-1如int a[]=new int[3];  可引用的数组元素为a[0]、a[1]、a[2]
   每个数组都有一个属性length指明它的长度,例如:a.length指明数组a的长度(元素个数 )
   数组一旦初始化,其长度是不可变的

遍历数组

for (int i =0;i < arr.length;i++){
                        
}

 数组元素的默认初始化值

数组是引用类型,它的元素相当于类的成员变量,因此数组一经分配空间,其中的每个元素也被按照成员变量同样的方式被隐式初始化

   对于基本数据类型而言,默认初始化值各有不同。整型0,浮点型0.0,char型0或‘\u0000’(表现效果为空),boolean型false
   对于引用数据类型而言,默认初始化值为null(注意与0不同!)

数组的内存解析 

创建基本数据类型数组  

public class Test {
	public static void main(String[] args) {
		int[] s;
		s = new int[10];
		for (int i = 0;i<s.length;i++) {
			s[i] = 2*i+1;
			System.out.println(s[i]);
		}
	}
}
int[] ss = new int[10]s[i]=2*i+1

内存结构简化

 main方法中局部变量ages存放在栈里,ages指向在堆中开辟的空间

 练习

从键盘读入学生成绩, 找出最高分并输出学生成绩等级。
成绩 >= 最高分-10 等级为 ’A’ 
成绩 >= 最高分-20 等级为 ’B’
成绩 >= 最高分-30 等级为 ’C’
其余 等级为’D’
提示:先读入学生人数,根据人数创建 int数组, 存放学生成绩。
public class Score {
	public static void main(String[] args) {
		//使用scanner读取学生个数
		System.out.print("输入学生人数:");
		Scanner scan =new Scanner(System.in);
		int n = scan.nextInt();
		//创建数组存储学生成绩,动态初始化
		//给数组中的元素赋值
		double[] score = new double[n];
		for(int i =0;i<n;i++) {
			System.out.println("输入第"+(i+1)+"个学生分数:");
			score[i] = scan.nextDouble();
		}
		//获取数组中的最大值
		double maxScore = score[0];
		for(int i =0;i<n;i++) {
			if(score[i]>maxScore)
				maxScore = score[i];
		}
		
		System.out.println("最高分是"+maxScore);
		
		char level;
		for (int i=0;i<n;i++) {
			if(score[i]>=maxScore-10) {
				level = 'A';
			}else if(score[i]>=maxScore-20) {
				level = 'B';
			}else if(score[i]>=maxScore-30){
				level = 'C';
			}else {
				level = 'D';
			}
			System.out.println("第"+(i+1)+"个学生的成绩"+score[i]+",等级是"+level);	
		}
	}
}

 多维数组的使用

Java语言里提供了支持多维数组的语法。
如果说可以把一维数组当成几何中的线性图形,那么二维数组就相当于是一个表格,像Excel中的表格一样。
对于二维数组的理解,我们可以看成是一维数组array1又作为另一个一维数组array2的元素而存在。从数组底层的运行机制来看,其实没有多维数组

二维数组[][]:数组中的数组

格式1(动态初始化):int[][] arr = new int [3][2];
   定义了名称为arr的二维数组
   二维数组中有3个一维数组
   每一个一维数组中有2个元素
   一维数组的名称分别为arr[0],arr [1],arr[2]
   给第一个一维数组1脚标位赋值为78写法是:arr[0][1] = 78;

格式 2(动态初始化):int[][] arr = new int [3][];
   二维数组中有3个一维数组。
   每个一维数组都是默认初始化值null (注意:区别于格式1)
   可以对这三个一维数组分别进行初始化
   arr[0]  = new int[3];arr[1] = new int[1]; arr[2] = new int[2];
   注:
    int[][] arr = new int [][3]; //非法

格式 3(静态初始化):int[][] arr = new int [][]{{3,8,2},{2,7},{9,0,1,6}}; 
   定义一个名称为arr的二维数组,二维数组中有三个一维数组
   每一个一维数组中具体元素也都已初始化
   第一个一维数组 arr[0] = {3,8,2};
   第二个一维数组 arr[1] = {2,7}; 
   第三个一维数组 arr[2] = {9,0,1,6}; 
   第三个一维数组的长度表示方式: arr[2].length; 
   注意特殊写法情况:int[] x,y[]; x 是一维数组, y是二维数组。
   Java中多维数组不必都是规则矩阵形式

数组元素的默认初始化值

针对方式int[][] arr =new int [4][3]; 

   外层元素的初始化值为:地址值

   内存元素的初始化值:与一维数组初始化情况相同

针对方式int[][] arr =new int [4][]; 

   外层元素的初始化值为:null

   内存元素的初始化值:不能调用,报空指针错

int[][] arr =new int [4][3];
System.out.println(arr[0]);//[I@15db9742  地址值
System.out.println(arr[0][0]);//0

float[][] arr =new float [4][3];
System.out.println(arr[0]);// 地址值
System.out.println(arr[0][0]);//0.0

int[][] arr =new float [4][];
System.out.println(arr[0]);// null
System.out.println(arr[0][0]);//空指针异常



二维数组内存解析

int[][] arr1 = new int[4][];
arr1[1] = new int[]{1,2,3};
arr1[2] = new int[4];
arr1[2][1] = 30;

练习 

1.获取arr数组中所有元素的和。
提示:使用for的嵌套循环

public class Score {
	public static void main(String[] args) {
		int[][] arr = new int[][]{{3,5,8},{12,9},{7,0,6,4}};
		int sum = 0;
		for (int i =0;i<arr.length;i++) {
			for (int j =0;j<arr[i].length;j++) {
				sum+=arr[i][j];
			}
		}
		System.out.println(sum);	
	}
}

2.声明:int[] x,y[];再给变量赋值以后,可以通过编译的是:

x[0]=y; y[0]=x; y[0][0]=x; x[0][0]=y;y[0][0]=x[0]; x=y

一维数组:int[] x或者int x[];二维数组 int[][] y,int[] y[],int y[][]

3.使用二维数组打印一个10行杨辉三角。

a[i][j] = a[i-1][j-1]+a[i-1][j]

public class Score {
	public static void main(String[] args) {
		//1.声明并初始化二维数组
		int[][] arr = new int[10][];
		//2.给数组的元素赋值
		for (int i=0;i<arr.length;i++) {
			arr[i] = new int[i+1];
			//首末行元素赋值
			arr[i][0] = arr[i][i]=1;
			for (int j=1;j<arr[i].length-1;j++) {
					arr[i][j] = arr[i-1][j-1]+arr[i-1][j];
					
				}
			}
		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();
		}
	}
}

 创建一个长度为6的int型数组,要求数组元素的值都在1-30之间,且是随机赋值。同时要求元素的值各不相同。

public class Score {
	public static void main(String[] args) {
		int[] arr = new int[6];
		for (int i = 0;i < arr.length ;i++) {
			arr[i] = (int)(Math.random()*6+1);
			for (int j = 0;j < i;j++) {
				if(arr[j] == arr[i]) {
					i--;
					break;
				}
			}
		}
		for (int value:arr) {
			System.out.print(value+" ");
		}
	}
}

数组中涉及到的常见算法

1. 数组元素的赋值 (杨辉三角、回形数等 )
2. 求数值型数组中元素的最大值、最小值、平均数、总和等
3. 数组的复制 、反转、查找 (线性查找 、二分法查找)
4. 数组元素的排序算法
练习

1.定义一个int型的一维数组,包含10个元素, 分别赋一些随机整数, 然后求出所有元素的最大值, 最小值,和 值,平均值, 平均值, 并输出 出来 。
要求: 所有随机数都是两位。

public class Score {
	public static void main(String[] args) {
		int[] arr = new int[10];
		int sum = 0;
		int max,min;
		arr[0] = (int)(Math.random()*90+10);
		max = min =arr[0];
		for (int i = 1; i < arr.length;i++) {
			arr[i] = (int)(Math.random()*90+10);
			
			sum+=arr[i];
			if (arr[i]>max) {
				max = arr[i];
			}
			if (arr[i]<min) {
				min = arr[i];
			}
	}
		for(int varchar:arr) {
			System.out.print(varchar+" ");
		}
		System.out.println("sum is:"+sum);
		System.out.println("min is:"+min);
		System.out.println("max is:"+max);
		System.out.println("avg is:"+(sum/10.0));
}

2.使用简单数组
(1) 创建一个名为ArrayTest 的类,在 main() 方法中声明 array1和array2两个变量,他们 是int[] 类型的数组。
(2) 使用大括号 {} ,把 array1初始化为 8个素数: 2,3,5,7,11,13,17,19
(3) 显示 array1的内容。
(4) 赋值array2变量等于array1,修改 array2中的偶索引元素,使其等于索引值 (如array[0]=0,array[2]=2) 。打印出 array1 。

public class Score {
	public static void main(String[] args) {
		int[] arr1,arr2;
		arr1 = new int[] {2,3,5,7,11,13,17,19};
		for (int index:arr1) {
			System.out.print(index+"\t");
		}
		arr2 = arr1;
		System.out.println();
		for (int i = 0;i<arr2.length;i++) {
			if (i%2==0) {
				arr2[i] = i;
			}
			System.out.print(arr1[i]+"\t");
		}
			
	}

arr2 = arr1 //不能称作数组的复制。arr1和arr2地址值相同,都指向了堆空间的唯一的数组实体

数组的复制

arr2对arr1的复制:

int[] arr2 = new int [arr1.length];
for(i=0;i<arr1.length;i++){
    arr2[i] = arr1[i]
}; 

数组的反转

方法一:
for(i=0;i<(arr.length)/2;i++){
    int temp = arr[i];
    arr[i] = arr[arr.length-i-1];
    arr[arr.length-i-1] = temp;
}; 

方法二:
for(i=0,j=arr.length-1;i<j;i++,j--){
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}; 


查找

线性查找

//线性查找
public class Score {
	public static void main(String[] args) {
		String[] arr = new String[] {"JJ","DD","MM","BB","GG","AA"};
		String dest = "B";
		boolean isFlag = true;
		for (int i =0;i<arr.length;i++) {
			if(dest.equals(arr[i])) {
				System.out.println("找到了指定的元素,位置是"+i);
				isFlag = false;
				break;
			}
		}
		if(isFlag) {
			System.out.println("哈啊哈没找到");
		}
	}

二分法查找(要查找的数组必须有序)

public class Score {
	public static void main(String[] args) {
		int[] arr = new int[] {-98,-45,2,23,46,98};
		int dest = 9;
		int head = 0;//初始索引
		int end = arr.length-1;//初始的末索引
		boolean isFlag = true;
		while(head<=end) {
			int mid = (head+end)/2;
			if (dest == arr[mid]) {
				System.out.println("找到,索引为"+mid);
				isFlag = false;
				break;
			}else if(dest>arr[mid]){
				head = mid+1;
			}else {
				end = mid -1;
			}
		}
		
		if (isFlag) {
			System.out.println("没找到");
		}
	}
}

排序算法 

排序:假设含有n个记录的序列为 {R1 ,R2 ,..., Rn }, 其相应的关键字序列为 {K1 ,K2 ,..., Kn }。将这些记录重新排序为 {Ri1,Ri2,...,Rin}, 使得相应的关键字值满足条件Ki1<=Ki2<=...<=Kin,这样的一种操作称为排序。
  通常来说,排序的目的是快速查找。
衡量排序算法的优劣
1. 时间复杂度 :分析关键字的比较次数和记录的移动次数

2. 空间复杂度: 分析排序算法中需要多少辅助内存

3. 稳定性: 若两个记录A和B的关键字值相等,但排序后 A、B的先后次序保持不变,则称这种排序算法是稳定的。

排序算法分类: 内部排序 和外部排序 。
   内部排序 :整个排序过程不需要借助于外部存储器(如磁盘等),所有排序操作都在内存中完成。
   外部排序 :参与排序的数据非常多,数据量非常大,计算机无法把整个排序过程放在内存中完成,必须借助于外部存储器(如磁盘)。外部排序最常见的是多路归并排序。
可以认为外部排序由多次内部排序组成。

十大内部排序算法

关于十大排序算法的详细思想见专门开辟的章节排序算法,此处要求会写标红的排序算法,了解标黄的排序算法思想

选择排序
    直接选择排序、 堆排序
交换排序
    冒泡排序 、快速排序
插入排序
    直接插入排序、 折半插入排序、 Shell排序
归并排序
桶式排序
基数排序

算法的五大特征

冒泡排序
基本思想 :
通过对待排序序列从前向后,依次比较相邻元素的排序码,若发生逆序则交换,使排序码较大的元素从前部向后移动。排序过程中,各元素不断接近自己的位置,如果一趟排序下来没有进行过交换,就说明有序。因此设置一个标志swap判断元素是否进行过交换,从而减少不必要的比较。

public class BubbleSort {
	public static void main(String[] args) {
		int[] arr = new int[] {-90,56,100};
		int temp=0;
		boolean swap = false;
		for (int i = 0;i < arr.length-1;i++) {
			for (int j = 0;j < arr.length-1-i;j++) {
				if (arr[j] > arr[j+1]) {
					temp = arr[j];
					arr[j] = arr[j+1];
					arr[j+1] = temp;
					swap = true;
				}
			}
			if (!swap) {
				break;
			}
		}
    }
}

快速排序
快速排序通常明显比同为 O(nlogn) 的其他算法更快,因此常被采用,而且快排采用了分治法的思想,所以在很多笔试中能经常看到快排的影子。可见掌握快排的重要性 。
快速排序(Quick Sort )由图灵奖获得者Tony Hoare 发明,被列为 20 世纪十大算法之一 ,是迄今为止所有内排序算法中速度最快的一种。快排时间复杂度为 O(nlog(n)) 。 

排序思想:
1. 从数列中挑出一个元素,称为 "基准 "(pivot)
2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准后面(相同数可以放到任一边。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区( partition )操作。
3. 递归地( recursive)把小于基准值元素的子数列和大于基准值元素的子序列排序。
4. 递归的最底部情形,是数列大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会结束。因为在每次的迭代(iteration)中,它至少会把一个元素摆到最后的位置去 。

练习:49 38 65 97 76 13 27 49

 

public class QuickSort {
	private static void swap(int[] data, int i, int j) {
		int temp = data[i];
		data[i] = data[j];
		data[j] = temp;
	}

	private static void subSort(int[] data, int start, int end) {
		if (start < end) {
			int base = data[start];
			int low = start;
			int high = end + 1;
			while (true) {
				while (low < end && data[++low] - base <= 0)
					;
				while (high > start && data[--high] - base >= 0)
					;
				if (low < high) {
					swap(data, low, high);
				} else {
					break;
				}
			}
			swap(data, start, high);
			
			subSort(data, start, high - 1);//递归调用
			subSort(data, high + 1, end);
		}
	}
	public static void quickSort(int[] data){
		subSort(data,0,data.length-1);
	}
	
	
	public static void main(String[] args) {
		int[] data = { 9, -16, 30, 23, -30, -49, 25, 21, 30 };
		System.out.println("排序之前:\n" + java.util.Arrays.toString(data));
		quickSort(data);
		System.out.println("排序之后:\n" + java.util.Arrays.toString(data));
	}
}

排序算法性能对比 

Arrays工具类的使用

java.util.Arrays类即为操作数组的工具类,包含了用来操作数组(比如排序和搜索)的各种方法 。

int[] arr1 =new int[]{1,2,3,4,};
int[] arr2 =new int[]{1,3,2,4,};
boolean isEquals = Arrays.equals(arr1,arr2) //flase

System.out.print(Arrays.toString(arr1)); //直接输出[1,2,3,4]

Arrays.fill(arr1,10) //[10,10,10,10] 将指定元素填充到数组

Arrays.sort(arr2) // [1,2,3,4] 排序

数组使用中的常见异常

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值