多维数组
java 支持两种数据类型的多维数组。第一种是矩形数组,也称等长数组。在二维矩形数组中,每一行有相同的列数。例:int[][] A = new int[4][2];
java 支持的第二种多维数组是交错数组,即所谓的正交数组、变长数组、锯齿形数组。在二维交错数组中,每一行可以有不同的列数。
在多维数组中,比较常用的是二维数组。多维数组的声明、实例化和初始化与一维数组的声明、实例化和初始化相类似。声明多维数组时,用[]对表示维数。两个[]对表示二维数组,3个[]对表示三维数组,以此类推。
基本数据类型的数组未初始化的值均为 0 , 对象数组 :初始化为null , Boolean:初始化默认为false,字符串:/u0000。
- 举例:
package com.k;
import java.util.Arrays;
public class Yichang {
public static void main(String[] args){
int[][] array = {{1, 2, 3},{4, 5, 6}};
int[][] brray = new int[2][3];
int[][] arr1 = new int[2][3]; //声明并创建一个二维整型数组(2行3列)
int[][] arr2 = {{1,2,3},{4,5,6}}; //声明并初始化一个二维整型数组(2行3列,6个元素)
int[][] arr3 = new int[][]{{1,2,3},{4,5,6}}; //声明创建并初始化
int[][] arr4 = new int[3][];
arr4[0] = new int[2];
arr4[1] = new int[4];
arr4[2] = new int[5]; // 不规则数组
System.out.println(Arrays.deepToString(brray));
System.out.println(Arrays.deepToString(arr1));
System.out.println(Arrays.deepToString(arr2));
System.out.println(Arrays.deepToString(arr3));
System.out.println(Arrays.deepToString(arr4));
}
}
[[0, 0, 0], [0, 0, 0]]
[[0, 0, 0], [0, 0, 0]]
[[1, 2, 3], [4, 5, 6]]
[[1, 2, 3], [4, 5, 6]]
[[0, 0], [0, 0, 0, 0], [0, 0, 0, 0, 0]]
二维数组的拷贝
二维数组的拷贝和一维数组的拷贝类似,同样有四种,分别是for循环拷贝,Object.clone(),System.arraycopy(),Arrays.copyOf() 四种拷贝方法。下面是代码示例:
- for循环拷贝(浅拷贝)
package com.k;
import java.util.Arrays;
public class Yichang {
public static void main(String[] args){
int[][] array = {{1, 2, 3},{4, 5, 6}};
int[][] brray = new int[2][3];
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
brray[i][j] = array[i][j];
}
}
System.out.println(Arrays.deepToString(brray));
}
}
[[1, 2, 3], [4, 5, 6]]
class TestArray2 {
private int val;
public void setVal(int val) {
this.val = val;
}
public int getVal() {
return this.val;
}
}
public class Yichang {
public static void main(String[] args) {
TestArray2[][] testArray2 = new TestArray2[2][2];
testArray2[0][0] = new TestArray2();
testArray2[0][1] = new TestArray2();
testArray2[1][0] = new TestArray2();
testArray2[1][1] = new TestArray2();
TestArray2[][] testArray3 = new TestArray2[2][2];
for (int i = 0; i < testArray2.length; i++) {
for (int j = 0; j < testArray2.length; j++) {
testArray3[i][j] = testArray2[i][j];
}
}
System.out.println("拷贝完成");
for (int i = 0; i < testArray2.length; i++) {
for (int j = 0; j < testArray2.length; j++) {
System.out.print(testArray2[i][j].getVal() + " ");
}
}
System.out.println();
for (int i = 0; i < testArray3.length; i++) {
for (int j = 0; j < testArray3.length; j++) {
System.out.print(testArray3[i][j].getVal() + " ");
}
}
System.out.println();
testArray2[0][0].setVal(100);
System.out.println("修改完成");
for (int i = 0; i < testArray2.length; i++) {
for (int j = 0; j < testArray2[i].length; j++) {
System.out.print(testArray2[i][j].getVal()+" ");
}
}
System.out.println();
for (int i = 0; i < testArray3.length; i++) {
for (int j = 0; j < testArray3[i].length; j++) {
System.out.print(testArray3[i][j].getVal()+" ");
}
}
System.out.println();
}
}
拷贝完成
0 0 0 0
0 0 0 0
修改完成
100 0 0 0
100 0 0 0
- ** Arrays.deepToString() 方法是多维数组以字符串形式输出。**
- Object.clone()
class TestArray2 {
private int val;
public void setVal(int val) {
this.val = val;
}
public int getVal() {
return this.val;
}
}
public class Yichang {
public static void main(String[] args) {
TestArray2[][] testArray2 = new TestArray2[2][2];
testArray2[0][0] = new TestArray2();
testArray2[0][1] = new TestArray2();
testArray2[1][0] = new TestArray2();
testArray2[1][1] = new TestArray2();
TestArray2[][] testArray3 = new TestArray2[2][2];
for (int i = 0; i < testArray2.length; i++) {
for (int j = 0; j < testArray2.length; j++) {
testArray3[i] = testArray2[i].clone();
}
}
System.out.println("拷贝完成");
for (int i = 0; i < testArray2.length; i++) {
for (int j = 0; j < testArray2.length; j++) {
System.out.print(testArray2[i][j].getVal() + " ");
}
}
System.out.println();
for (int i = 0; i < testArray3.length; i++) {
for (int j = 0; j < testArray3.length; j++) {
System.out.print(testArray3[i][j].getVal() + " ");
}
}
System.out.println();
testArray2[0][0].setVal(100);
System.out.println("修改完成");
for (int i = 0; i < testArray2.length; i++) {
for (int j = 0; j < testArray2[i].length; j++) {
System.out.print(testArray2[i][j].getVal()+" ");
}
}
System.out.println();
for (int i = 0; i < testArray3.length; i++) {
for (int j = 0; j < testArray3[i].length; j++) {
System.out.print(testArray3[i][j].getVal()+" ");
}
}
System.out.println();
}
}
拷贝完成
0 0 0 0
0 0 0 0
修改完成
100 0 0 0
100 0 0 0
- System.arraycopy():
for (int i = 0; i < testArray2.length; i++) {
System.arraycopy(testArray2[i], 0, testArray3[i], 0, testArray2[i].length);
}
- Arrays.copyOf():
for (int i = 0; i < testArray2.length; i++) {
testArray3[i] = Arrays.copyOf(testArray2[i], testArray2[i].length);
}
匿名数组
使用数组时,一般需要先声明数组变量,然后创建并初始化一个数组并赋值给声明的数组变量。Java语言也支持匿名数组,即在需要数组变量的地方,直接通过下列形式创建一个匿名数组。
- new 数组类型[] {初始值设定项}; //创建一个一维匿名数组
- new 数组类型[][] {初始值设定项};//创建一个二维匿名数组
可变参数
Java可变参数,适用于参数个数不确定,类型确定的情况,Java把可变参数当做数组处理。
可变参数使用时需要注意:
1.只能出现在参数列表的最后;
2.“…”位于变量类型和变量名之间,前后有无空格都可以;
3.调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,在方法体中以数组的形式访问可变参数。
时间复杂度:
一个算法中的语句执行次数称为语句频度或时间频度。记为T(n)。 时间复杂度,在刚才提到的时间频度中,n称为问题的规模,当n不断变化时,时间频度T(n)也会不断变化。但有时我们想知道它变化时呈现什么规律。为此,我们引入时间复杂度概念。 一般情况下,算法中基本操作重复执行的次数是问题规模n的某个函数,用T(n)表示,若有某个辅助函数f(n),使得当n趋近于无穷大时,T(n)/f(n)的极限值为不等于零的常数,则称f(n)是T(n)的同数量级函数。记作T(n)=O(f(n)),称O(f(n)) 为算法的渐进时间复杂度,简称时间复杂度。
按数量级递增排列,常见的时间复杂度有:常数阶O(1),对数阶O(log2n),线性阶O(n), 线性对数阶O(nlog2n),平方阶O(n2),立方阶O(n3),…, k次方阶O(nk),指数阶O(2n)。随着问题规模n的不断增大,上述时间复杂度不断增大,算法的执行效率越低。
数组的排序
- 冒泡排序
- 直接插入排序
- 选择排序
冒泡排序
冒泡排序(Bubble Sort),又被称为气泡排序或泡沫排序。它是一种较简单的排序算法。它会遍历若干次要排序的数列,每次遍历时,它都会从前往后依次的比较相邻两个数的大小;如果前者比后者大,则交换它们的位置。这样,一次遍历之后,最大的元素就在数列的末尾! 采用相同的方法再次遍历时,第二大的元素就被排列在最大元素之前。重复此操作,直到整个数列都有序为止!
图文举例冒泡排序过程:数组{20,40,30,10,60,50}排序
- 举例:
public class PaiXu {
public static void MaoPao(int[] array){
int tmp = 0;
Boolean swap = true;
for(int i = 0;i <= array.length-1; i++){
for(int j = 0;j < array.length-1-i;j++){
if(array[j] > array[j+1]){
tmp = array[j];
array[j] = array[j+1];
array[j+1] = tmp;
swap = true;
}
}
if (!swap){
break; //冒泡排序及优化
}
}
}
public static void main(String[] args) {
int[] array={2,1,5,10,3,8};
MaoPao(array);
System.out.println(Arrays.toString(array));
}
}
[1, 2, 3, 5, 8, 10]
- 冒泡排序时间复杂度:
最坏的时间复杂度为O(n^2),最好的时间复杂度为O(n)。 - 冒泡排序的稳定性:
冒泡排序是稳定的算法,它满足稳定算法的定义。
算法稳定性 – 假设在数列中存在a[i]=a[j],若在排序之前,a[i]在a[j]前面;并且排序之后,a[i]仍然在a[j]前面。则这个排序算法是稳定的!
直接插入排序
直接插入排序(Straight Insertion Sort)的基本思想是:把n个待排序的元素看成为一个有序表和一个无序表。开始时有序表中只包含1个元素,无序表中包含有n-1个元素,排序过程中每次从无序表中取出第一个元素,将它插入到有序表中的适当位置,使之成为新的有序表,重复n-1次可完成排序过程。
- 举例:
public class PaiXu {
public static void insert(int[] array){
int tmp = 0;
int j = 0;
for(int i = 1;i < array.length;i ++){
tmp = array[i];
for(j = i - 1;j >= 0; j --){
if (array[j] > tmp){
array[j + 1] = array[j];
}else{
break;
}
}
array[j + 1] = tmp;
}
}
public static void main(String[] args) {
int[] array={2,1,5,10,3,8};
insert(array);
System.out.println(Arrays.toString(array));
}
}
[1, 2, 3, 5, 8, 10]
- 直接插入排序时间复杂度:
最坏的时间复杂度为O(n^2),当数组有序时,最好的时间复杂度为O(n)。 - 直接插入排序的稳定性:
直接插入排序是稳定的算法,它满足稳定算法的定义。
算法稳定性 – 假设在数列中存在a[i]=a[j],若在排序之前,a[i]在a[j]前面;并且排序之后,a[i]仍然在a[j]前面。则这个排序算法是稳定的!
选择排序
选择排序(Selection sort)是一种简单直观的排序算法。它的基本思想是:从数组的第一个元素开始,与其后面相邻的元素比较大小,如果大于则交换次序,以此类推,直到所有元素均排序完毕。
- 举例:
public class PaiXu {
public static void selectedSort(int[] array){
int tmp = 0;
for (int i = 0;i < array.length;i ++){
for (int j = i+1;j < array.length;j++){
if(array[i] > array[j]){
tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
}
}
}
public static void main(String[] args) {
int[] array={2,1,5,10,3,8};
selectedSort(array);
System.out.println(Arrays.toString(array));
}
}
[1, 2, 3, 5, 8, 10]
- 选择排序时间复杂度:
最坏的时间复杂度为O(n^2),当数组有序时,最好的时间复杂度为O(n)。 - 选择排序的稳定性:
选择排序是不稳定的算法,它是跳跃式的交换次序。
以上的排序方法都是升序排列,排序是在内部排序,在内存中处理。还有Arrays.sort() 方法也是升序排序的一种方法,底层是优化后的快速排序,相关具体例子在上一节博客中。 - 练习:3阶魔方阵。
package mypratice;
import java.util.Scanner;
/**
* @Package: mypratice
* @Author:kkz
* @Description:
* @Date:Created in 2018/10/24 0:34
*/
public class Mofang {
private static void Magic(int n){
int[][] array= new int[n][n]; //定义二位数组,默认赋0值
int row = 0;
int col=n/2; //行列赋初值
for(int i = 1;i <= n * n;i ++){
array[row][col] = i; //将1-9放入魔方阵中
row --;
col ++; //放在第一个数的上一行,下一列
//行列同时越界:放到上个数的正下方
if(row < 0 && col >= n){
row += 2;
col --;
}
// 行越界:把这个数放到同列的末行
else if(row < 0){
row = n-1;
}
// 列越界:把这个数放到同行的首列
else if(col >= n){
col = 0;
}
//冲突: 放到上个数的正下方
else if(array[row][col] != 0){
row += 2;
col --;
}
}
//打印数组
for(int i = 0;i < n;i ++){
for(int j = 0;j < n;j ++){
System.out.print(array[i][j] + " ");
}
System.out.println();
}
}
public static void main(String[] args) {
//输入n的值
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
Magic(n);
}
}
3
8 1 6
3 5 7
4 9 2
Over…