5. Java数组、排序和查找

1.数组

1.1 数组简介

数组可以存放多个同一类型的数据。数组也是一种数据类型,是引用类型

double[] hens = {3, 5, 1, 3.4, 2.5, 8, 7};
double totalWeight = 0;
for(int i = 0; i < hens.length; i++) {
	totalWeight += hens[i];
}
System.out.println("总体重=" + totalWeight+ " 平均体重=" + (totalWeight / hens.length) );

1.2 数组的使用

【注】double scores[] <=> double[] scores

1.2.1 动态初始化

第一种动态分配方式

double scores[] = new double[5];

第二种动态分配方式, 先声明数组,再 new 分配空间

double scores[] ; //声明数组, 这时 scores 是 null
scores = new double[5]; //分配内存空间,可以存放数据

数组的引用 / 使用 / 访问 :
数组名[下标],如a[2]表示数组a的第3个元素

double scores[] = new double[5];
Scanner myScanner = new Scanner(System.in);

for(int i=0; i < scores.length; i++) {
	System.out.println("请输入第"+ (i+1) +"个元素的值");
	scores[i] = myScanner.nextDouble( );
}

System.out.println("==数组的元素/值的情况如下:===");
for(int i=0; i<scores.length; i++){
	System.out.println("第"+ (i+1) +"个元素的值=" + scores[i]);
}

1.2.2 静态初始化

int a[] = {1, 2, 3, 4, 5};

1.2.3 数组使用细节

  • 数组是多个相同类型数据的组合。

    int[] arr = {1, 2, 3, 60, 1.1};//错误 double -> int
    int[] arr1 = {1, 2, 3, 60,"hello"};//错误 String -> int
    double[] arr2 = {1.1, 2.2, 3.3, 60.6, 100};//正确 int -> double 
    
  • 数组元素可以是 基本类型引用类型

    String[] arr3 = {"北京","jack","milan"};
    
  • 数组创建后,如果没有赋值,有默认值 int 0,short 0,byte 0,long 0,float 0.0,double 0.0,char \u0000,boolean false,String null。

  • 数组下标必须在指定范围内使用,否则报错:下标越界异常(运行时报错)。

  • 数组属于引用类型,数组型数据是对象(object)。

【例】创建一个 char 类型的 26 个元素的数组,分别放置’A’~‘Z’。使用 for 循环访问所有元素并打印出来。

char[] chars = new char[26];
for( int i = 0; i < chars.length; i++) {
	//'A' + i 是 int , 且不是具体数值,需要强制转换再赋值
	chars[i] = (char)('A' + i); 
}
//循环输出
for( int i = 0; i < chars.length; i++) {
	System.out.print(chars[i] + " ");
}

1.3 数组赋值机制

基本数据类型是值传递。下面 n2 的变化,不会影响到 n1 的值,因为拷贝的是值。

int n1 = 10;
int n2 = n1;
n2 = 80;
System.out.println("n1=" + n1);//10
System.out.println("n2=" + n2);//80

数组在默认情况下是引用传递,赋的值是地址。下面arr1的变化会影响arr2,因为拷贝的是地址。

int[] arr1 = {1, 2, 3};
int[] arr2 = arr1;//把arr1赋给arr2
arr2[0] = 10;
//arr1的值
System.out.println(" ====arr1的元素====");
for(int i = 0; i < arr1.length; i++) {
	System.out.println(arr1[i]);
}

运行结果:
在这里插入图片描述

原理示意图:
在这里插入图片描述
既然把arr1直接赋给arr2时,会使两者指向同一片空间的地址,改变其中一个数组,另一个也随之改变;那么,如果要求改变新数组arr2时不影响原数组arr1,则需要另选方案,可以进行数组拷贝。

1.4 数组拷贝

将 int[] arr1 = {10, 20, 30}; 拷贝到 arr2 数组,要求数据空间是独立的。

int[] arr1 = {10,20,30};
//创建一个新的数组 arr2,开辟新的空间
//大小 arr1.length;
int[] arr2 = new int[arr1.length];
for(int i = 0; i < arr1.length; i++) {
	arr2[i] = arr1[i];
}

1.5 数组反转

把数组 {11,22,33,44,55,66} 反转。

int[] arr = {11, 22, 33, 44, 55, 66};
for(int i = 0; i < arr.length/2; i++) {
	int t = arr[i];
	arr[i] = arr[arr.length - i - 1];
	arr[arr.length - i - 1] = t;
}
for(int i = 0; i < arr.length; i++) {
	System.out.println(arr[i]);
}

1.6 数组扩容 / 缩减

将 arr{1, 2, 3} 扩充为 arr{1, 2, 3, 4}

int[] arr = {1, 2, 3};
int[] arrNew = new int[arr.length + 1];
for (int i=0; i<arr.length; i++)
{
	arrNew[i] = arr[i]; 
}
arrNew[arrNew.length - 1] = 4;
arr = arrNew;
for(int i = 0; i < arr.length; i++) {
	System.out.println(arr[i]);
}

用户可以向 arr{1, 2, 3} 追加元素,并且可以不断追加,直至按下 “n”。

int[] arr = {1, 2, 3};
Scanner myScanner = new Scanner(System.in);
do
{
	int[] arrNew = new int[arr.length + 1];
	for (int i=0; i<arr.length; i++){
		arrNew[i] = arr[i]; 
	}
	System.out.print("请输入要追加的元素:");
	arrNew[arrNew.length - 1] = myScanner.nextInt();
	arr = arrNew;
	for(int i = 0; i < arr.length; i++) {
		System.out.println(arr[i]);
	}
	System.out.print("是否要继续追加元素(y/n):");
	char ch = myScanner.next().charAt(0);
	if (ch == 'n'){
		break;
	}
}while (true);

