5.1二维数组概括:
在 Java 中二维数组被看作数组的数组,即二维数组为一个特殊的一维数组,其每个元素又是一个一维数组。
5.2二维数组格式:
type[ ][ ] arr;
type 表示二维数组的类型,array 表示数组名称,第一个中括号表示行,第二个中括号表示列。
声明 int 类型和 char 类型的数组
int[][] age;
char[][] sex;
5.3初始化二维数组:
二维数组可以初始化,和一维数组一样,可以通过3种方式来指定元素的初始值。
(1) int[ ][ ] arr=new int[ ][ ]{值 1,值 2,值 3,…,值 n};
(2) int arr=new int[ ][ ]{new 构造方法(参数列),…};
(3) int[ ][ ] arr={{第1行第1列的值,第1行第2列的值,…},{第2行第1列的值,第2行第2列的值,…},…};
5.4操作:
- 获取当前元素
array[i-1][j-1];
其中,array 表示数组名称,i 表示数组的行数,j 表示数组的列数。
这是由于数组的下标起始值为 0,因此行和列的下标需要减 1。
- 获取全部元素
在二维数组中,直接使用 length 属性获取的是数组的行数;
在指定的索引后加上 length(如 array[0].length)表示的是该行拥有多少个元素,即列数。
如果要获取二维数组中的全部元素,最简单、最常用的办法就是使用 for 语句。
public static void main(String[] args)
{
double[ ][ ] score={{100,99,99},{100,98,97},{100,100,99.5},{99.5,99,98.5 }};
for(int i=0;i<score.length;i++) { //遍历行
for(int j=0;j<score[i].length;j++) { //遍历列
System.out.println("score["+i+"]["+j+"]="+score[i][j]);
}
}
}
上述代码使用嵌套 for 循环语句输出二维数组。在输出二维数组时,
第一个 for 循环语句表示以行进行循环,
第二个 for 循环语句表示以列进行循环,
这样就实现了获取二维数组中每个元素的值的功能。
- 查找元素:
线性查找
循环遍历数组查找
二分查找
public class douSearch{
public static void main(String[] args) {
int[][] m={
{1,2,3},
{4,5,6},
{7,8,9}
};
int minLine=0;
int maxLine=m.length-1;
int midLine=(minLine+maxLine)/2;
int key=4;
while(true) { //查找key位于哪一行(二分查找)
if(key>m[midLine][m[0].length-1]) {
minLine=midLine+1;
}
if(key<m[midLine][0]) {
maxLine=midLine-1;
}
if(key<=m[midLine][m[0].length-1]&&key>=m[midLine][0]) { //key位于这一行后
int min=0; 再在这行中进行二分查找
int max=m[midLine].length-1;
int mid=(min+max)/2;
while(m[midLine][mid]!=key) {
if(key>m[midLine][mid]) {
min=mid+1;
}
if(key<m[midLine][mid]) {
max=mid-1;
}
mid=(min+max)/2;
if(max<min) {
System.out.println("找不到");
return;
}
}
System.out.println((midLine+1)+":"+(mid+1)); //打印输出找到的下标
return;
}
midLine=(minLine+maxLine)/2;
if(maxLine<minLine) {
System.out.println("找不到");
return;
}
}
}
}
思路:
1 2 3 4 min
5 6 7 8 mid
9 10 11 12 max
首先在以行为变量使用二分查找 找到要找的元素位于哪一行
再在这行中使用二分查找 找到要找的元素 返回其下标
5.5 经典例题:
- 两个矩阵相乘 编写两个矩阵相乘的方法。方法头如下:
public static double[] [] multip1yMatrix(doub1e[][] a, double[][] b)
为了使矩阵a能够和矩阵b相乘,矩阵a的列数必须与矩阵b的行数相同,并且两个矩阵的元素要具有相同或兼容的数据类型。
class Demo4_1{
public static void main(String[] args){
int[][] m1={
{1,2,3},
{4,5,6},
{7,8,9}
};
int[][] m2={
{1,1,1},
{1,1,1},
{1,1,1}
};
int[][] m3=new int[m1.length][m2[0].length]; //创建存放结果的数组
for(int i=0;i<m3.length;i++){ //计算两个矩阵相乘
for(int j=0;j<m3[0].length;j++){
int sum=0;
for(int k=0;k<m2.length;k++){
sum+=m1[i][k]*m2[k][j];
}
m3[i][j]=sum;
}
}
for(int i=0;i<m3.length;i++){ //打印输出结果的二维数组
for(int j=0;j<m3[0].length;j++){
System.out.print(m3[i][j]+" ");
}
System.out.println();
}
}
}
解题思路:
一个m*p × 另一个p*n 最终相乘结果为 m*n
按照公式进行相乘相加的结果的步骤
2.五子棋游戏
import java.util.Scanner;
class Demo4_2{
public static String[][] board=new String[15][15]; //全局变量 棋盘
public static Scanner scanner=new Scanner(System.in);
public static void main(String[] args){
initBoard(); //初始化棋盘
printBoard(); //打印棋盘
startGame(); //开始游戏
}
public static void startGame(){
int player=0; //计数下棋的总次数
while(isGameContinue()){ //判断游戏是否继续
if(player%2==0){ //黑
System.out.println("黑方下棋");
if(!luozi("X")){
continue;
}
}else{ //白
System.out.println("白方下棋");
if(!luozi("O")){
continue;
}
}
player++;
}
System.out.println("游戏结束!");
}
public static boolean luozi(String chess){ //落子
System.out.print(">>>x=");
int x=scanner.nextInt()-1;
System.out.print(">>>y=");
int y=scanner.nextInt()-1;
if(!board[x][y].equals("+")){ //此处已有棋子
System.out.println("此处已有棋子,请重新下棋!");
return false;
}else{
board[x][y]=chess; //将棋子落入棋盘
printBoard(); //打印落子后的棋盘
return true;
}
}
public static boolean isGameContinue(){ //判断游戏是否继续
for(int i=0;i<board.length;i++){ // 遍历棋盘 判断是否五子连珠
for(int j=0;j<board.length;j++){
if(!board[i][j].equals("+")){ //只有不是棋盘符号时再判断时候连续相等
boolean flag=true;
if(j<11){ //向右
for(int y=1;y<=4;y++){
if(!board[i][j].equals(board[i][j+y])){
flag=false;
break;
}
}
if(flag){
return false;
}
}
if(i<11){ //向下
flag=true;
for(int x=1;x<=4;x++){
if(!board[i][j].equals(board[i+x][j])){
flag=false;
}
}
if(flag){
return false;
}
}
if(i<11&&j<11){ //右下
flag=true;
for(int k=1;k<=4;k++){
if(!board[i][j].equals(board[i+k][j+k])){
flag=false;
}
}
if(flag){
return false;
}
}
if(i>3&&j<11){ //右上
flag=true;
for(int k=1;k<=4;k++){
if(!board[i][j].equals(board[i-k][j+k])){
flag=false;
}
}
if(flag){ //上述四个方向 任意一个方向连珠
return false; //游戏不继续
}
}
}
}
}
return true; //判断完没有连珠 游戏继续
}
public static void printBoard(){ //打印棋盘
for(int i=0;i<board.length;i++){
for(int j=0;j<board[i].length;j++){
System.out.print(board[i][j]+" ");
}
System.out.println();
}
}
public static void initBoard(){ //初始化棋盘
for(int i=0;i<board.length;i++){
for(int j=0;j<board[i].length;j++){
board[i][j]="+";
}
}
}
}
解题思路:
1.创建一个棋盘出来 棋盘 二维数组
2.开始下棋
黑白双方轮流(下棋次数%2) 下棋
输入棋子的坐标 将相应的元素改为棋子元素(黑 白)
3.每次下完一个棋子 判断是否结束(谁赢/和棋)
5.7 数组小结:
1) elementType口 arrayRefVar (元素类型[]数组引用变量 )
elementType arrayRefVar[](元素类型数组引用变量[]) 声明一个数组类型的变量。
推荐使用 elementType[] arrayRefVar 风格。
2)声明数组变量并不会给数组分配任何空间。
数组变量不是基本数据类型变量。数组变量包含的是对数组的引用。
3) 只有创建数组后才能给数组元素賦值。可以使用 new 操作符创建数组。
4)数组中的每个元素都是使用语法 arrayRefVar[index](数组引用变量[ 下标 ])表示的。
下标必须是一个整数或一个整数表达式。
5)创建数组之后,它的大小就不能改变,可以使用 arrayRefVar . length 得到数组的大小。
由于数组的下标总是从 0 开始,所以,最后一个下标总是 arrayRefVar.length-1。
如果试图引用数组界外的元索,就会发生越界错误。
6)当创建一个数组时,如果其中的元素的基本数据类型是数值型,那么赋默认值 0。
字符类型的默认值为 ’\u0000 * , 布尔类型的默认值为 false。
7)Java 有一个称为数组初始化语法的简捷表达式,它将数组的声明、创建和初始化合并为一条语句,其语法为:
元素类型[]数组引用变量={valueO.valuel,....valuek};
8)将数组参数传递给方法时,实际上传递的是数组的引用;
更准确地说,被调用的方法可以修改调用者的原始数组的元素。
9)如果数组是排好序的,对于査找数组中的一个元素而言,二分查找比线性查找更加髙效。
10)可以使用以下语法来声明二维数组变量:
元素类型 [][] 数组变量
11) 使用下面的语法表示二维数组中的每个元素:
数组变董 [ 行下标 ][ 列下标 ];
12) 可以使用数组初始化语法来创建和初始化二维数组:
元素类型 [] 数组变置 ={{ 某行的值 }, { 某行的值 }};
13)可以使用数组的数组构成多维数组。