目录
01 数组元素基本操作
package Matrix;
/*
定义一个int 型的一维数组,包含 10 个元素,分别赋一些随机整数,
然后求出所有元素的最大值, 最小值,和值, 平均值, 并输出 出来 。
要求:所有随机数都是两位数。
*/
public class ArrayTest3 {
public static void main(String[] args){
int[] arr = new int[10];
int maxNum = 0;
int minNum = 100;
int sum = 0;
int averNum = 0;
for(int i = 0; i < arr.length; i++){
// 赋值
arr[i] = (int)(Math.random() * 90 + 10);
sum += arr[i];
if(maxNum < arr[i]){
maxNum = arr[i];
}
if(minNum > arr[i]){
minNum = arr[i];
}
System.out.println(arr[i] + " ");
}
averNum = sum / 10;
System.out.println("最大值为" + maxNum);
System.out.println("最小值为" + minNum);
System.out.println("平均值为" + averNum);
System.out.println("和值为" + sum);
}
}
02 数组的复制
数组赋值
- 直接相等,是赋值地址,会同时改变
/*
创建一个 名为 ArrayTest 的 类,在 main() 方法中声明 array1 和 array2 两 个 变量,
他们 是 int 类型的数组。
使用大括号 {}{},把 array1 初始化为 8 个素数: 2,3,5,7,11,13,17,19 。
显示 array1 的内容。
赋值 array2 变量等于 array1 ,修改 array2 中的偶索引元素,使其等于索引值
如 array[0]=0,array[2]=2) 。打印出 array1
*/
public class FuZhiArray {
public static void main(String[] args){
int[] array1 = new int[]{2,3,5,7,11,13,17,19};
int[] array2; // 这里来初始化不能用new 否则后面无法编译
for (int i = 0; i < array1.length; i++) {
System.out.print(array1[i] + "\t");
}
System.out.println();
// 赋值arr2 = arr1
array2 = array1;
for (int i = 0; i < array2.length; i++){
if (i % 2 == 0){
array2[i] = i;
}
System.out.print(array1[i] + "\t");
}
}
}
实现数组的复制
// 复制arr2 = arr1
int[] array2 = new int[array1.length];
for (int i = 0; i < array2.length; i++){
array2[i] = array1[i];
03 数组的反转
public class FuZhiArray {
public static void main(String[] args){
int[] array1 = new int[]{2,3,5,7,11,13,17,19};
for (int i = 0; i < array1.length; i++) {
System.out.print(array1[i] + "\t");
}
System.out.println();
// 数组反转方法一
// for (int i = 0; i < array1.length / 2; i++){
// int temp = array1[i];
// array1[i] = array1[array1.length-i-1];
// array1[array1.length - i - 1] = temp;
// }
// 方法二
for( int i = 0, j= array1.length-1; i < j; i++,j--){
int temp = array1[i];
array1[i] = array1[j];
array1[j] = temp;
}
for (int i = 0; i < array1.length; i++) {
System.out.print(array1[i] + "\t");
}
}
}
04 数组的查找
4.1 线性查找
public class FuZhiArray {
public static void main(String[] args){
int[] array1 = new int[]{2,3,5,7,11,13,17,19};
for (int i = 0; i < array1.length; i++) {
System.out.print(array1[i] + "\t");
}
System.out.println();
// 查找
int num = 5; // 设置要找的数
boolean flag = true; // 如果没找到的标识符
for(int i= 0; i < array1.length; i++){
if(num == array1[i]){
System.out.println("找到了");
flag = false;
break;
}
}
if(flag){ // 没改过,说明没找到
System.out.println("没找到");
}
}
}
4.2 二分查找
public class FuZhiArray {
public static void main(String[] args){
int[] array1 = new int[]{2,3,5,7,11,13,17,19};
for (int i = 0; i < array1.length; i++) {
System.out.print(array1[i] + "\t");
}
System.out.println();
// 二分查找: 所查找的数组必须有序
int[] array2 = new int[]{-2,3,5,7,11,13,17,109};
int num2 = 5;
int head = 0; // 初始索引
int end = array2.length -1; // 末索引
boolean isFlag = true; //如果没找到的标识符
while(head <= end){
int middle = (head + end) / 2;
if (num2 == array2[middle]){
System.out.println("所查找数值的索引为" + middle);
isFlag = false;
break;
}else if(num2 > array2[middle]){
head = middle + 1;
}else{
end = middle - 1;
}
}
if(isFlag){
System.out.println("没找到");
}
}
}
05 排序算法
5.1 概述
- 排序:假设含有 n 个记录的序列为{R1,R2,…,Rn},其相应的关键字序列为{K1 ,K2,…,Kn}。将这些记录重新排序为{Ri1,Ri2,…,Rin},使得相应的关键字值满足条 Ki1<=Ki2<=…<=Kin,这样的一种操作称为排序。
- 通常来说,排序的目的是快速查找。
衡量排序算法的优劣:
- 时间复杂度:分析关键字的比较次数和记录的移动次数
- 空间复杂度:分析排序算法中需要多少辅助内存
- 稳定性:若两个记录 A 和 B 的关键字值相等,但排序后 A、B 的先后次序保持不变,则称这种排序算法是稳定的。
排序算法分类:内部排序和外部排序。
- 内部排序:整个排序过程不需要借助于外部存储器(如磁盘等),所有排序操作都在内存中完成。
- 外部排序:参与排序的数据非常多,数据量非常大,计算机无法把整个排序过程放在内存中完成,必须借助于外部存储器(如磁盘)。外部排序最常见的是多路归并排序。可以认为外部排序是由多次内部排序组成。
5.2 十种排序算法
- 选择排序
- 直接选择排序、堆排序
- 交换排序
- 冒泡排序、快速排序
- 插入排序
- 直接插入排序、折半插入排序、Shell 排序
- 归并排序
- 桶式排序
- 基数排序
算法特点
输入(Input) | 有 0 个或多个输入数据,这些输入必须有清楚的描述和定义 |
输出(Output) | 至少有 1 个或多个输出结果,不可以没有输出结果 |
有穷性(有限性,Finiteness) | 算法在有限的步骤之后会自动结束而不会无限循环,并且每一个步骤可以在可接受的时间内完成 |
确定性(明确性,Definiteness) | 算法中的每一步都有确定的含义,不会出现二义性 |
可行性(有效性,Effectiveness | 算法的每一步都是清楚且可行的,能让用户用纸笔计算而求出答案 |
5.2.1 冒泡排序
public class BubbleSort {
public static void main(String[] args) {
int[] arr = new int[] {1,2,-34,5,3,4,2,1,6,78,-9};
// 冒泡排序
for(int i = 0; i < arr.length - 1; i++){ // i 控制外部排序次数,每个数都要进行排序
for(int j = 0; j < arr.length - 1 - i; j++){ // j 控制欸一轮的内部排序,即将最大数排到最后一个
if(arr[j] > arr[j+1]){ // 保证索引能指到最后一个数
int temp = arr[j]; // 前面数大于后面数,则交换两个数
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
for (int i = 0; i < arr.length; i++){
System.out.print(arr[i] + " ");
}
}
}
5.2.2 快速排序
排序思想
- 从数列中挑出一个元素,称为"基准"(pivot),
- 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。(分而治之)
- 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。
快速排序 java实现
public class QuickSort {
private static void swap(int[] data, int i, int j){ // 方法的定义,交换索引为i和j两个数值
int temp = data[i];
data[i] = data[j];
data[j] = temp;
}
private static void subSort(int[] data, int start, int end){ // 定义排序方法
if(start < end){
// 定义三个指针
int base = data[start]; // 基准值
int low = start;
int high = end + 1;
while(true){
while(low < end && data[++low] <= base) // 前++ 先运算后取值
;
// 这里是一个循环,调整low指针位置,直到arr[low] > base
// 同理,调整 high指针位置,直到arr[high] < base
while(high > start && data[--high] >= base)
;
// 经过循环的调整,交换两个数值
if(low < high){ // 只有low还在 high左边时,交换数值
swap(data, low, high);
}else{ // 否则退出
break;
}
}
swap(data,start,high); // 交换基准值和high的指针值,保证基准值左侧比基准值小
subSort(data, start, high - 1); // 递归调用左侧子列
subSort(data, high + 1, end); // 递归调用右侧子列
}
}
public static void quickSort(int[] data){
subSort(data, 0, data.length - 1);
}
// 排序样例
public static void main(String[] args){
int[] data = new int[]{9, 1,2,5,7,-23,3,-5,98};
System.out.println("排序之前:" + java.util.Arrays.toString(data));
quickSort(data);
System.out.println("排序之后:" + java.util.Arrays.toString(data));
}
}
06 Arrays 工具类的使用
java.util.Arrays类即为操作数组的工具类,包含了用来操作数组(比如排序和搜索)的各种方法。
/*
操作数组工具类
boolean equals(int[] a,int[] b):判断两个数组是否相等。
String toString(int[] a) : 输出数组信息。
void fill(int[] a,int val) : 将指定值填充到数组之中。
*/
import java.util.Arrays;
/*
* java.util.Arrays:作数组的工具类,包含了用来操作数组(比如排序和搜索)的各种方法。
*/
public class ArraysTest {
public static void main(String[] args) {
//1.boolean equals(int[] a,int[] b)判断两个数组是否相等。
int[] arr1 = new int[]{1,2,3,4};
int[] arr2 = new int[]{1,2,9,3};
boolean isEquals = Arrays.equals(arr1, arr2);
System.out.println(isEquals);
//2.String toString(int[] a)输出数组信息。
System.out.println(Arrays.toString(arr1));
//3.void fill(int[] a,int val)将指定值填充到数组之中:全部替换
Arrays.fill(arr1, 10);
System.out.println(Arrays.toString(arr1));
//4.void sort(int[] a)对数组进行排序。
Arrays.sort(arr2);
System.out.println(Arrays.toString(arr2));
//5.int binarySearch(int[] a,int key)对排序后的数组进行二分法检索指定的值。
int[] arr3 = new int[]{-43,32,76,92,165,185,271,342};
int index = Arrays.binarySearch(arr3, 210);
if(index >= 0){
System.out.println(index);
}else{
System.err.println("未找到。");
}
}
}
07 数组异常
public class ArrayExceptionTest {
/*
* 数组中的常见异常:
* 1.数组角标越界的异常:ArrayIndexOutOfBoundsException
*
* 2.空指针异常:NullPointerException
*
*/
public static void main(String[] args) {
//1.数组角标越界的异常:ArrayIndexOutOfBoundsException
int[] arr = new int[]{1,2,3,4,5,6};
//错误1:
// for(int i = 0;i <= arr.length;i++){ 角标越界
// System.out.println(arr[i]);
// }
//错误2:
// System.out.println(arr[-2]);
//错误3 // 一旦出现错误,剩下程序不再执行
// System.out.println("hello");
//2.空指针异常:NullPointerException
//情况一:
// int[] arr2= new int[]{1,2,3};
// arr2 = null; // 指针地址改成空的了
// System.out.println(arr2[0]);
//情况二:
// int[][] arr2 = new int[4][];
// System.out.println(arr2[0][0]);
//情况三:
// String[] arr3 = new String[]{"AA","QQ","YY","XX","TT","KK"};
// arr3[0] = null;
// System.out.println(arr3[0].toString());
}
}
}