缩减数组,每次缩减最末尾的一个元素,直至用户按下“n”,或者数组中只剩一个元素时提醒不能再缩减。

int[] arr = {1, 2, 3, 4, 5};
Scanner myScanner = new Scanner(System.in);
do
{
	int[] arrNew = new int[arr.length - 1];
	for(int i=0; i<arrNew.length; i++){
		arrNew[i] = arr[i]; 
	}
	arr = arrNew;
	System.out.println("缩减后的数组为:");
	for(int i = 0; i < arr.length; i++) {
		System.out.println(arr[i] + "  ");
	}
	System.out.print("是否要继续缩减数组(y/n):");
	char ch = myScanner.next().charAt(0);
	if(ch == 'n'){
		break;
	}else if(ch == 'y' && arr.length == 1){
		System.out.println("当前数组长度为1,不能再继续缩减");
		break;
	}
}while (true);

2. 排序

2.1 排序的分类

内部排序:所有数据都加载到内存中进行排序。包括(交换式排序法、选择式排序法和插入式排序法);
外部排序:数据量过大,无法全部加载到内存中,需要借助外部存储进行排序。包括(合并排序法和直接合并排序法)。

2.2 冒泡排序

在这里插入图片描述

int[] arr = {6, 3, 5, 7, 0};
for (int i=0; i<arr.length-1; i++)
{
	for (int j=0; j<arr.length-i-1; j++)
	{
		if(arr[j] > arr[j+1]){
			int temp = arr[j];
			arr[j] = arr[j+1];
			arr[j+1] = temp;
		}

	}
	System.out.println("===第"+(i+1)+"轮交换后的结果===");
	for (int j=0; j<arr.length; j++)
	{
		System.out.print(arr[j]+" ");
	}
	System.out.print("\n");
}

3. 查找

在 java 中,我们常用的查找有两种:
(1) 顺序查找
(2) 二分查找【放在算法部分讲解】

猜数游戏中有这些名字:白眉鹰王、金毛狮王、紫衫龙王、青翼蝠王:从键盘中任意输入一个名字,判断其中是否包含此名字。 要求:如果找到了,就提示找到,并给出下标值。(采用顺序查找)

String[] names = {"白眉鹰王", "金毛狮王", "紫衫龙王", "青翼蝠王"};
System.out.print("请输入要搜索的名字:");
Scanner myScanner = new Scanner(System.in);
String s = myScanner.next();
int index = -1;
for (int i=0; i<names.length; i++)
{
	if(s.equals(names[i])){
		index = i;
		break;
	}
}
if(index != -1){
	System.out.println("该名字在第"+index+"个位置上");
}else{
	System.out.println("该名字不存在");
}

4. 二维数组

4.1 二维数组内存布局

请添加图片描述

4.2 静态初始化

int[][] arr = {{1,1,1}, {8,8,9}};

【例】用二维数组输出如下矩阵:
  0 0 0 0 0 0
  0 0 1 0 0 0
  0 2 0 3 0 0
  0 0 0 0 0 0

//二维数组定义和赋初值
int[][] arr = { {0, 0, 0, 0, 0, 0}, 
				{0, 0, 1, 0, 0, 0}, 
				{0, 2, 0, 3, 0, 0},
				{0, 0, 0, 0, 0, 0} 
			  };
//二维数组遍历
//arr.length表示二维数组中有多少一维数组
//arr[i].length表示内含的一维数组有多少个元素
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();
}

【注】若有int[][] arr = {{1,1,1}, {8,8,9}, {100}},其中的第三个一维数组不能直接写成 100,因为它应该是 int[] 类型。

4.3 动态初始化

使用方式 1:

int a[][]=new int[2][3];

使用方式 2:

int arr[][]; 
arr = new int[2][3];

上面两种操作进行之后,arr = {{0, 0, 0}, {0, 0, 0}}。

使用方式 3:创建列数不确定的二维数组
例:动态创建下面的二维数组,并输出。
1
2 2
3 3 3

//创建二维数组,内含3个一维数组,
//但每个一维数组还未开辟空间
int[][] arr = new int[3][];
for (int i=0; i<arr.length; i++)
{
	//给每个一维数组开辟空间
	//未给一维数组new空间时,arr[i]是null
	arr[i] = new int[i+1];
	//遍历一维数组,并给一维数组的每个元素赋值
	for (int j=0; j<arr[i].length; j++)
	{
		arr[i][j] = i+1;
	}
}
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();
}

4.3 杨辉三角

使用二维数组打印 10 行的杨辉三角。

int[][] arr = new int[10][];
for (int i=0; i<arr.length; i++)
{
	arr[i] = new int[i+1];
	for (int j=0; j<arr[i].length; j++)
	{
		if (j==0 || j==arr[i].length-1)//每行第一个和最后一个
		{
			arr[i][j] = 1;
		}else{
			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();
}

4.4 使用细节和注意事项

  • 一维数组的声明方式有:int[] xint x[]
  • 二维数组的声明方式有:int[][] yint[] y[]int y[][]
  • 二维数组实际上由多个一维数组组成,其中的一维数组长度可以相同,也可以不同。比如:int map [][] = {{1,2},{3,4,5}}。map[0] 是含有2个元素的一维数组,map[1] 是含有3个元素的一维数组,map 也称为列数不等的二维数组
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值