第5章 数组

1 .数组概述

数组是具有相同数据类型的一组数据的集合。例如,球类的合集——足球、篮球、羽毛球等;电器集合——电视剧、洗衣机、电风扇等。在程序设计中,可以将这些集合称为数组。数组中的元素具有相同的数据类型。在Java中同样将数组看作一个对象,虽然基本数据类型不是对象,但由基本数据类型组成的数组却是对象。在程序设计中引入数组可以更有效的管理和处理数据。可根据数组的维数将数组分为一维数组、二维数组……

2.一维数组

一维数组实质上是一组相同类型数据的线性集合,当在程序中需要处理一组数据,或者传递一组数据时,可以应用这种类型的数据。

2.1创建一维数组

数组作为对象允许使用new关键字进行内存分配。在使用数组之前,必须首先定义数组变量所属的类型。一维数组的创建有两种形式。

1.先声明,再用new关键字进行内存分配

声明一维数组有下列两种方式:

数组元素类型 数组名字[ ];

数组元素类型[ ] 数组名字;

数组元素类型决定了数组的数据类型,它可以是Java中任意的数据类型,包括简单类型和组合类型。数组名字为一个合法的标识符,符号“ [ ] ”指明该变量是一个数组类型变量。单个“ [ ] ”表示要创建的数组是一维数组。

声明一维数组,代码如下:

int arr[];                    //声明int型数组,数组中每个元素都是int型数值 

声明数组后,还不能立即访问它的任何元素,因为声明数组只是给出了数组名字和元素的数据类型,要想真正使用数组,还要为它分配内存空间。在为数组分配内存空间时必须指明数组的长度。为数组分配内存空间的语法格式如下:

数组名字 = new 数组元素的类型[数组元素的个数];

  • 数组名字:被连接到数组变量的名称。
  • 数组元素的个数:指定数组中变量的个数,即数组的长度。

通过上面的语法可知,使用new关键字为数组分配内存时,必须指定数组元素的类型和数组元素的个数,即数组的长度。

为数组分配内存,代码如下:

arr = new int[5];

以上代码表示创建一个含有5个元素的整型数组,并且将创建的数组对象赋给引用变量arr,即通过引用变量arr来引用这个数组

使用new关键字为数组分配内存时,整型数组中各个元素的初始值都为0

2.声明的同时为数组分配内存

这种创建数组的方式是将数组的声明和内存的分配合在一起执行。语法如下:

数组元素的类型 数组名 =new数组元素的类型[数组元素的个数];

声明并为数组分配内存,代码如下:

int month[ ] = new int[12]

上面的代码创建数组month,并指定了数组的长度为12。

2.2 初始化一维数组

数组与基本数据类型一样可以进行初始化操作。数组的初始化可分别初始化数组中的每个元素。数组的初始化有以下两种方式:

int arr[] =new int[]{1,2,3,5,25};

int arr2[] ={34,23,12,6};

从中可以看出,数组的初始化就是包括在大括号之内用逗号分开的表达式列表。用逗号(,)分隔数组中的各个元素,系统自动为数组分配一定的空间。用第一张初始化方式,将创建5个元素的数组,其元素依此为1、2、3、5、25。第二种初始化方式,会创建4个元素的数组,其元素依此为34、23、12、6。

2.3 使用一维数组

例1,使用一维数组输出1~12月每个月份的天数

在项目中创建GetDays类,在主方法中创建并初始化一个用于储存1~12月每个月份天数的int型数组,在控制台上输出1~12月每个月份的天数

代码:


public final class GetDays {//创建类

	public static void main(String[] args) {//主方法
		int day[]=new int[] {31,28,31,30,31,30,31,31,30,31,30,31};//创建并初始化一维数据
		for(int i=0;i<12;i++) {//利用循环将信息输出
			System.out.println((i+1)+"月有"+day[i]+"天");//输出每月的天数
		}
	}

}

运行结果:

3230314ce1134f978dff504336792425.png

3 . 二维数组

