数组算法
选择排序
int[] arr={6,2,8,0,1,9};
for (int i = 0; i < arr.length-1; i++)
{
for(int j=i+1;j<arr.length-1;j++)
{
if(arr[i]>arr[j])
{
int temp=0;
temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
}
/*
将第一个元素与后面的元素依次比较,如果这个元素大于后面的元素,换位
第一次循环结束,最小值出现在了0角标位
我们再将第二个元素与后面元素依次比较,如果这个元素大于后面的元素,换位
第二次循环结束,第二小的值出现在了1角标位
......
就这样依次比较,最终将数组中的元素从小到大排序
此处i<arr.length-1是因为当遍历最后一个元素时,不需要进行比较了,该元素就是最大值。
哪怕此处循环条件为i<arr.length,i=arr.length-1时,j=arr.length,内循环也无法执行循环体
*/
冒泡排序
int[] arr={6,2,8,0,1,9};
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=0;
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
/*
将两个相邻元素进行比较,如果前一元素比后一元素大,换位
第一次循环
将第一个元素与第二个元素进行比较,第一个元素大于第二个元素,进行换位
将第二个元素与第三个元素进行比较,第二个元素大于第三个元素,进行换位
将第三个元素与第四个元素进行比较,第三个元素大于第四个元素,进行换位
......
当第一次循环结束后,最大值出现在了最后
第二次循环依旧从第一个元素开始,但是只遍历到arr[arr.lenfgth-2],
即最后一个元素不遍历,次数第二大的元素在倒数第二个角标位上
第三次循环时,最后两个元素不遍历
......
就这样不断循环,每次将最大值放在遍历到的最后一个角标位上,每次少遍历一个角标位
将数组从小到大进行排序
j<arr.length-i-1的目的就是为了控制让每次循环少遍历一个元素。
*/
//在实际开发中我们会使用Java给我提供的排序方法,但这种排序思想还是要掌握
/*
使用Java提供的排序方法的步骤
1.导包
import java.util.*;
2.调用方法
Arrays.sort(arr);
*/
插入排序
每次拿后面的元素,插入到之前的一个有序序列中,使之仍保持有序
比如数组{2,6,3,1,8}
- {2},6,3,1,8 将6插入{2}这个有序数列
- {2,6},3,1,8 将3插入{2,6}这个有序数列
- {2,3,6},1,8 将1插入{2,3,6}这个有序数列
- {1,2,3,6},8 将8插入{1,2,3,6}这个有序数列
- 最终数组为:{1,2,3,6,8}
代码实现:
import java.util.Arrays;
public class InsertSort {
public static void insertSort(int[] arr)
{
//外循环的循环次数代表从索引为1处遍历数组,将数组中的元素加入有序数组。
for (int i = 1; i < arr.length - 1; i++) {
/*
j=i代表从有序数组的最后一个元素开始遍历,直到第一个元素
j>0是为了防止数组越界
将数组中要插入的元素与有序序列的最后一个元素开始依次进行比较,
如果小于有序序列的元素,就换位。如果不小于,结束内循环。
*/
for (j=i;j>0&&arr[j]<arr[j-1];j--)
{
int temp=arr[j];
arr[j]=arr[j-1];
arr[j-1]=temp;
}
}
}
public static void main(String[] args) {
int[] arr={2,6,3,1,8};
insertSort(arr);
System.out.println(Arrays.toString(arr));
}
}
快速排序
- 从数组中选出一个数作为基准数
- 分区:将数组中大于或等于基准数的数放在基准数右边,将数组中小于基准数的数放在基准数的左边
- 再对左右区间重复第二步,直到各区间只有一个数
分区实现思路:挖坑填数
- 将基准数挖出形成第一个坑,标记第一个数为开始位,最后一个数为结束位
- 由后向前找比他小的数,找到后挖出此数填到前一个坑中,将此数前面的数标记为结束位
- 由前向后找比他大的数,找到后也挖出次数填到前一个坑中,将此数后面的数标记为开始位
- 重复执行2,3步骤,直到结束位小于或等于开始位为止
代码实现:
import java.util.Arrays;
public class QuickSort {
public static void quickSort(int[] arr,int start,int end)
{
if(start<end)
{
//分组的索引
int index=getIndex(arr,start,end);
//递归调用
//对左区进行分组
quickSort(arr,start,index-1);
//对右区进行分组
quickSort(arr,index+1,end);
}
}
private static int getIndex(int[] arr, int start, int end) {
int i=start;
int j=end;
//用temp记录基准数
int temp=arr[i];
while(i<j)
{
//由后向前遍历,直到出现小于基准数的元素
while(i<j&&arr[j]>=temp)
{
j--;
}
//将找到的数填到上一个坑中
if(i<j)
{
arr[i]=arr[j];
//将i自增1是为了跳过遍历已经被遍历过的数
i++;
}
//由前向后遍历,直到出现大于基准数的元素
while(i<j&&arr[i]<temp)
{
i++;
}
//将找到的数填到上一个坑中
if(i<j)
{
arr[j]=arr[i];
//将j自减1是为了跳过遍历已经被遍历过的数
j--;
}
}
//当i和j相等时,代表开始标志位和结束标志位重合,遍历结束
//此时将基准数填到最后一个坑中
arr[i]=temp;
//此时i和j相等,分组已经完成,返回基准数所在的索引,对左右区进行递归,分组直至左右区只有一个元素位置
return i;
}
public static void main(String[] args) {
int[] arr={3,1,6,3,7};
quickSort(arr,0,arr.length-1);
System.out.println(Arrays.toString(arr));
}
}
二分查找
我们介绍一种更加高效的查找方式,二分查找
举个例子,如果在1~100之间指定一个数字,你来猜,猜出数字后,会提示你你猜的这个数大了还是小了。
最快的方式就是猜中间值,这样可以最快的缩小范围,进而最快的找到这个数。
而折半查找用的就是这种思想
先比较中间元素与目标值(key)的大小关系,然后一步步缩小范围,最后确定目标值在数组中的位置
import java.util.Arrays;
public class BinarySearch {
public static int binarySearch(int[] arr,int key)
{
int max=arr.length-1;
int min=0;
int mid=(min+max)/2;
//因为我们不知道max何时小于min,即不知道具体的循环次数,所以使用while循环
while(max>=min)
{
//如果目标数等于中间元素,代表直接找到目标数索引
if(key==arr[mid])
{
return mid;
}
else if(key>arr[mid])
min=mid+1;
else
max=mid-1;
mid=(min+max)/2;
}
return -1;
}
public static void main(String[] args) {
int[] arr={1,2,3,4,5,6};
int index=binarySearch(arr,4);
System.out.println(index);
}
}
/*
首先我们要判断key是否与arr[mid]相等,如果相等就找到了目标元素的角标,直接跳出循环
如果不相等,判断key与arr[mid]的大小关系
如果,key>arr[mid],说明猜的值小了,就要把下限提高,我们key已经和arr[mid]比较过了,所以下限变为mid+1
如果,key<arr[mid],说明猜的值大了,就要把上限降低,所以下限变成max-1
当范围发生改变后,要改变mid的值,不然就是死循环,然后再次循环比较,知道找到目标值的角标
当min>max时,代表数组中不存在目标值,循环结束
*/
//折半查找还有第二种表现方式
while(key!=arr[mid])
{
if(key>arr[mid])
min=mid+1;
else
max=mid-1;
mid=(min+max)/2;
if(min<max)
break;
}
/*
我们把key!=arr[mid]作为控制循环体的条件
如果min小于max,说明目标值在数组中不存在,直接跳出循环。
*/
//注意:折半查找只适用于有顺序的数组,不适合乱序的数组!!
Arrays类
概述
针对数组进行操作的工具类。
提供了排序,查找等功能。
使用Arrays类是要导入java.util.Arrays包
方法
public static String toString(int[] a)
返回指定数组的内容的字符串表示形式。
传入的对象也可以是其他类型的数组
public class Demo {
public static void main(String[] args) {
int[] arr={1,2,4,2,4,5};
char[] ch={'d','3','a','g'};
System.out.println(Arrays.toString(arr));
System.out.println(Arrays.toString(ch));
}
}
/*
运行结果:
[1, 2, 4, 2, 4, 5]
[d, 3, a, g]
*/
public static void sort(int[] a)
按照数字顺序排列指定的数组。
public static void sort(int[] a, int fromIndex, int toIndex)
按升序排列数组的指定范围。
传入的对象也可以是其他类型的数组
public class Demo {
public static void main(String[] args) {
int[] arr={1,2,4,2,4,5};
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
}
}
/*
运行结果:
[1, 2, 2, 4, 4, 5]
*/
public class Demo {
public static void main(String[] args) {
int[] arr={1,2,4,2,4,5};
Arrays.sort(arr,3,6);
System.out.println(Arrays.toString(arr));
}
}
/*
运行结果:
[1, 2, 4, 2, 4, 5]
*/
public static int binarySearch(int[] a,int key)
使用二分搜索算法搜索指定的int数组的指定值。
传入的对象也可以是其他类型的数组
int[] arr={1,2,3,4,5,6};
int index=binarySearch(arr,4);
static boolean equals(int[] a, int[] a2)
比较两个数组中的元素,是否一样
public class Demo4 {
public static void main(String[] args) {
int[] arr1={1,2,3,4};
int[] arr2={1,2,3,4};
boolean b=Arrays.equals(arr1,arr2);
System.out.println(b);
}
}
/*
运行结果:
true
*/
public static int[] copyOf(int[] original, int newLength)
复制源数组中的元素到一个新的数组中,新的数组长度是newLength 从0开始复制旧数组
public static int[] copyOfRange(int[] original, int from, int to)
复制源数组中的指定范围间的几个元素到新数组中
public class Demo4 {
public static void main(String[] args) {
int[] arr={1,2,3,4,5,6,7};
int[] arr1=Arrays.copyOf(arr,3);
int[] arr2=Arrays.copyOfRange(arr,3,6);
System.out.println(Arrays.toString(arr1));
System.out.println(Arrays.toString(arr2));
}
}
/*
运行结果:
[1, 2, 3]
[4, 5, 6]
*/