目录
前言:
当我们需要存储大量的相同数据时,我们就可以考虑数组这种存储数据的结构来实现。在 Java 中数组具有如下的特点:
-
数组的长度固定,当数组定义好的,它的长度是不能发生变化的
-
数组中的元素类型是一致
-
数组中每个元素都有与之对应的下标,通过下标可以获取到数组中对应的元素
-
数组中的元素在内存是连续存放的
一、数组的定义
在 Java 中数组定义有以下几种方式:
// 第一种:
数据类型[] 数组名称 = new 数据类型[元素个数/长度];
// 第二种:
数据类型[] 数组名称 = new 数据类型[]{元素1,元素2,....,元素n};
// 第三种:
数据类型[] 数组名称 = {元素1,元素2,....,元素n};
示例:
public class ArrayDemo01 {
public static void main(String[] args) {
// 第一种方式:数据类型[] 数组名称 = new 数据类型[长度];
int[] arr = new int[5];
int tmp[] = new int[6];
// 第二种方式:数据类型[] 数组名称 = new 数据类型[]{元素1,元素2,...,元素n};
String[] strs = new String[]{"hello", "world", "java", "python"};
// 第三种方式:数据类型[] 数组名称 = {元素1,元素2,...,元素n};
String[] strs1 = {"hello", "world", "java", "python"};
}
}
二、数组的赋值
public class ArrayDemo02 {
public static void main(String[] args) {
int[] nums = new int[5];
// 1. 获取数组元素个数,通过数组对象的 length 属性
System.out.println(nums.length);
// 2. 获取第一个元素,它需要通过数组的下标,而下标是从 0 开始到数组长度 - 1。
// 0 ,原因是当创建了数组后,没有给数组的元素赋值,它的默认是会根据数组类型来定。
// 如果数组类型是 int ,那么它元素默认值为 0
// 如果数组类型是 String,那么它的元素默认值为 null
// 如果数组类型是 double ,那么它的元素默认值是 0.0
// 如果数组类型是 char,那么它的元素默认是是 ''
System.out.println(nums[0]); // 0
// 3. 给数组的元素赋值
for (int i = 0; i < nums.length; i++) {
nums[i] = (i + 10) % 7;
}
System.out.println("-------------");
// 4. 显示所有元素
for (int i = 0; i < nums.length; i++) {
System.out.println(nums[i]);
}
}
}
三、数组排序
3.1 冒泡排序
思路:相邻两个元素进行比较,如果前面元素比后面元素大就交换位置,每一趟执行完后,就会得到最大的数。
排序过程:
排序实现:
/**
* 冒泡排序
*/
public class BubbleSort {
public static void main(String[] args) {
int[] arr = {6, 9, 1, 5, 2, 3, 8, 4, 7};
print(arr);
// 排序后
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length -1 - i; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
print(arr);
}
private static void print(int[] arr) {
for (int el : arr) {
System.out.print(el + "\t");
}
System.out.println();
}
}
3.2 选择排序
思路:每次都从剩余元素中找到最小的元素并将其放到有序数组的最后。
排序过程:
排序实现:
/**
* 选择排序
*/
public class SelectSort {
public static void main(String[] args) {
int[] arr = {6, 9, 1, 5, 2, 3, 8, 4, 7};
print(arr);
// 排序
for (int i = 0; i < arr.length - 1; i++) {
for (int j = i + 1; j < arr.length; j++) {
if (arr[i] > arr[j]) {
int temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
}
}
print(arr);
}
private static void print(int[] arr) {
for (int el : arr) {
System.out.print(el + "\t");
}
System.out.println();
}
3.3 插入排序
思路:默认第一个元素是有序的,然后从后面元素取出元素也前面的元素进行比较,然后找到合适的位置结束。
排序过程:
/**
* 插入排序
*/
public class InsertSort {
public static void main(String[] args) {
int[] arr = {6, 9, 1, 5, 2, 3, 8, 4, 7};
print(arr);
int e;
int j;
for (int i = 1; i < arr.length; i++) {
e = arr[i];
for (j = i; j > 0 && arr[j - 1] > e; j--) {
arr[j] = arr[j - 1];
}
arr[j] = e;
}
print(arr);
}
private static void print(int[] arr) {
for (int el : arr) {
System.out.print(el + "\t");
}
System.out.println();
}
}
四、数组查找
4.1 线性查找
思路:将被查找的元素与数组中的每一个元素从前往后一匹配,如果能匹配上则找到,否则找不到
public class LineSearch {
public static void main(String[] args) {
int[] arr = {6, 9, 1, 5, 2, 3, 8, 4, 7};
int key = 8; // 要查找的元素
int index = -1;
for (int i = 0; i < arr.length; i++) {
if (arr[i] == key) {
index = i;
break;
}
}
if (index != -1) System.out.println(arr[index]);
else System.out.println("没找到");
}
}
4.2 折半查找
也叫二分查找,思路是对定义两个指针分别指向被查找数组的第一个元素和最后一个元素的位置,然后再定义一个中间指针指向第一个指针加上第二个指针然后除以 2 后的位置。如果被查找的元素小于中间指针对应的元素,则在左边区域查找,如果被查找的元素大于中间指针对应元素则在右边区域查找。
要实现折半查找,被查找的数组必须有序。
/**
\* 折半查找
*/
public class BinarySearch {
public static void main(String[] args) {
int[] arr = {6, 9, 1, 5, 2, 3, 8, 4, 7};
// 排序
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j+1]) {
int tmp = arr[j+1];
arr[j+1] = arr[j];
arr[j] = tmp;
}
}
}
int key = 8; // 被查找的元素
int left = 0; // 左指针
int right = arr.length - 1; // 右指针
int middle = (left + right) / 2; // 中间指针
while (arr[middle] != key) {
if (key < arr[middle]) {
right = middle - 1;
}
if (key > arr[middle]) {
left = middle + 1;
}
if (middle > right) {
middle = -1;
break;
}
middle = (left + right) / 2;
}
System.out.println(arr[middle]);
}
}
五、二维数组
二维数组就是由行和列组成的一个表格。行和列对应的位置就是存放数组元素的位置。
二给数组的定义如下:
数组类型[][] 数组名称 = new 数组类型[行数][列数];
数组类型[][] 数组名称 = new 数组类型[][] {
{第一行的元素},
{第二行的元素},
.....
};
示例:
public class ArrayDemo01 {
public static void main(String[] args) {
int[][] arr = new int[3][3];
arr[0][0] = 1;
arr[0][1] = 2;
arr[0][2] = 3;
arr[1][0] = 3;
arr[1][1] = 4;
arr[1][2] = 5;
for (int[] ints : arr) { // 遍历行
for (int e : ints) { // 遍历列
System.out.print(e + "\t");
}
System.out.println();
}
}
}
public class ArrayDemo02 {
public static void main(String[] args) {
int[][] arr = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
for(int[] out: arr) {
for (int e : out) {
System.out.print(e + "\t");
}
System.out.println();
}
}
}
案例:八皇后问题
问题表述为:在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。如果经过±90度、±180度旋转,和对角线对称变换的摆法看成一类,共有42类。计算机发明后,有多种计算机语言可以编程解决此问题。
public class EightQueen {
public static int count = 8;
public static int n = 8;
public static void main(String[] args) {
int[][] board = new int[n][n];
eightQueen(board, 0);
}
private static void eightQueen(int[][] board, int level) {
if (level == n) {
count++;
System.out.printf("这是第%d个解:\n", count);
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[i].length; j++) {
System.out.println(board[i][j] + " ");
}
System.out.println();
}
} else {
int[][] newBoard = new int[n][n];
for (int i = 0; i < newBoard.length; i++) {
for (int j = 0; j < newBoard[i].length; j++) {
newBoard[i][j] = board[i][j];
}
}
for (int col = 0; col < n; col++) {
if (isNoDanger(newBoard, level, col)) {
for (int c = 0; c < n; c++) {
newBoard[level][c] = 0;
}
newBoard[level][col] = 1;
eightQueen(newBoard, level + 1);
}
}
}
}
private static boolean isNoDanger(int[][] board, int x, int y) {
for (int r = x - 1; r >= 0; r--) {
if (board[r][y] == 0) {
return false;
}
}
for (int r = x - 1,c=y-1; r >= 0 && c >= 0; r--,c--) {
if (board[r][c] == 1) {
return false;
}
}
for (int r = x - 1, c = y + 1; r >= 0 && c < n; r--, c++) {
if (board[r][c] == 1) {
return false;
}
}
return true;
}
}