如果一维数组中的各个元素仍然是一个数组,那么它就是一个二维数组。二维数组常用于表示表,表中的信息以行和列的形式组织,第一个下标代表元素所在的行,第二个下标代表元素所在的列。

3.1 创建二维数组

二维数组可以看作是特殊的一维数组,创建有两种方式:

1.先声明,再用new关键字进行内存分配

声明二维数组的语法如下:

数组元素的类型 数组名字[][];

数组元素的类型[][] 数组名字;

声明二维数组,代码如下:

int a[][];

同一维数组一样,二维数组在声明时也没有分配内存空间,同样要使用new关键字来分配内存,然后才可以访问每个元素。对于高维数组,有两种为数组分配内存的方式。

第一种内存分配方式是直接为每一维分配内存空间,代码如下:

a = new int[2][4] 

上述代码创建了二维数组a,二维数组a中包括两个长度为4的一维数组。

第二种内存分配方式是分别为每一维分配内存,代码如下:

a=new int[2][];

a[0] =new int[2];

a[1]=new int [3];

上述代码创建了二维数组a,但是只声明a第一维的长度,也就是“行数”,第二维的长度也就是“列数”,则是为每一行单独声明的,因此创建的数组a是“不定长数组”。

2.声明的同时为数组分配内存

第二种创建方式与第一种实现的功能相同,只不过声明和赋值合并到同一行代码中。例如,创建一个2行4列的二维数组,代码如下:

int a =new int[2][4]

3.2 初始化二维数组

二维数组的初始化与一维数组初始化类似,同样可以使用大括号完成。语法如下:

type arrayname[][] ={value1,value2,…valuen};

  • type:数组数据类型
  • arrayname:数组名称,一个合法的标识符
  • value:二维数组中各个元素,都代表一个一维数组。

初始化二维数组,代码如下:

int myarr[][]={{12,0},{45,10}};

初始化二维数组后,要明确数组的下标都是0开始。例如,上面的代码中myarr[1][1]的值为10。int型二维数组是以int a[][]来定义的,所以可以直接给a[x][y]赋值。例如,给a[1]的第二个元素赋值的语句如下:

a[1][1]=20

3.3 使用二维数组

例2,输出一个3行4列且所以元素都为0的矩形

在项目中创建Matrix类,在主方法中编写代码实现输出一个3行4列且所有元素都为0的矩形

代码:


public class Matrix {//创建类

	public static void main(String[] args) {//主方法
		int a[][]=new int[3][4];//定义二维数组
		for(int i =0;i<a.length;i++) {
			for(int j =0;j<a[i].length;j++) {//循环遍历数组中的每个元素
				System.out.print(a[i][j]);//将数组中的元素输出
			}
			System.out.println();//输出空格
		}
	}

}

运行结果:

563ac1863f5a475bb8bd5f4323bfc01c.png

4.  数组的基本操作 

4.1 遍历数组

遍历数组就是获取数组中的每个元素。通常遍历数组都是使用for循环来实现。

遍历二维数组需使用双层for循环,通过数组的length属性可获取数组的长度。

例3,呈梯形输出二维数组中的元素

在项目中创建Trap类,在主方法中编写代码,定义二维数组,将二维数组中的元素呈梯形输出。

代码:

public final class Trap {//创建类
	public static void main(String[] args) {//主方法
		int b[][]=new int[][] {{1},{2,3},{4,5,6}};//定义二维数组
		for(int k=0;k<b.length;k++) {
			for(int c=0;c<b[k].length;c++) {//循环遍历二维数组中的每个元素
				System.out.print(b[k][c]);//将数组中的元素输出			
			}
			System.out.println();//输出空格
		}
	}
}

运行结果:

3c8fc919f789463bb8a5134e4416c6a1.png

例4,使用foreach语句遍历二维数组 

在项目中创建Tautog类,在主方法中定义二维数组,使用foreach语句遍历二维数组。

代码:

