一、数组的概念以及数组案例
1、容器的概念
用于存储数据的一块内存称为容器,生活中有很多容器,例如 水杯,衣柜,书包,有一定的空间可以存放“东西”
存放在容器中的数据 称为“元素”
2、为什么会存在数组呢?
假如现在要存储全班同学的成绩 , 全班40人,按照定义变量的思维,需要定义40个double类型的变量,每次从40个变量中找某一个变量,操作很麻烦, Java中可以定义一个数据类型存放40个人的成绩 , 这个类型就是数组类型。
数组定义: 它是相同数据类型的有序集合
3、 数组特点
- 数组的长度固定(数组的长度一旦声明,就不能改变)
- 数组中存储的元素数据类型必须相同
- 数组的元素 通过下标访问,且下标默认从0 开始
- 数组类型属于引用数据类型, 数组的元素类型 既可以是基本数据类型,也可以是引用数据类型。
4、创建数组
方式一:
数组存储的数据类型 [] 数组名 = new 数组存储的数据类型[长度];
详解:
数组存储的数据类型 :创建数组容器中可以存储什么数据类型 (基本数据类型 ,引用数据类型)
[] : 表示数组
数组名: 给数组起给名字,遵循标识符规则
new : 创建数组的关键 字
[长度] : 数组的长度 , 这个长度定义后不可改变
例如
int [] arr = new int[3];
new出来的空间在堆内存中,数组是引用数据类型 ,存在内存地址
内存解析: 在堆内存中开辟一段连续的3个长度的int类型的内存空间 ,并由arr变量指向这块内存的地址 (换句话说 arr输出的就是 这个内存的地址)
方式二:
数据类型 [] 数组名 = new 数据类型[]{元素1,元素2,元素3...}
这里的数组长度根据元素的个数自动分配大小
int [] arr = new int[]{90,88,78,92};
或者
int arr [] = new int[]{90,88,78,92}
方式三:
数据类型 [] 数组名 = {元素1,元素2,元素3...};
注意: 这里的元素类型必须满足 数组的元素数据类型
char [] arr = {'a','b','c'};
或者
char arr [] = {'a','b','c'};
5、数组的访问
数组的访问通过索引访问
索引(下标): 每一个数组的元素都有一个编号,这个编号从0开始 , 这个编号称为数组的索引,通过数据名[索引] 访问到数组的元素
例如: 访问数组的第二个元素: 数组名[1]
数组的长度: 数组的长度 声明已固定 ,访问数组的长度 : 数组名.length
数组的最大索引= 数组的长度 -1
数组元素的赋值 :通过索引可以给元素赋值 数组名[索引] = 值
将数据 赋值给 指定索引的 元素
二、、动态数组
1、数组的定义
用于存储相同数据类型的一组连续的存储空间
2、数组的特点:
数组的长度一旦定义,则不可改变
访问数组的元素需要通过下标(索引)访问,下标从0开始
数组是引用数据内存,内存分布在堆内存中,数组的变量存储的内存地址
3、动态数组:
由于数组的长度定义后不能改变,所谓“动态数组”是可以增加数组的长度, 所以Java实现动态数组是改变数组变量指向不同的内存的地址。 本质并没有将数组的长度改变。
动态数组的本质: 将内存空间的改变, 以及指向数组内存的地址改变
操作1 : 给数组 添加新元素 ,可添加在最后面 ,也可添加到指定位置
/**
* 添加元素 (添加到末尾)
*/
public static int [] addEle(int [] array ,int num){
// 目标数组 添加的原始
//int [] array = {10,9,3,2,1};
// 1、创建临时数组的变量
int [] tempArray = new int[array.length+1];
//2、将目标数组的元素 copy到 临时数组的内存中
for(int i = 0 ;i<array.length;i++){
tempArray[i]= array[i];
}
// 3、将添加的元素放入临时数组中
tempArray[tempArray.length-1] = num;
// 4、将目标数组的地址 指向 临时数组的地址
array= tempArray; // 由于tempArray 是局部变量, 方法执行完内存自动回收 ,
// 如果不返回 没有地址指向tempArray的内存
// 如果返回并接收,说明这块内存仍然有用。
return array;
}
/**
* 将元素num 添加到指定index的位置
*/
public static int [] addEle(int [] arr , int num ,int index){
// 1、创建临时数组的大小
int [] tempArray = new int[arr.length+1];
//2、遍历arr
for(int i = 0 ; i<=arr.length;i++){
// 如果i<index
if(i<index){
tempArray[i] = arr[i];
}else if(i==index){ // 2
tempArray[i] = num;
}else{ // i > index
// i=3 arr[i-1] 10 9 3 2 1 -> 10 9 5 3 0 0
// i =4 array[i-1] 2-> 10 9 5 3 2 0
// i=5 array[4] 1 -> 10 9 5 3 2 1
tempArray[i] = arr[i-1];
}
}
// 赋值
arr = tempArray;
return arr;
}
操作2: 删除元素 ,删除指定下标的元素
/**
* 删除指定下标的元素
* @param arr 目标数组
* @param index 删除的下标
* @return 删除之后的数组
*/
public static int [] removeEle(int [] arr, int index){
// 1、创建一个临时数组 用于存放删除后的原始
int [] tempArray = new int [arr.length-1];
// 2、遍历目标数组
for(int i = 0 ;i<arr.length;i++){
if(i<index){
tempArray[i] = arr[i];
}else if(i==index){
continue;
}else {//i>index
tempArray[i-1] = arr[i];
}
}
// 3 将目标数组的地址变换成 新数组的地址
arr=tempArray;
return arr;
}
三、数组的排序
排序: 将一组数列(无序的)按照从小到大或者从大到小的顺序排列。
1、冒泡排序
从第一个数开始, 与它相邻的数比较 ,较大(或较小)的数放在后面,最终比较一轮之后,得出最大(或最小)的数放在最后
比较思路:
冒泡排序的规则
* 1、从第一个数开始,将这个数 与它相邻的数比较 ,如果 这个数大于它相邻的数
* 则两个数交换位置
* i=0 相邻i=1
* 2、依次 从第二个数开始,再将这个数与它相邻的数比较,如果第二个数大于相邻的数
* 则继续交换
* 依次类推, 到倒数第二个截止 ,直到将最大的数放在最后面
* 3、重复以上1,2步骤
/
public static void main(String[] args) {
int [] array = {5,4,3,2,1};
//用于交换的临时变量
int temp=0;
for(int j =0;j<array.length-1;j++) {
for (int i = 0; i < array.length -j-1; i++) {
// 相邻的数比较
if (array[i] > array[i + 1]) {
temp = array[i];
array[i] = array[i + 1];
array[i + 1] = temp;
}
}
System.out.println("比较一轮之后:" + Arrays.toString(array));
}
}
2、选择排序
/**
* 选择排序: 从一堆数中选择一个最小数 放在第一个位置,再从一堆数中选择一个
* 最小数放在第二个位置, 依次 将一堆数的最小数按顺序排放。
* 步骤: 1、假设第一个数是最小数,需要定义最小数的下标minIndex=0
* 将这个数与后面的每一个数比较,找到最小数的下标即可
* 2、将第一个数与最小数的下标交换 ,得出最小数在第一位。
* 3、 依次类推, 将已比较的数 忽略,继续从生下的元素中找足最小数,放入已比较的数的下一位
* 直到整个数列比较结束
* @param args
*/
public static void main(String[] args) {
int [] array = {3,2,1,5,7,4};
for(int j=0;j<array.length-1;j++) {
// 假设第一个数是最小数
int minIndex = j;
// 为什么i =j+1 因为初始值要略过已比较的下标
for (int i = 1+j; i < array.length; i++) {
if (array[minIndex] > array[i]) {
minIndex = i;
}
}
// 将这个最小数放在 第一位
int temp = 0;
temp = array[j];
array[j] = array[minIndex];
array[minIndex] = temp;
System.out.println("----第一次完成后:" + Arrays.toString(array));
}
System.out.println("最后的排序:"+Arrays.toString(array));
}
}
3、插入排序
/**
* 插入排序
* 1、从第一个元素开始,假设第一个元素是已排好序的
* 2、从下一个元素开始,依次比较它前面的所有元素(从后向前扫描)
* 3、 如果这个元素 小于它前面的元素 则两两交换 ,
* 如果这个元素 大于它前面的元素,则不交换
* 4、依次重复2,3步骤 ,直到将所有数 比较完成
* 5,4,3,2,1
*
* 4 5 3 2 1 i从1开始
*
* 4 3 5 2 1 i从2开始
* 3 4 5 2 1
*
* 3 4 2 5 1 i从3开始
* 3 2 4 5 1
* 2 3 4 5 1
*
* 2 3 4 1 5 i从4开始
* 2 3 1 4 5
* 2 1 3 4 5
* 1 2 3 4 5
* @param args
*/
public static void main(String[] args) {
int [] array = {5,4,3,2,1};
// 外层循环循环 每一个数的比较次数
for(int j=0;j<array.length-1;j++) {
int temp = 0;
for (int i = 1+j; i > 0; i--) {
if (array[i] < array[i - 1]) {
temp = array[i];
array[i] = array[i - 1];
array[i - 1] = temp;
}
}
System.out.println("每一次完成后的结果:"+ Arrays.toString(array));
}
System.out.println("最后一次完成后的结果:"+Arrays.toString(array));
}
四、二维数组以及多维数组
1、二维数组定义:
在一维数组中定义每一个元素也是一个数组元素,这样的数组称为“二维数组”
多维数组就是在一维数组上再次定义二维数组或三维数组等。
一维数组定义 int [] array = { 1, 2 , 3}
//定义三个长度的二维数组,其数组的每一个元素是一个一维数组
int [][] arrays = {{} ,{} ,{}} ;
或者
int [][] arrays = new int [3][2]; // 左边的[]中表示二维数组的长度 ,其中2可以省略,3 不能省略
// 注意: 等号左边有几个[] 就表示几维
// 1、定义二维数组
int [][] array;
// 定义时给二维数组赋值 3个长度的二维数组 里面的一维数组的长度不一定相等
int [][] array2 = {{1,2,3},{4,5},{7,8}};
// 定义时只指定大小 不给定初始值
int [][] array3 = new int[3][]; // 等价 {{},{},{}}
// array3[0][0]=1; // 赋值时 空指针异常 ,因为里面的一维数组是空的
//定义一个3个长度的二维数组,里面的元素长度是2
int array4 [][] = new int[3][2];
//给元素赋值
array4[0][0] =1;
// 输出二维数组中的所有元素
for(int i=0;i<array4.length;i++){
// System.out.println(array4[i]);
for(int j=0;j<array4[i].length;j++){
System.out.println(array4[i][j]);
}
}
2、二维数组的应用
1、定义一个5*5的二维矩阵 ,随机赋值100以内的整数 并输出这个矩阵 ,并计算最大值最小值
public static void main(String[] args) {
int[][]array=new int[5][5];
array=array(array);
}
public static int[][]array(int[][]array){
int max=0;
int min=100; //先赋予最小值一个最大元素,以作比较
for(int i=0;i<5;i++){
for (int j=0;j<5;j++){
array[i][j]=(int)(Math.random()*100); //将100以内随机数赋值给数组
System.out.print(array[i][j]+" ");
if(max<array[i][j]){
max=array[i][j]; //得出最大值
}
if(min>array[i][j]){
min=array[i][j]; //得出最小值
}
}
System.out.println();
}
System.out.println("最大值:"+max);
System.out.println("最小值:"+min);
return array;
}
2、五子棋游戏
public class wuziqi {
static String [][] qipan = new String[20][20]; //全局变量,定义棋盘
static Scanner sc = new Scanner(System.in);
public static void main(String[] args) {
// 1、 初始化棋盘
for(int i=0;i<qipan.length;i++){
for(int j = 0 ;j <qipan[i].length;j++){
qipan[i][j]="+ "; //初始化棋盘,赋予+号
}
}
// 打印棋盘
printPan(); //输出初始棋盘
while(true) {
// 2、开始玩游戏
System.out.println("请玩家(黑棋)落入棋子,输入行和列");
int row = sc.nextInt();
int column = sc.nextInt();
if(row>20 || row<1 || column>20 || column<1){ //判断所下位置是否属于棋盘内
System.out.println("玩家的落入点不在棋盘上。请重新录入");
continue; //跳出当前循环,重新开始循环
}else{
// 判断当前的位置是否为可落入棋子
if(qipan[row-1][column-1]!="+ "){
System.out.println("玩家的落入点已存在棋子,不能落入");
continue; //跳出当前循环,重新开始循环
}else{
qipan[row-1][column-1]="● ";
}
}
// 3、白棋落入
int row1 = 0;
int column1 = 0;
// 验证 白棋落入是否为有效位置
while(true){
row1 = (int)(Math.random()*20);
column1 = (int)(Math.random()*20);
if(qipan[row1][column1]=="+ "){
break; //结束当前循环
}
}
qipan[row1][ column1]="○ ";
// 打印棋盘
printPan(); //输出落棋后的棋盘信息
// 判断输赢
if(judge()){ //遍历棋盘信息判断输赢;若赢了便结束所有循环,没有则继续
System.out.println(s+"赢了,游戏结束!!");
break; //结束所有循环
}
}
}
/**
* 打印棋盘
*/
public static void printPan(){
for(int i=0;i<qipan.length;i++){
for(int j = 0 ;j <qipan[i].length;j++){
System.out.print(qipan[i][j]);
}
System.out.println();
}
}
/**
* 判断输赢
* @return
*/
static String s=""; // 全局变量 用于表示某一方
public static boolean judge(){
boolean flag=false;
for(int i =0;i<qipan.length;i++) {
for (int j = 0; j < qipan[i].length; j++) {
if (qipan[i][j] == "● " || qipan[i][j] == "○ ") {
// 判断右斜下方向
if (i < 16 && j < 16
&& qipan[i][j] == qipan[i + 1][j + 1]
&& qipan[i][j] == qipan[i + 2][j + 2]
&& qipan[i][j] == qipan[i + 3][j + 3]
&& qipan[i][j] == qipan[i + 4][j + 4]
) {
s = qipan[i][j];
flag = true;
break;
}else if(i>4&&j<16&&qipan[i][j]==qipan[i-1][j+1]
&&qipan[i][j]==qipan[i-2][j+2]
&&qipan[i][j]==qipan[i-3][j+3]
&&qipan[i][j]==qipan[i-4][j+4]){
//判断右斜上
s = qipan[i][j];
flag = true;
break;
} else if (j < 16 && qipan[i][j] == qipan[i][j + 1]
&& qipan[i][j] == qipan[i][j +2]
&& qipan[i][j] == qipan[i][j +3]
&& qipan[i][j] == qipan[i][j +4]) {
// 判断 右横向
s = qipan[i][j];
flag = true;
break;
} else if (j >4 && qipan[i][j] == qipan[i+1][j ]
&& qipan[i][j] == qipan[i+2][j ]
&& qipan[i][j] == qipan[i+3][j ]
&& qipan[i][j] == qipan[i+4][j ]) {
// 判断 左横向
s = qipan[i][j];
flag = true;
break;
}else if(i<16&&qipan[i][j] == qipan[i+1][j]
&&qipan[i][j] == qipan[i+2][j]
&&qipan[i][j] == qipan[i+3][j]
&&qipan[i][j] == qipan[i+4][j]){
//判断向下纵向
s = qipan[i][j];
flag = true;
break;
}else if(i>4&&qipan[i][j]==qipan[i-1][j]
&&qipan[i][j]==qipan[i-2][j]
&&qipan[i][j]==qipan[i-3][j]
&&qipan[i][j]==qipan[i-4][j]){
//判断向上纵向
s = qipan[i][j];
flag = true;
break;
}else if(i<16&&j>4&&qipan[i][j]==qipan[i+1][j-1]
&&qipan[i][j]==qipan[i+2][j-2]
&&qipan[i][j]==qipan[i+3][j-3]
&&qipan[i][j]==qipan[i+4][j-4]){
//判断左斜下
s = qipan[i][j];
flag = true;
break;
}else if(i>4&&j>4
&& qipan[i][j] == qipan[i-1][j-1]
&& qipan[i][j] == qipan[i-2][j-2]
&& qipan[i][j] == qipan[i-3][j-3]
&& qipan[i][j] == qipan[i-4][j-4]){
//判断左斜上
s = qipan[i][j];
flag = true;
break;
}
}
}
}
return flag;
}
}