1、为什么定义数组要采用type[] arrayName;这种方式?
因为这种方式具有很好的可读性,使用这种方式很容易就可以理解这是定义一个变量,其中变量名是arrayName,变量的类型是type[]。
2、定义数组是为什么不可以指定数组的长度?
我们知道数组是一种引用类型的变量,因此使用它来定义一个变量时,仅仅表示定义了一个引用变量(也就是定义了一个指针),这个引用变量还未指向任何有效内存,因此定义数组时不能指定数组的长度。
因为定义数组只是定义了一个引用变量,并未指向任何有效的内存空间,所以还没有内存空间来存储数组元素,因此这个数组也不能使用,只有对数组进行初始化之后才可以使用。
Arrays:针对数组进行操作的工具类。属于util包。没有构造方法。但是这个类的方法都是静态方法,可以通过类直接调用
public static String toString(T[] a):把数组转换成字符串
public static void sort(T[] a):对数组进行排序(底层是快速排序)
public static int binarySearch(T[] a,Tkey):二分查找
public class ArrayDemo {
public static void main(String[] args) {
int[] arr = {24,69,80,57,13};
System.out.println(Arrays.toString(arr)); //[24, 69, 80, 57, 13]
System.out.println(Arrays.binarySearch(arr, 57)); //-2(为什么呢?看后面的源码找答案)
Arrays.sort(arr);
System.out.println(Arrays.toString(arr)); //[13, 24, 57, 69, 80]
System.out.println(Arrays.binarySearch(arr, 57)); //2
}
}
为了更加深刻的了解这些方法的原理,下面贴出源码以供理解:
这个是toString的源码:只要是对象,我们在使用之前都要判断是不是null,以防出现空指针异常
public static String toString(int[] a) {
if (a == null)
return "null";
int iMax = a.length - 1;
if (iMax == -1)
return "[]";
StringBuilder b = new StringBuilder();
b.append('[');
for (int i = 0; ; i++) {
b.append(a[i]);
if (i == iMax)
return b.append(']').toString();
b.append(", ");
}
}
binarySearch的源码:
public static int binarySearch(int[] a, int key) {
return binarySearch0(a, 0, a.length, key);
}
private static int binarySearch0(int[] a, int fromIndex, int toIndex, int key) {
int low = fromIndex;
int high = toIndex - 1;
while (low <= high) {
int mid = (low + high) >>> 1;
int midVal = a[mid];
if (midVal < key)
low = mid + 1;
else if (midVal > key)
high = mid - 1;
else
return mid; // key found
}
return -(low + 1); // key not found.
}
冒泡排序
1、相邻元素两两比较,大的往后面放。
2、第一次排序完毕后,最大值就出现在了最大索引处。
3、第二次排序,最后一个索引的位置就不需要比较了
4、第三次排序,倒数第二个索引位置就不需要比较了
用i来表示比较的次数。每一次都会从索引为0的位置开始向后比较。
第一轮:i = 1,j 的范围是第一个到最后一个,所以j的索引范围是[0,arr.length-1](arr.length-1是数组最后一个位置的索引,看成一个整体)
第一轮之后,会确定一个最大值。因此第二轮比较的时候就不用去比较这个最大值了。
第二轮:i = 2,因为第一轮已经确定了一个最大值,有1个元素不会参与比较。因此第二轮 j 的索引范围变成了[0,(arr.length-1)-1]
第二轮比较之后,会确定两个应该在数组末尾的两个值。第三轮就不用去比较这两个值了。
第三轮:i = 3,因为第二轮已经确定了两个大值了,有2个元素不会参与比较。因此第三轮 j 的索引范围变成了[0,(arr.length-1)-2]
……..
依次类推:第 i 次 j 的索引范围应该是:[0,(arr.length-1)-(i-1)]
代码如下:
public class BubbuleDemo {
public static void main(String[] args) {
int[] arr = { 24, 69, 80, 57, 13 };
bubbleSort(arr);
}
// 冒泡排序
public static void bubbleSort(int[] arr) {
for (int i = 1; i <= arr.length - 1; i++) { // 控制比较的次数。次数 = 数组长度-1
for (int j = 0; j < (arr.length - 1) - (i - 1); 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] + " ");
}
}
}
选择排序
1、从索引为0的地方开始,依次和后面的比较,小的往前放
2、第一次比较从0索引开始往后比较。第一次比较完毕后,最小的元素就出现在了第一个位置上。
3、第二次比较的时候就不比较第一个元素了,就会从第二个元素开始比较。也就是第二次比较从1索引开始比较。
第二次比较完毕后,第二小的就出现在了第二个位置上。
4、第三次比较的时候就不比较前两个元素了,就会从第三个元素开始比较.也就是第三次比较从2索引开始比较。
…….
第 n 比较的时候就不比较前(n-1)个元素了,会从第n个元素开始比较。也就是第n次比较从(n-1)索引开始比较。
public class SelectSort {
public static void main(String[] args) {
int[] arr = { 24, 69, 80, 57, 13 };
selectSort(arr);
}
public static void selectSort(int[] arr) {
for (int i = 0; i <= (arr.length - 2); i++) { //已经确认好的值的个数,比如:确定了0个人,就从0索引开始依次跟后面的比较
for (int j = i + 1; j <= (arr.length - 1); j++) {
if (arr[i] > arr[j]) {
int temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
}
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " "); //13 24 57 69 80
}
}
}
二分查找(折半查找算法):数组元素有序的情况下
1、每次都去找中间的那个元素,跟要查找的元素比较,
2、如果中间元素的值 > 要查找的值,就在左半部分找
3、如果中间元素的值 < 要查找的值,就在右半部分找
注意:只有有序数组才可以使用这个方法。不可以对无序数组采用二分查找,不可以先排序再二分查找,因为你的数组元素都变了,你查找的索引已经不再是原始数组的索引了。
public class BinarySearch {
public static void main(String[] args) {
int[] arr = { 11, 23, 34, 46, 57, 68, 79, 80 };
System.out.println(binarySearch(arr, 57)); //4
}
//二分查找
public static int binarySearch(int[] arr, int value) {
int min = 0;
int max = arr.length - 1;
int mid = (max + min) / 2;
while (min <= max) {
if (arr[mid] > value) {
max = mid - 1;
} else if (arr[mid] < value) {
min = mid + 1;
}else{
return mid;
}
mid = (max + min) / 2;
}
return -1; //找不到的情况
}
}