public class Tautog {//创建类
	public static void main(String[] args) {//主方法
		int arr2[][]= {{4,3},{1,2}};//定义二维数组
		System.out.println("数组中的元素是:");//提示信息
		int i=0;//外层循环计数器变量
		for(int x[]:arr2) {//外层循环变量为一维数组
			i++;//外层计数器递增
			int j=0;//内层循环计数器变量
			for(int e:x) {//循环遍历每一个数组元素
				j++;//内层计数器递增
				if(i==arr2.length &&j ==x.length) {//判断变量是二维数组中的最后一个元素
					System.out.print(e);//输出二维数组的最后一个元素
				}else//如果不是二维数组中的最后一个元素
					System.out.print(e+"、");//输出信息
			}		
		}
	}
}

运行结果:

7d3d84955fd142abb8d155bb95a6e642.png

4.2 填充替换数组元素 

数组中的元素定义完成后,可通过Arrays类的静态方法fill( )来对数组中的元素进行替换。改方法通过各种重载形式可完成对任意类型的数组元素的替换。fill( )方法有两种参数类型。

1.fill(int[] a,int value)

该方法可将指定的int值分配给int型数组的每个元素。语法如下:

fill(int[] a,int value)

  • a:要先进行元素替换的数组。
  • value:要储存数组中所有元素的值

例5,使用fill( )方法填充数组元素

在项目中创建Swap类,在主方法中创建一维数组,并实现通过filll( )方法填充数组元素,最后将数组中的各个元素输出。

代码:

import java.util.Arrays;//导入java.util.Arrays类
public class Swap {//创建类
	public static void main(String[] args) {//主方法
		int arr[]=new int[5];//创建int型整数
		Arrays.fill(arr,8);//使用同一个值对数组进行填充
		for(int i=0;i<arr.length;i++) {//循环遍历数组中的元素
			System.out.println("第"+i+"个元素是:"+arr[i]);//将数组中的元素依此输出
		}
	}

}

运行结果:

8b75e68fd5ff412bbf8c0cf2ae654b55.png

2.fill (int[] a,int fromlndex,int tolndex,int value)

该方法将指定的int值分配给int型数组指定范围中的每个元素。填充的范围从索引fromIndex(包括)一直到索引toIndex(不包括)。如果fromIndex==toIndex,则填充范围为空,语法如下:

fill (int[] a,int fromlndex,int tolndex,int value)

  • a:要进行填充的数组
  • fromIndex:要使指定值填充的第一个元素的索引(包括)。
  • toIndex:要使用指定值填充的最后一个元素的索引(不包括)。
  • value:要分配给数组指定范围中的每个元素的值。

例6,使用fill()方法替换数组中的元素

在项目中创建Displace类,创建一维数组,并通过fill()方法替换数组元素,最后将数组中的各个元素输出

代码:

import java.util.Arrays;//导入java.util.Arrays类
public class Displase {//创建类
	public static void main(String[] args) {//主方法
	int arr[]=new int[] {45,12,2,10};//定义初始化int型数组arr
	Arrays.fill(arr,1,2,8);//使用fill()方法替换数组指定范围内的元素
	for(int i=0;i<arr.length;i++) {//循环遍历数组中的元素
		System.out.println("第"+i+"个元素是:"+arr[i]);//将数组中的每个元素输出
	}
	}

}

运行结果:

bb32552e191343e38331d8cdd27164f9.png

4.3 对数组进行排序 

通过Arrays类的静态方法sort()可以实现对数组的排序。Sort()方法提供了多种重载形式,可对任意的数组进行升序排序。语法如下:

Arrays.sort(object)

其中,object是指进行排序的数组名称。

例7,使用sort()方法将数组排序后输出

在项目中创建Taxis类,在主方法中创建一维数组,将数组排序后输出。

代码:

import java.util.Arrays;//导入java.util.Arrays类
public class Taxis {//创建类
	public static void main(String[] args) {//主方法
		int arr[]=new int[] {23,42,12,8};//声明数组
		Arrays.sort(arr);//将数组进行排序
		for(int i=0;i<arr.length;i++) {//循环遍历排序后的数组
			System.out.println(arr[i]);//将排序后数组中的各个元素输出
		}

	}

}

