目录
方法一:调用Arrays工具类的sort()方法对数组进行排序
方法一:通过使用Arrays工具类的binarySearch()方法
1,数组排序
方法一:调用Arrays工具类的sort()方法对数组进行排序
public static void main(String[] args) {
//定义一个无序的数组
int[] arr01= {1,2,3,18,4,8,6,48,58,6413,14,15,16,17};
System.out.println(Arrays.toString(arr01));
//排序前
//用sort()方法对数组进行排序
Arrays.sort(arr01);
//排序后的数组
System.out.println(Arrays.toString(arr01));
}
方法二:冒泡排序
冒泡排序私对一个数组进行从小到大的排序。
步骤:
1、比较相邻的元素,如果第一个比第二个大,就交换位置。
2、对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
3、针对所有的元素重复以上的步骤,除了最后一个元素。
特点:每一轮循环后,最大的一个数被交换到末尾,因此,下一轮循环就可以“排除”最后的数,每一轮循环都比上一轮循环的结束位置靠前一位。
注意:
N个数字来排序
俩俩比较小靠前
总共比较N-1轮
每轮比较N-1-i次
public static void main(String[] args) {
//无序数组
int[] arr01= {1,2,3,18,4,8,6,48,58,6413,14,15,16,17};
// System.out.println("交换前:"+Arrays.toString(arr01));
//使用异或运算符交换交换数组中相邻元素之间的位置(异或运算符交换位置只能是整型,字符型可以使用但是需要强制类型转换为整型,浮点型和字符串不可以)
// arr01[1]=arr01[1]^arr01[2];
// arr01[2]=arr01[1]^arr01[2];
// arr01[1]=arr01[1]^arr01[2];
// System.out.println("交换后"+Arrays.toString(arr01));
//对整个数组进行冒泡排序
//比较的轮数为:n-1(n为数组的个数
for (int i = 0; i <arr01.length-1; i++) {
//每轮比较的次数为n-i(n为数组的个数)(i为比较的轮数)
for (int j =0; j < arr01.length-1-i; j++) {
//比较
if(arr01[j]>arr01[j+1]) {
arr01[j]=arr01[j]^arr01[j+1];
arr01[j+1]=arr01[j]^arr01[j+1];
arr01[j]=arr01[j]^arr01[j+1]; ;
}
System.out.printf("第%d次交换后的%s\n",j+1,Arrays.toString(arr01));
}
}
优化后代码:每进行一次排序,都判断一下数组是否已经有序,如果有序则不用在进行排序。
public static void main(String[] args) {
//无序数组
int[] arr01= {1,2,3,18,4,8,6,48,58,6413,14,15,16,17};
// System.out.println("交换前:"+Arrays.toString(arr01));
// //使用异或运算符交换交换数组中相邻元素之间的位置(异或运算符交换位置只能是整型,字符型可以使用但是需要强制类型转换为整型,浮点型和字符串不可以)
// arr01[1]=arr01[1]^arr01[2];
// arr01[2]=arr01[1]^arr01[2];
// arr01[1]=arr01[1]^arr01[2];
// System.out.println("交换后"+Arrays.toString(arr01));
//对整个数组进行冒泡排序
//比较的轮数为:n-1(n为数组的个数)
int counter=0;
for (int i = 0; i <arr01.length-1; i++) {
//每轮比较的次数为n-i(n为数组的个数)(i为比较的轮数)
//设置一个变量来判断数组是否有序
//true为有序
//false为无序
boolean isSort=true;
for (int j =0; j < arr01.length-1-i; j++) {
//比较
counter++;
if(arr01[j]>arr01[j+1]) {
arr01[j]=arr01[j]^arr01[j+1];
arr01[j+1]=arr01[j]^arr01[j+1];
arr01[j]=arr01[j]^arr01[j+1];
isSort=false;
}
System.out.printf("第%d次交换后的%s\n",j+1,Arrays.toString(arr01));
}
if(isSort==true) {
break;
}
System.err.printf("第%d轮交换后的%s\n",i+1,Arrays.toString(arr01));
}
System.out.println("总共比较了"+counter+"次");
}
2,数组查找
方法一:通过使用Arrays工具类的binarySearch()方法
(注意:进行查找的数组必须是有序数组)
如果数组无序,首先需要对数组进行排序操作
public static void main(String[] args) {
int[] arr01= {1,2,3,18,6,4,8,2,6,48,58,6413,14,15,16,17};
int target=14;
//快速排序
Arrays.sort(arr01);
System.out.println(Arrays.toString(arr01));
//基于二分查找的数组必须有序
int index=Arrays.binarySearch(arr01,target);
System.out.println(index);
}
方法二:二分查找(进行二分查找的数组必须是有序的)
二分查找算法思想:
1,判断搜索数组的“中位元素”与要查找的“目标元素”是否相等。
如果相等,代表查找成功,退出算法;
如果不相等,继续比较“中位元素”与要查找的“目标元素”的大小关系;
如果“中位元素”大于“目标元素”,当前数组的前半部分作为新的搜索数组,因为后半部分的所有元素都大于“目标元素”,它们全都被排除了。
如果“中位元素”小于“目标元素”,当前数组的后半部分作为新的搜索数组,因为前半部分的所有元素都小于“目标元素”,它们全都被排除了。
2、在新的搜索数组上,重新开始第1步的工作。
public static void main(String[] args) {
try(Scanner scanner=new Scanner(System.in)){
int [] arr01= {12,5,8,4,56,8,484,848,495,95,84,85,9};
System.out.println("请输入目标元素:");
int target=scanner.nextInt();
//定义首尾下标
int low=0,high=arr01.length-1,index=-1;
while (low<=high) {
int mid=(low+high)/2;//中间元素的下标
if (arr01[mid]==target) {
index=mid;
break;
}else if (arr01[mid]<target) {//目标元素在中间元素的后边,将high向中间元素的前边移动
low=mid+1;
}else if (arr01[mid]>target) {//目标元素在中间元素的前边,将low向中间元素的后边移动
high=mid-1;
}
}
System.out.println("目标元素是"+arr01[index]+"目标元素的下标"+index);
}
}
方法三:双指针查找
通过两个下标,分别从数组头部和尾部,同时对该无序数组进行遍历,将数组中的每个元素与指定元素进行比较,从而确定该数组中是否存在指定元素。
public static void main(String[] args) {
int [] arr01= {12,5,8,4,56,8,484,848,495,95,84,85,9};
System.out.println("请输入目标元素:");
int target=484;
//从两头同时开始向中间查找
for (int i = 0,k=arr01.length-1; i <= k; i++,k--) {
//从头开始查找
if (arr01[i]==target) {
System.out.println("目标元素出现的位置是:"+i);
break;
}
//从尾开始查找
if (arr01[k]==target) {
System.out.println("目标元素出现的位置是:"+k);
break;
}
}
}
方法四:遍历查找
可以通过对该数组进行遍历,将数组中的每个元素与指定元素进行比较,从而确定该数组中是否存在指定元素。
public static void main(String[] args) {
String[] arr1= {"张三","李四","王五","李明"};
String targetString="张三";
int index=-1;
for (int i = 0; i < arr1.length; i++) {
if (arr1[i].equals(targetString)) {
index=i;
break;
}
}
if(index>=0) {
System.out.println(targetString+"已找到");
}else {
System.out.println(targetString+"未找到");
}
}
3,数组乱序
数组乱序,也被称为数组洗牌,实现算法中有一个非常著名的洗牌算法Fisher-Yates算法,是由 Ronald A.Fisher和Frank Yates于1938年发明的,后来被Knuth在自己的著作《The Art of Computer Programming》中介绍,很多人直接称Knuth洗牌算法。
实现步骤:
1,假设有一组需要乱序的数组arr。
2,从arr中随机选取一个未乱序的元素。
3,将该元素与数组arr中最后一个未乱序的元素交换。
4,重复2-3的步骤,直到数组arr中元素全部完成乱序。
public static void main(String[] args) {
int[] arr= {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17};
System.out.println(Arrays.toString(arr));
int count=0;
for (int i = arr.length-1; i>0 ; i--) {
int index=(int)(Math.random()*i);
arr[index]=arr[index]^arr[i];
arr[i]=arr[index]^arr[i];
arr[index]=arr[index]^arr[i];
count++;
System.out.printf("第"+count+"次交换完成后的数组"+Arrays.toString(arr));
System.out.println("交换的两个元素的下标是"+i+":"+index);
}
System.out.println("最终交换完成后的数组"+Arrays.toString(arr));
}
4,数组旋转
向左旋转:(顺序旋转)
将头元素和他后边的元素交换位置
public static void main(String[] args) {
int[] arr2= {1,2,3,4,5,6,7,8,9};
System.out.println("原数组为:"+Arrays.toString(arr));
//向左旋转(顺序旋转)将头元素和他后边的元素交换位置
for (int i = 0; i < 2; i++) {
//从头一个元素和他的后一个元素交换
//顺序旋转(向右交换)
for (int k = 0; k < arr2.length-1; k++) {
arr2[k]=arr2[k]^arr2[k+1];
arr2[k+1]=arr2[k]^arr2[k+1];
arr2[k]=arr2[k]^arr2[k+1];
}
}
System.out.println("向左旋转2次后的数组为:"+Arrays.toString(arr2));
}
向右旋转:(逆序旋转)
尾元素后他的前一个元素交换位置
public static void main(String[] args) {
int[] arr= {1,2,3,4,5,6,7,8,9};
int[] arr2= {1,2,3,4,5,6,7,8,9};
System.out.println("原数组为:"+Arrays.toString(arr));
//向右旋转 (逆序旋转)尾元素后他的前一个元素交换位置
//外层循环决定循环的位数和旋转的次数、旋转3次
for (int i = 0; i < 3; i++) {
//交换的次数,每次向右旋转(移动)1次
//从最后一个元素和他的前一个元素交换
//交换的顺序(逆序旋转)(向左交换)
for (int k = arr.length-1; k >0; k--) {
arr[k]=arr[k]^arr[k-1];
arr[k-1]=arr[k]^arr[k-1];
arr[k]=arr[k]^arr[k-1];
}
}
System.out.println("向右旋转3次后的数组为:"+Arrays.toString(arr));
}