数组
数组就是一组数据, 可以存放多个相同数据类型数据, 是属于引用类型
数组的创建与使用
- 动态初始化
数据类型 数组名[] = new 数据类型[大小]
double[] abc 与 double abc[] 等价
使用下标来进行赋值
- 先声明数组 然后创建数组
double scores[]; // 先声明这是一个数组 (还没分配内存空间)
scores = new double[10]; // 分配内存空间 下面就可以存放数据了
- 静态初始化
如: int a[] = {1,2,3,4,5}; // 用于知道有多少个数据存储的场景
注意事项
数组属于引用类型, 数组型数据为对象
数组赋值机制
基本数据类型是值传递 (复制另一份数值 地址不一样) 形参的任何改变不会影响实参~
数组在默认情况是引用传递, 赋的是地址 (地址一样) (拷贝的是地址, 赋值后 引用到同一个地址)
(如在函数参数传递时为引用传递, 那若函数的的引用类型 = null 与不会影响主函数 引用类型数据的内容)
在栈开辟一个空间 指向一块内存 (存的是地址) 然后该内存地址里的内容是在堆中存放
数组反转
public static void main(String[] args) {
int[] arr = {11,22,33,44,55,66};
for (int i = 0; i<arr.length/2;i++){ // arr[5] <-> arr[0] arr[4] <-> arr[1] arr[3] <-> arr[2]
int temp = arr[i];
arr[i] = arr[arr.length-i-1];
arr[arr.length-i-1] = temp;
}
// 当然可以让 arr 逆序赋值给 arr2
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
数组扩容
重新定义一个数组 然后赋值给那个数组, 然后让旧数组指向新定义的扩容数组即可
public static void main(String[] args) {
// 数组扩容
int[] arr = {1,2,3};
int[] newArr = new int[arr.length+1];
for (int i = 0; i<arr.length; i++){
newArr[i] = arr[i];
}
newArr[newArr.length-1] = 5; // 扩容的那个数
arr = newArr; // 让旧数组指向新数组~
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" "); // 1 2 3 5 扩容成功~
}
}
public static void main(String[] args) {
// 数组动态扩容
Scanner myScanner = new Scanner(System.in);
int[] arr = {1,2,3};
while(true){
int[] newArr = new int[arr.length+1];
for (int i = 0; i<arr.length; i++){
newArr[i] = arr[i];
}
System.out.println("请输入想要添加的元素");
int add = myScanner.nextInt();
newArr[newArr.length-1] = add; // 扩容的那个数
arr = newArr; // 让旧数组指向新数组~
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" "); // 1 2 3 5 扩容成功~
}
System.out.println();
// 是否继续添加
System.out.println("是否需要继续添加数据y/n");
char keyboard = myScanner.next().charAt(0);
if(keyboard == 'n'){
break;
}else if(keyboard == 'y'){
continue;
} // 可以增加逻辑增加防止乱输入
}
System.out.println("你已退出添加数组元素程序");
}
数组的缩减 思路类似
数组排序
冒泡排序
public static void main(String[] args) {
// 冒泡排序
int[] arr = { 2, 3, 1, 5, 78, 32, -1, -999 };
boolean flag = true;
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;
flag = false;
}
}
if (flag) {
break;
}
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
}
二维数组
二维数组本质是由多个一维数组组成的, 其各个一维数组长度可以一致, 也可以不相同
public static void main(String[] args) {
// 二维数组 第一个[]表示这个二维数组有多少个元素 第二个是每个元素里有多少个元素
// 二维数组中的一维数组元素个数不一定全部一样
int[][] arr1 = { { 1, 2, 3, 4 }, { 2, 3, 4, 5,6,7,8,9}, { 3, 4, 5, 6 }, { 4, 5, 6, 7 } };
for (int i = 0; i < arr1.length; i++) {
for (int j = 0; j < arr1[i].length; j++) {
System.out.print(arr1[i][j]);
}
System.out.println();
}
}
初始化形式与一维数组的类似
内存分析
二维数组的简单应用(动态二维数组)
public static void main(String[] args) {
/* 动态创建二维数组, 并打印
i = 0: 1
i = 1: 2 2
i = 2: 3 3 3
*/
int[][] arr = new int[3][]; // 创建二维数组, 只是创建了一维数组的个数
for (int i = 0; i < arr.length; i++) {
// 给二维数组的每一个元素(即一维数组)开辟内容空间
arr[i] = new int[i + 1]; // 若不给一维数组开辟空间, 那么 arr[i] 就是 null
// 遍历一维数组, 并给一维数组赋值~
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();
}
}
杨辉三角(二维数组的经典应用!)
第一种方法是一开始就创建了10*10的二维数组 比较费空间 (因为有些空间浪费了, 没用来存数据)
第二种方法是先是定下有多少个一维数组(即二维数组的行数), 然后再动态给一维数组开辟空间 然后赋值~
public static void main(String[] args) {
// 打印杨辉三角~
int[][] arr = new int[10][10];
arr[0][0] = 1;
arr[1][0] = 1;
arr[1][1] = 1; // 因为比较特殊 我就先初始化了, 当然初始化的工作也能放到循环里面进行
for (int i = 2; i < arr.length; i++) {
for (int j = 0; j <= i; j++) {
if (j == 0 || i == j) {
arr[i][j] = 1;
} else { // 除了一头一尾 那就是通过公式计算值了
arr[i][j] = arr[i - 1][j] + arr[i - 1][j - 1];
}
}
}
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j <= i; j++) {
System.out.print(arr[i][j]+" ");
}
System.out.println();
}
}
public static void main(String[] args) {
// 打印杨辉三角~
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++) {
// 每行数据的一头一尾都是1!
if(j == 0 || j == arr[i].length-1){
arr[i][j] = 1;
}else{ // 其余的就可以 按照公式计算~
arr[i][j] = arr[i - 1][j] + arr[i - 1][j - 1];
}
}
}
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j <= i; j++) {
System.out.print(arr[i][j]+" ");
}
System.out.println();
}
}
练习题
已知有一个升序序列, 当添加一个数据后, 序列仍有序, 该如何实现?
public static void main(String[] args) {
// 已知有一个升序序列, 当添加一个数据后, 序列仍有序
int[] arr = { 10, 12, 45, 90 };
int index = -1; // 寻找待插入的位置
while (true) {
Scanner myscanner = new Scanner(System.in);
System.out.println("请输入待插入的数据");
int insertData = myscanner.nextInt();
for (int i = 0; i < arr.length; i++) {
if (arr[i] >= insertData) {
index = i;
break;
}
}
if (index == -1)
index = arr.length; // 遍历完发现index数值没有变化 说明数组的元素都比待插入元素小
int[] newArr = new int[arr.length + 1]; // 扩容后的数组 用于存放新的数组~
for (int j = 0; j < index; j++) {
newArr[j] = arr[j];
}
for (int j = index + 1; j < newArr.length; j++) {
newArr[j] = arr[j - 1];
}
newArr[index] = insertData;
// 拷贝数组的另外一种做法 (与上面方法类似)
for (int i = 0, j = 0; i < newArr.length; i++) {
if (i != index) {
newArr[i] = arr[j];
j++;
} else {
newArr[i] = insertData;
}
}
arr = newArr; // 让arr指向新的数组 -> 完成扩容~
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
System.out.println("请问还需要输入数据么?(y/n)");
char character = myscanner.next().charAt(0);
if (character == 'y') {
continue;
} else {
break;
}
}