运行结果:

94898a6b727342ecbd31e8ccf640920b.png

4.4 复制数组 

Arrays类的compOf()方法与copyOfRange()方法可以实现对数组的复制。copyOf()方法是复制数组至指定长度,copyOfRange()方法则将指定数组的指定长度复制到一个新数组中。

1.copyOf()方法

该方法提供了多种重载形式,用于满足不同类型数组的复制。语法如下:

copyOf(arr,int newlength)

  • arr:要进行复制的数组
  • newlength:int型常量,指复制后的新数组长度。如果新数组的长度大于数组arr的长度,则用0填充(根据复制数组的类型来决定填充的值,整型数组用0填充,char型数组则使用null来填充);如果复制后的数组长度小于数组arr的长度,则会从数组arr的第一个元素开始截取至满足新数组长度为止。

例8,复制数组

在项目中创建Cope类,在主方法中创建一维数组,实现将此数组复制得到一个长度为5的新数组,并将新数组输出。

代码:

import java.util.Arrays;//导入java.util.Arrays类
public final class Cope {//创建类
	public static void main(String[] args) {//主方法
		int arr[]=new int[] {23,42,12};//定义数组
		int newarr[]=Arrays.copyOf(arr,5);//复制数组arr
		for(int i=0;i<newarr.length;i++) {//循环遍历复制后的新数组
			System.out.println(newarr[i]);//将新数组输出
		}
	}

}

运行结果:

c21cd5f69d684fb4a9a60c0cda0a787e.png

2.copyOfRange()方法

该方法同样提供了多种重载形式。语法如下:

copyOfRange(arr,int formlndex,int tolndex) 

  • arr:要进行复制的数组对象。
  • formIndex:指定开始复制数组的索引位置。formIndex必须在0至整个数组的长度之间。新数组包括索引是formIndex的元素。
  • toIndex:要复制范围的最后索引位置。可大于数组arr的长度。新数组不包括索引是toIndex的元素。

例9,按照索引复制数组

在项目中创建Repeta类,在主方法中创建一维数组,并将数组中索引位置是0~3的元素复制到新数组中,最后将新数组输出。

代码:

import java.util.Arrays;//导入java.util.Arrays类
public class Repeat {//创建类
	public static void main(String[] args) {//主方法
		int arr[]=new int[] {23,42,12,84,10};//定义数组
		int newarr[]=Arrays.copyOfRange(arr,0,3);//复制数组
		for(int i=0;i<newarr.length;i++) {//循环遍历复制后的新数组
			System.out.println(newarr[i]);//将新数组中的每个元素输出
		}
	}

}

运行结果:

60a2e08b5848490bab9f8156a93c8a80.png

4.5 查询数组 

Arrays类的binarySearch()方法,可使用二分搜索来搜索指定数组,以获得指定对象。该方法返回要搜索元素的索引值。binarySearch()方法提供了多种重载形式,用于满足各种类型数组的查找需要。binarySearch()方法有两种参数类型。

1.binarySearch(Object[] a,Object key)

语法如下:

binarySearch(Object[] a,Object key)

  • a:要搜索的数组
  • key:要搜索的值

如果key包含在数组中,则返回搜索值得索引;否则返回-1或“-”(插入点)。插入点是搜索键将要插入数组得那一点,即第一个大于此键得索引。

查询数组元素,代码如下:

int arr[] =new int[]{4,25,30};//创建并初始化数组
Arrays.sort(arr);//将数组进行排序
int index =Arrays.binarySearch(arr,8);

上面的代码中变量index的值是元素“8”在数组arr中索引在0~1内的索引位置。由于在指定的范围内并不存在元素“8”,index的值是“-”(插入点)。如果对数组进行排序,元素“8”应该在“25”的前面,因此插入点应该是元素“25”的索引值2,所有index的值是-2.

如果数组中的所有元素都小于指定的键,则为a.length(这保证了当且仅当此键被找到时,返回的值将大于等于0)。

例10,查找元素在数组中的索引位置

在项目中创建Reference类,在主方法中创建一维数组ia,实现查找元素4在数组ia中的索引位置。

代码:

import java.util.Arrays;//导入java.util.Arrays类
public abstract class Reference {//创建类
	public static void main(String[] args) {//主方法
		int ia[]=new int[] {1,8,9,4,5};//定义int型数组ia
		Arrays.sort(ia);//将数组进行排序
		int index=Arrays.binarySearch(ia, 4);//查找数组ia中元素4的索引位置
		System.out.println("4的索引位置是:"+index);//将索引输出
	}

}

运行结果:

8d61e4d8fa1a445195474377036c2c59.png

 2.binarySearch(Object[]a,int fromIndex,int toIndex,Object key)

该方法在指定的范围内检索某一元素。语法如下:

binarySearch(Object[]a,int fromIndex,int toIndex,Object key)

  • a:要进行检索的数组
  • fromIndex:指定范围的开始处索引(包含)。
  • toIndex:指定范围的结束处索引(不包含)。
  • key:要搜索的元素。

使用该方法前,同样要对数组排序,这样才能获得准确的索引值。如果要搜索的元素key在指定的范围内,则返回搜索键的索引;否则返回“-1”或者“-”(插入点)。如果范围中的所有元素都小于指定的键,则插入点为toIndex(注意,这保证了当且仅当此键被找到,返回的值将大于等于0)。

例11,在指定范围内查找元素在数组中的索引位置

在项目中创建Rakel类,在主方法中创建String数组,实现查找元素“cd”在指定范围的数组str中的索引位置。

代码:

import java.util.Arrays;//导入java.util.Arrays类
public class Rakel {//创建类
	public static void main(String[] args) {//主方法
		String str[]=new String[] {"ab","cd","ef","yz"};//定义String型数组str
		Arrays.sort(str);//将数组进行排序
		int index=Arrays.binarySearch(str,0,2,"cd");//在指定范围内搜索元素"cd"的索引位置
		System.out.println("cd的索引位置是:"+index);//将索引输出
	}

}

运行结果:

863e311aec184cad920dd7871705e12b.png

5.数组排序算法 

5.1冒泡排序

冒泡排序是最常用的数组排序算法之一,它排序数组元素的过程总是将较小的数往前放、较大的数往后放,类似水中气泡往上升的动作,所有称为冒泡排序。

冒泡排序的基本思想是对比相邻的元素值,如果满足条件就交换元素值,把较小的元素移到数组前面,把较大的元素移到数组后面(也就是交换两个元素的位置),这样较小的元素就像气泡一样从底部上升到顶部。

例12,冒泡排序

在项目中创建BubbleSort类,这个类的代码将对一个int型的一维数组中的元素进行冒泡排序。

代码:

public class BubbleSort {//创建类
 public static void main(String[] args) {//主方法
  int[]array= {63,4,24,1,3,15};//创建一个数组,元素是乱序的
  BubbleSort sorter =new BubbleSort();//创建冒泡排序类的对象
  sorter.sort(array);//调用排序方法,对数组排序
 }

 public void sort(int[]array) {
  for(int i=1;i<array.length;i++) {
   //比较相邻两个元素,较大的元素往后冒泡
   for(int j=0;j<array.length-i;j++) {
    if(array[j]>array[j+1]) {
    	int temp =array[j];//把第一个元素值保存到临时变量中
    	array[j]=array[j+1];//把第二个元素值保存到第一个元素单元中
    	array[j+1]=temp;//把临时变量(第一个元素原值)保存到第二个元素单元中 
    }
   }
  }
  showArray(array);//输出冒泡排序后的数组元素
 }
 
 public void showArray(int[]array) {
	 for(int i:array) {//遍历数组
		 System.out.print(">"+i);//输出每个数组元素值
	 }
	 System.out.println();
 }
 }
    
  

运行结果:

aba3df5a2d944b8fae4b28e37ebabedb.png

5.2 直接选择排序 

1.基本思想

直接选择排序的基本思想是将指定排序位置元素与其他数组元素分别对比,如果满足条件就交换元素值。注意这里与冒泡排序的区别,不是交换相邻的元素,而是把满足条件的元素与指定的排序位置元素交换(如果从最后一个元素开始排序),这样排序好的位置逐渐扩大,直至整个数组都变成已排序好的格式。

2.算法示例

每一趟从待排序的数组元素中选出最小(或最大)的一个元素,顺序地放在已排好序地数列地最后,直到全部待排序地数据元素排完。例如:

初始数组资源         【63   4   24   1   3   15】

第一趟排序后         【15   4   24   1   3  】63

第二趟排序后         【15   4    3     1】24  63

第三趟排序后         【 1    4    3 】15   24  63

第四趟排序后         【 1    3 】4    15   24  63  

第五趟排序后         【1】 3     4    15   24  63  

例13,直接选择排序

在项目中创建SelectSort类,这个类的代码将对一个int型的一维数组中的元素进行直接选择排序。

代码:

public final class SelectSort {//创建类
	public static void main(String[] args) {//主方法
		int[]array= {63,4,24,1,3,15};//创建一个数组,元素是乱序的
		SelectSort sorter=new SelectSort();//创建直接排序类的对象
		sorter.sort(array);
	}
	
	public void sort(int[]array) {
		int index;
		for(int i=1;i<array.length;i++) {
			index =0;
			for(int j=1;j<=array.length-i;j++) {
				if(array[j]>array[index]) {
					index=j;
				}
			}
			//交换在位置array.length-1和index(最大值)上的两个数
			int temp=array[array.length-i];//把第一个元素值保存到临时变量中
			array[array.length-i]=array[index];//把第二个元素值保存到第一个元素单元中
			array[index]=temp;//把临时变量(第一个元素原值)保存到第二个元素单元中
		}
		showArray(array);//输出直接选择排序后的数组元素		
	}
	
	public void showArray(int[]array) {
		for(int i:array) {//遍历数组
			System.out.print(">"+i);//输出每个数组元素值
		}
		System.out.println();
	}

}

运行结果:

5814074c41cf4983913ab8be0314c18f.png

5.3 反转排序 

1.基本思想

反转排序的基本思想就是把数组最后一个元素与第一个元素替换,倒数第二个元素和第二个元素替换,以此类推,直到把所有数组元素反转替换。

2.算法示例

反转排序是对数组两边的元素进行替换,所有只需要循环数组长度的半数次,如数组长度为7,那么for循环只需要循环3次。例如:

初始数组资源         【10   20   30   40   50   60】

第一趟排序后             60【20   30   40   50】10

第二趟排序后             60    50【30  40】20   10

第三趟排序后             60    50    40   30   20   10

例14,反转排序

在项目中创建ReverseSort类,这个类的代码将对一个int型的一维数组中的元素进行反转排序。

代码:

public class ReverseSort {//创建类
	public static void main(String[] args) {//主方法
		int[]array = {10,20,30,40,50,60};//创建一个数组
		ReverseSort sorter=new ReverseSort();//创建反转排序类的对象
		sorter.sort(array);//调用排序对象方法,将数组反转
	}
	
public void sort(int[]array) {
	System.out.println("数组原有内容:");
	showArray(array);//输出排序前的数组元素
	int temp;
	int len=array.length;
	for(int i=0;i<len/2;i++) {
		temp =array[i];
		array[i]=array[len-1-i];
		array[len-1-i]=temp;
	}
	System.out.println("数组反转后的内容:");
	showArray(array);//输出排序后的数组元素
}

public void showArray(int[]array) {
	for(int i:array) {//遍历数组
		System.out.print("\t"+i);//输出每个数组元素值
	}
	System.out.println();
}
}

运行结果:

94e46eea188042c3a2631d980e9287b2.png

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只奶球.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值